Merge branch 'master' into idles_talks_locomotion_improvements

This commit is contained in:
dooglifeSF 2019-06-26 09:31:23 -07:00
commit 9f8d1dd51d
396 changed files with 50355 additions and 1957 deletions
BUILD_WIN.mdCMakeLists.txt
domain-server/src
interface
launchers
libraries

View file

@ -31,7 +31,7 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo
### Step 2. Installing CMake
Download and install the latest version of CMake 3.9.
Download and install the latest version of CMake 3.14.
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.14 Version page](https://cmake.org/files/v3.14/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.

View file

@ -139,6 +139,7 @@ option(BUILD_MANUAL_TESTS "Build manual tests" ${BUILD_MANUAL_TESTS_OPTION})
option(BUILD_TOOLS "Build tools" ${BUILD_TOOLS_OPTION})
option(BUILD_INSTALLER "Build installer" ${BUILD_INSTALLER_OPTION})
option(USE_GLES "Use OpenGL ES" ${GLES_OPTION})
option(USE_KHR_ROBUSTNESS "Use KHR_robustness" OFF)
option(DISABLE_QML "Disable QML" ${DISABLE_QML_OPTION})
option(DISABLE_KTX_CACHE "Disable KTX Cache" OFF)
option(
@ -149,6 +150,10 @@ option(
set(PLATFORM_QT_GL OpenGL)
if (USE_KHR_ROBUSTNESS)
add_definitions(-DUSE_KHR_ROBUSTNESS)
endif()
if (USE_GLES)
add_definitions(-DUSE_GLES)
add_definitions(-DGPU_POINTER_STORAGE_SHARED)

View file

@ -136,7 +136,8 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessag
} else {
qDebug() << "Refusing connection from node at" << message->getSenderSockAddr()
<< "with hardware address" << nodeConnection.hardwareAddress
<< "and machine fingerprint" << nodeConnection.machineFingerprint;
<< "and machine fingerprint" << nodeConnection.machineFingerprint
<< "sysinfo" << nodeConnection.SystemInfo;
}
}

View file

@ -37,7 +37,11 @@ NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, c
dataStream >> newHeader.machineFingerprint;
// and the operating system type
dataStream >> newHeader.SystemInfo;
QByteArray compressedSystemInfo;
dataStream >> compressedSystemInfo;
if (!compressedSystemInfo.isEmpty()) {
newHeader.SystemInfo = qUncompress(compressedSystemInfo);
}
dataStream >> newHeader.connectReason;

View file

@ -53,6 +53,9 @@ Item {
StatText {
text: root.recenterText
}
StatText {
text: root.overrideJointText
}
StatText {
text: "Anim Vars:--------------------------------------------------------------------------------"
}
@ -98,6 +101,9 @@ Item {
StatText {
text: root.sittingText
}
StatText {
text: root.flowText
}
StatText {
text: "State Machines:---------------------------------------------------------------------------"
}
@ -131,6 +137,9 @@ Item {
StatText {
text: root.walkingText
}
StatText {
text: root.networkGraphText
}
StatText {
text: "Alpha Values:--------------------------------------------------------------------------"
}

View file

@ -340,10 +340,10 @@ Item {
text: "GPU: " + root.gpuFrameTime.toFixed(1) + " ms"
}
StatText {
text: "GPU (Per pixel): " + root.gpuFrameTimePerPixel.toFixed(5) + " ns/pp"
text: "GPU (Per pixel): " + root.gpuFrameTimePerPixel.toFixed(1) + " ns/pp"
}
StatText {
text: "GPU frame size: " + root.gpuFrameSize.x + " x " + root.gpuFrameSize.y
text: "GPU frame size: " + root.gpuFrameSize.x.toFixed(0) + " x " + root.gpuFrameSize.y.toFixed(0)
}
StatText {
text: "LOD Target: " + root.lodTargetFramerate + " Hz Angle: " + root.lodAngle + " deg"

View file

@ -91,7 +91,20 @@ Rectangle {
Component {
id: highlightBar
Rectangle {
width: tabListView.currentItem.width
height: tabListView.currentItem.height
color: simplifiedUI.colors.darkBackground
x: tabListView.currentItem.x
Behavior on x {
SmoothedAnimation {
duration: 250
}
}
Behavior on width {
SmoothedAnimation {
duration: 250
}
}
}
}
@ -104,6 +117,7 @@ Rectangle {
orientation: ListView.Horizontal
model: tabListModel
highlight: highlightBar
highlightFollowsCurrentItem: false
interactive: contentItem.width > width
delegate: Item {
visible: model.tabTitle !== "Dev" || (model.tabTitle === "Dev" && root.developerModeEnabled)

View file

@ -122,12 +122,22 @@ Flickable {
}
HifiStylesUit.GraphikRegular {
text: "<b>CPU:</b> " + PlatformInfo.getCPUBrand()
text: "<b>CPU:</b>"
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
Component.onCompleted: {
var cpu = JSON.parse(PlatformInfo.getCPU(0));
var cpuModel = cpu.model;
if (cpuModel.length === 0) {
cpuModel = "Unknown";
}
text = "<b>CPU:</b> " + cpuModel;
}
}
HifiStylesUit.GraphikRegular {
@ -158,12 +168,22 @@ Flickable {
}
HifiStylesUit.GraphikRegular {
text: "<b>GPU:</b> " + PlatformInfo.getGraphicsCardType()
text: "<b>GPU:</b> "
Layout.maximumWidth: parent.width
height: paintedHeight
size: 16
color: simplifiedUI.colors.text.white
wrapMode: Text.Wrap
Component.onCompleted: {
var gpu = JSON.parse(PlatformInfo.getGPU(0));
var gpuModel = gpu.model;
if (gpuModel.length === 0) {
gpuModel = "Unknown";
}
text = "<b>GPU:</b> " + gpuModel;
}
}
HifiStylesUit.GraphikRegular {
@ -180,9 +200,11 @@ Flickable {
width: 200
height: 32
text: "Copy to Clipboard"
temporaryText: "Copied!"
onClicked: {
Window.copyToClipboard(root.buildPlatformInfoTextToCopy());
showTemporaryText();
}
}
}
@ -206,12 +228,29 @@ Flickable {
textToCopy += "Computer Vendor/Model: " + computerVendor + "/" + computerModel + "\n";
textToCopy += "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + "\n";
textToCopy += "OS Type: " + PlatformInfo.getOperatingSystemType() + "\n";
textToCopy += "CPU: " + PlatformInfo.getCPUBrand() + "\n";
var cpu = JSON.parse(PlatformInfo.getCPU(0));
var cpuModel = cpu.model;
if (cpuModel.length === 0) {
cpuModel = "Unknown";
}
textToCopy += "CPU: " + cpuModel + "\n";
textToCopy += "# CPUs: " + PlatformInfo.getNumCPUs() + "\n";
textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n";
textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n";
textToCopy += "GPU: " + PlatformInfo.getGraphicsCardType() + "\n";
textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None"));
var gpu = JSON.parse(PlatformInfo.getGPU(0));
var gpuModel = gpu.model;
if (gpuModel.length === 0) {
gpuModel = "Unknown";
}
textToCopy += "GPU: " + gpuModel + "\n";
textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")) + "\n";
textToCopy += "\n**All Platform Info**\n";
textToCopy += JSON.stringify(JSON.parse(PlatformInfo.getPlatform()), null, 4);
return textToCopy;
}

View file

@ -16,6 +16,9 @@ import TabletScriptingInterface 1.0
Original.Button {
id: root
// The two properties below are used when calling showTemporaryText()
property string originalText: ""
property string temporaryText: ""
SimplifiedConstants.SimplifiedConstants {
id: simplifiedUI
@ -103,4 +106,31 @@ Original.Button {
horizontalAlignment: Text.AlignHCenter
text: root.text
}
Timer {
id: showTemporaryTextTimer
interval: 1500
repeat: false
running: false
onTriggered: {
buttonText.text = root.originalText;
root.originalText = "";
}
}
function showTemporaryText() {
if (root.temporaryText === "") {
return;
}
if (showTemporaryTextTimer.running) {
showTemporaryTextTimer.restart();
return;
}
root.originalText = buttonText.text;
buttonText.text = root.temporaryText;
showTemporaryTextTimer.start();
}
}

View file

@ -2775,7 +2775,6 @@ void Application::cleanupBeforeQuit() {
// destroy Audio so it and its threads have a chance to go down safely
// this must happen after QML, as there are unexplained audio crashes originating in qtwebengine
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "stop");
DependencyManager::destroy<AudioClient>();
DependencyManager::destroy<AudioScriptingInterface>();
@ -2935,8 +2934,10 @@ void Application::initializeGL() {
#if !defined(DISABLE_QML)
QStringList chromiumFlags;
// HACK: re-expose mic and camera to prevent crash on domain-change in chromium's media::FakeAudioInputStream::ReadAudioFromSource()
// Bug 21993: disable microphone and camera input
chromiumFlags << "--use-fake-device-for-media-stream";
//chromiumFlags << "--use-fake-device-for-media-stream";
// Disable signed distance field font rendering on ATI/AMD GPUs, due to
// https://highfidelity.manuscript.com/f/cases/13677/Text-showing-up-white-on-Marketplace-app
std::string vendor{ (const char*)glGetString(GL_VENDOR) };
@ -3741,18 +3742,6 @@ void Application::resizeGL() {
DependencyManager::get<FramebufferCache>()->setFrameBufferSize(fromGlm(renderSize));
}
auto renderResolutionScale = getRenderResolutionScale();
if (displayPlugin->getRenderResolutionScale() != renderResolutionScale) {
auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration();
assert(renderConfig);
auto mainView = renderConfig->getConfig("RenderMainView.RenderDeferredTask");
// mainView can be null if we're rendering in forward mode
if (mainView) {
mainView->setProperty("resolutionScale", renderResolutionScale);
}
displayPlugin->setRenderResolutionScale(renderResolutionScale);
}
// FIXME the aspect ratio for stereo displays is incorrect based on this.
float aspectRatio = displayPlugin->getRecommendedAspectRatio();
_myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio,
@ -8546,23 +8535,7 @@ void Application::shareSnapshot(const QString& path, const QUrl& href) {
}
float Application::getRenderResolutionScale() const {
auto menu = Menu::getInstance();
if (!menu) {
return 1.0f;
}
if (menu->isOptionChecked(MenuOption::RenderResolutionOne)) {
return 1.0f;
} else if (menu->isOptionChecked(MenuOption::RenderResolutionTwoThird)) {
return 0.666f;
} else if (menu->isOptionChecked(MenuOption::RenderResolutionHalf)) {
return 0.5f;
} else if (menu->isOptionChecked(MenuOption::RenderResolutionThird)) {
return 0.333f;
} else if (menu->isOptionChecked(MenuOption::RenderResolutionQuarter)) {
return 0.25f;
} else {
return 1.0f;
}
return RenderScriptingInterface::getInstance()->getViewportResolutionScale();
}
void Application::notifyPacketVersionMismatch() {

View file

@ -382,28 +382,6 @@ Menu::Menu() {
// Developer > Render > OpenVR threaded submit
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::OpenVrThreadedSubmit, 0, true);
// Developer > Render > Resolution
MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution);
QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu);
resolutionGroup->setExclusive(true);
#if defined(Q_OS_MAC)
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionOne, 0, false));
#else
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionOne, 0, true));
#endif
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionTwoThird, 0, false));
#if defined(Q_OS_MAC)
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionHalf, 0, true));
#else
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionHalf, 0, false));
#endif
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionThird, 0, false));
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionQuarter, 0, false));
//const QString = "Automatic Texture Memory";
//const QString = "64 MB";
//const QString = "256 MB";

View file

@ -168,12 +168,6 @@ namespace MenuOption {
const QString RenderMaxTexture4096MB = "4096 MB";
const QString RenderMaxTexture6144MB = "6144 MB";
const QString RenderMaxTexture8192MB = "8192 MB";
const QString RenderResolution = "Scale Resolution";
const QString RenderResolutionOne = "1";
const QString RenderResolutionTwoThird = "2/3";
const QString RenderResolutionHalf = "1/2";
const QString RenderResolutionThird = "1/3";
const QString RenderResolutionQuarter = "1/4";
const QString RenderSensorToWorldMatrix = "Show SensorToWorld Matrix";
const QString RenderIKTargets = "Show IK Targets";
const QString RenderIKConstraints = "Show IK Constraints";

View file

@ -19,13 +19,15 @@
* The <code>"far-grab"</code> {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and
* orientation, optionally relative to another entity. Collisions between the entity and the user's avatar are disabled during
* the far-grab.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
*
* @typedef {object} Entities.ActionArguments-FarGrab
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
* relative to the entity's position and rotation.
* @property {Uuid} otherJointIndex=null - If a joint index in the <code>otherID</code> entity, the <code>targetPosition</code>
* and <code>targetRotation</code> are relative to the entity joint's position and rotation.
* @property {Vec3} targetPosition=0,0,0 - The target position.
* @property {Quat} targetRotation=0,0,0,1 - The target rotation.
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
* relative to this entity's position and rotation.
* @property {number} linearTimeScale=3.4e+38 - Controls how long it takes for the entity's position to catch up with the
* target position. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action
* is applied using an exponential decay.
@ -33,6 +35,7 @@
* target orientation. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the
* action is applied using an exponential decay.
*/
// The properties are per ObjectActionTractor.
class AvatarActionFarGrab : public ObjectActionTractor {
public:
AvatarActionFarGrab(const QUuid& id, EntityItemPointer ownerEntity);

View file

@ -447,16 +447,16 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
/**jsdoc
* The <code>"hold"</code> {@link Entities.ActionType|ActionType} positions and rotates an entity relative to an avatar's hand.
* Collisions between the entity and the user's avatar are disabled during the hold.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
*
* @typedef {object} Entities.ActionArguments-Hold
* @property {Uuid} holderID=MyAvatar.sessionUUID - The ID of the avatar holding the entity.
* @property {string} hand=right - The hand holding the entity: <code>"left"</code> or <code>"right"</code>.
* @property {Vec3} relativePosition=0,0,0 - The target position relative to the avatar's hand.
* @property {Vec3} relativeRotation=0,0,0,1 - The target rotation relative to the avatar's hand.
* @property {number} timeScale=3.4e+38 - Controls how long it takes for the entity's position and rotation to catch up with
* the target. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action is
* applied using an exponential decay.
* @property {string} hand=right - The hand holding the entity: <code>"left"</code> or <code>"right"</code>.
* @property {boolean} kinematic=false - If <code>true</code>, the entity is made kinematic during the action; the entity won't
* lag behind the hand but constraint actions such as <code>"hinge"</code> won't act properly.
* @property {boolean} kinematicSetVelocity=false - If <code>true</code> and <code>kinematic</code> is <code>true</code>, the

View file

@ -6100,6 +6100,30 @@ QVariantList MyAvatar::getCollidingFlowJoints() {
return result;
}
int MyAvatar::getOverrideJointCount() const {
if (_skeletonModel) {
return _skeletonModel->getRig().getOverrideJointCount();
} else {
return 0;
}
}
bool MyAvatar::getFlowActive() const {
if (_skeletonModel) {
return _skeletonModel->getRig().getFlowActive();
} else {
return false;
}
}
bool MyAvatar::getNetworkGraphActive() const {
if (_skeletonModel) {
return _skeletonModel->getRig().getNetworkGraphActive();
} else {
return false;
}
}
void MyAvatar::initFlowFromFST() {
if (_skeletonModel->isLoaded()) {
auto &flowData = _skeletonModel->getHFMModel().flowData;

View file

@ -1835,6 +1835,10 @@ public:
*/
Q_INVOKABLE QVariantList getCollidingFlowJoints();
int getOverrideJointCount() const;
bool getFlowActive() const;
bool getNetworkGraphActive() const;
public slots:
/**jsdoc

View file

@ -192,7 +192,7 @@ QString PlatformInfoScriptingInterface::getDisplay(int index) {
}
QString PlatformInfoScriptingInterface::getMemory() {
auto desc = platform::getMemory(0);
auto desc = platform::getMemory();
return QString(desc.dump().c_str());
}
@ -201,6 +201,10 @@ QString PlatformInfoScriptingInterface::getComputer() {
return QString(desc.dump().c_str());
}
QString PlatformInfoScriptingInterface::getPlatform() {
auto desc = platform::getAll();
return QString(desc.dump().c_str());
}
PlatformInfoScriptingInterface::PlatformTier PlatformInfoScriptingInterface::getTierProfiled() {
return (PlatformInfoScriptingInterface::PlatformTier) platform::Profiler::profilePlatform();

View file

@ -51,6 +51,8 @@ public slots:
* Gets the operating system type.
* @function PlatformInfo.getOperatingSystemType
* @returns {string} <code>"WINDOWS"</code>, <code>"MACOS"</code>, or <code>"UNKNOWN"</code>.
* @deprecated This function is deprecated and will be removed.
* use getComputer()["OS"] instead
*/
QString getOperatingSystemType();
@ -61,6 +63,10 @@ public slots:
* @example <caption>Report the CPU being used.</caption>
* print("CPU: " + PlatformInfo.getCPUBrand());
* // Example: Intel(R) Core(TM) i7-7820HK CPU @ 2.90GHz
* @deprecated This function is deprecated and will be removed.
* use getNumCPUs() to know the number of CPUs in the hardware, at least one is expected
* use getCPU(0)["vendor"] to get the brand of the vendor
* use getCPU(0)["model"] to get the model name of the cpu
*/
QString getCPUBrand();
@ -68,6 +74,8 @@ public slots:
* Gets the number of logical CPU cores.
* @function PlatformInfo.getNumLogicalCores
* @returns {number} The number of logical CPU cores.
* @deprecated This function is deprecated and will be removed.
* use getCPU(0)["numCores"] instead
*/
unsigned int getNumLogicalCores();
@ -75,6 +83,8 @@ public slots:
* Returns the total system memory in megabytes.
* @function PlatformInfo.getTotalSystemMemoryMB
* @returns {number} The total system memory in megabytes.
* @deprecated This function is deprecated and will be removed.
* use getMemory()["memTotal"] instead
*/
int getTotalSystemMemoryMB();
@ -82,6 +92,10 @@ public slots:
* Gets the graphics card type.
* @function PlatformInfo.getGraphicsCardType
* @returns {string} The graphics card type.
* @deprecated This function is deprecated and will be removed.
* use getNumGPUs() to know the number of GPUs in the hardware, at least one is expected
* use getGPU(0)["vendor"] to get the brand of the vendor
* use getGPU(0)["model"] to get the model name of the gpu
*/
QString getGraphicsCardType();
@ -141,7 +155,7 @@ public slots:
/**jsdoc
* Get the description of the GPU at the index parameter
* expected fields are:
* - gpuVendor...
* - vendor, model...
* @param index The index of the GPU of the platform
* @function PlatformInfo.getGPU
* @returns {string} The GPU description json field
@ -183,6 +197,14 @@ public slots:
*/
QString getComputer();
/**jsdoc
* Get the complete description of the Platform as an aggregated Json
* The expected object description is:
* { "computer": {...}, "memory": {...}, "cpus": [{...}, ...], "gpus": [{...}, ...], "displays": [{...}, ...] }
* @function PlatformInfo.getPlatform
* @returns {string} The Platform description json field
*/
QString getPlatform();
/**jsdoc
* Get the Platform TIer profiled on startup of the Computer

View file

@ -30,14 +30,16 @@ void RenderScriptingInterface::loadSettings() {
_shadowsEnabled = (_shadowsEnabledSetting.get());
_ambientOcclusionEnabled = (_ambientOcclusionEnabledSetting.get());
_antialiasingEnabled = (_antialiasingEnabledSetting.get());
_viewportResolutionScale = (_viewportResolutionScaleSetting.get());
});
forceRenderMethod((RenderMethod)_renderMethod);
forceShadowsEnabled(_shadowsEnabled);
forceAmbientOcclusionEnabled(_ambientOcclusionEnabled);
forceAntialiasingEnabled(_antialiasingEnabled);
forceViewportResolutionScale(_viewportResolutionScale);
}
RenderScriptingInterface::RenderMethod RenderScriptingInterface::getRenderMethod() {
RenderScriptingInterface::RenderMethod RenderScriptingInterface::getRenderMethod() const {
return (RenderMethod) _renderMethod;
}
@ -64,7 +66,7 @@ QStringList RenderScriptingInterface::getRenderMethodNames() const {
return refrenderMethodNames;
}
bool RenderScriptingInterface::getShadowsEnabled() {
bool RenderScriptingInterface::getShadowsEnabled() const {
return _shadowsEnabled;
}
@ -88,7 +90,7 @@ void RenderScriptingInterface::forceShadowsEnabled(bool enabled) {
});
}
bool RenderScriptingInterface::getAmbientOcclusionEnabled() {
bool RenderScriptingInterface::getAmbientOcclusionEnabled() const {
return _ambientOcclusionEnabled;
}
@ -112,7 +114,7 @@ void RenderScriptingInterface::forceAmbientOcclusionEnabled(bool enabled) {
});
}
bool RenderScriptingInterface::getAntialiasingEnabled() {
bool RenderScriptingInterface::getAntialiasingEnabled() const {
return _antialiasingEnabled;
}
@ -145,3 +147,37 @@ void RenderScriptingInterface::forceAntialiasingEnabled(bool enabled) {
}
float RenderScriptingInterface::getViewportResolutionScale() const {
return _viewportResolutionScale;
}
void RenderScriptingInterface::setViewportResolutionScale(float scale) {
if (_viewportResolutionScale != scale) {
forceViewportResolutionScale(scale);
emit settingsChanged();
}
}
void RenderScriptingInterface::forceViewportResolutionScale(float scale) {
// just not negative values or zero
if (scale <= 0.f) {
return;
}
_renderSettingLock.withWriteLock([&] {
_viewportResolutionScale = (scale);
_viewportResolutionScaleSetting.set(scale);
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
assert(renderConfig);
auto deferredView = renderConfig->getConfig("RenderMainView.RenderDeferredTask");
// mainView can be null if we're rendering in forward mode
if (deferredView) {
deferredView->setProperty("resolutionScale", _viewportResolutionScale);
}
auto forwardView = renderConfig->getConfig("RenderMainView.RenderForwardTask");
// mainView can be null if we're rendering in forward mode
if (forwardView) {
forwardView->setProperty("resolutionScale", _viewportResolutionScale);
}
});
}

View file

@ -29,6 +29,7 @@ class RenderScriptingInterface : public QObject {
Q_PROPERTY(bool shadowsEnabled READ getShadowsEnabled WRITE setShadowsEnabled NOTIFY settingsChanged)
Q_PROPERTY(bool ambientOcclusionEnabled READ getAmbientOcclusionEnabled WRITE setAmbientOcclusionEnabled NOTIFY settingsChanged)
Q_PROPERTY(bool antialiasingEnabled READ getAntialiasingEnabled WRITE setAntialiasingEnabled NOTIFY settingsChanged)
Q_PROPERTY(float viewportResolutionScale READ getViewportResolutionScale WRITE setViewportResolutionScale NOTIFY settingsChanged)
public:
RenderScriptingInterface();
@ -66,7 +67,7 @@ public slots:
* @function Render.getRenderMethod
* @returns {number} <code>"DEFERRED"</code> or <code>"FORWARD"</code>
*/
RenderMethod getRenderMethod();
RenderMethod getRenderMethod() const;
/**jsdoc
* Sets the current render method
@ -88,7 +89,7 @@ public slots:
* @function Render.getShadowsEnabled
* @returns {bool} <code>true</code> if shadows are enabled, otherwise <code>false</code>
*/
bool getShadowsEnabled();
bool getShadowsEnabled() const;
/**jsdoc
* Enables or disables shadows
@ -102,7 +103,7 @@ public slots:
* @function Render.getAmbientOcclusionEnabled
* @returns {bool} <code>true</code> if ambient occlusion is enabled, otherwise <code>false</code>
*/
bool getAmbientOcclusionEnabled();
bool getAmbientOcclusionEnabled() const;
/**jsdoc
* Enables or disables ambient occlusion
@ -116,7 +117,7 @@ public slots:
* @function Render.getAntialiasingEnabled
* @returns {bool} <code>true</code> if anti-aliasing is enabled, otherwise <code>false</code>
*/
bool getAntialiasingEnabled();
bool getAntialiasingEnabled() const;
/**jsdoc
* Enables or disables anti-aliasing
@ -130,14 +131,14 @@ public slots:
* @function Render.getViewportResolutionScale
* @returns {number}
*/
// float getViewportResolutionScale();
float getViewportResolutionScale() const;
/**jsdoc
* Sets the current viewport resolution scale
* @function Render.setViewportResolutionScale
* @param {number} resolutionScale - between epsilon and 1.0
*/
// void setViewportResolutionScale(float resolutionScale);
void setViewportResolutionScale(float resolutionScale);
signals:
void settingsChanged();
@ -150,19 +151,22 @@ private:
int _renderMethod{ RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED };
bool _shadowsEnabled{ true };
bool _ambientOcclusionEnabled{ false };
bool _antialiasingEnabled { true };
bool _antialiasingEnabled{ true };
float _viewportResolutionScale{ 1.0f };
// Actual settings saved on disk
Setting::Handle<int> _renderMethodSetting { "renderMethod", RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED };
Setting::Handle<bool> _shadowsEnabledSetting { "shadowsEnabled", true };
Setting::Handle<bool> _ambientOcclusionEnabledSetting { "ambientOcclusionEnabled", false };
Setting::Handle<bool> _antialiasingEnabledSetting { "antialiasingEnabled", true };
Setting::Handle<float> _viewportResolutionScaleSetting { "viewportResolutionScale", 1.0f };
// Force assign both setting AND runtime value to the parameter value
void forceRenderMethod(RenderMethod renderMethod);
void forceShadowsEnabled(bool enabled);
void forceAmbientOcclusionEnabled(bool enabled);
void forceAntialiasingEnabled(bool enabled);
void forceViewportResolutionScale(float scale);
static std::once_flag registry_flag;
};

View file

@ -165,14 +165,14 @@ public slots:
/**jsdoc
* Set number of cycles texture size is required to be stable
* @function Entities.setMinimumGPUTextureMemStabilityCount
* @function Test.setMinimumGPUTextureMemStabilityCount
* @param {number} count - Number of cycles to wait
*/
Q_INVOKABLE void setMinimumGPUTextureMemStabilityCount(int count);
/**jsdoc
* Check whether all textures have been loaded.
* @function Entities.isTextureLoadingComplete
* @function Test.isTextureLoadingComplete
* @returns {boolean} <code>true</code> texture memory usage is not increasing
*/
Q_INVOKABLE bool isTextureLoadingComplete();

View file

@ -94,6 +94,21 @@ void AnimStats::updateStats(bool force) {
}
emit walkingTextChanged();
// print current overrideJointText
int overrideJointCount = myAvatar->getOverrideJointCount();
_overrideJointText = QString("Override Joint Count: %1").arg(overrideJointCount);
emit overrideJointTextChanged();
// print current flowText
bool flowActive = myAvatar->getFlowActive();
_flowText = QString("Flow: %1").arg(flowActive ? "enabled" : "disabled");
emit flowTextChanged();
// print current networkGraphText
bool networkGraphActive = myAvatar->getNetworkGraphActive();
_networkGraphText = QString("Network Graph: %1").arg(networkGraphActive ? "enabled" : "disabled");
emit networkGraphTextChanged();
// update animation debug alpha values
QStringList newAnimAlphaValues;
qint64 now = usecTimestampNow();

View file

@ -25,6 +25,9 @@ class AnimStats : public QQuickItem {
Q_PROPERTY(QString recenterText READ recenterText NOTIFY recenterTextChanged)
Q_PROPERTY(QString sittingText READ sittingText NOTIFY sittingTextChanged)
Q_PROPERTY(QString walkingText READ walkingText NOTIFY walkingTextChanged)
Q_PROPERTY(QString overrideJointText READ overrideJointText NOTIFY overrideJointTextChanged)
Q_PROPERTY(QString flowText READ flowText NOTIFY flowTextChanged)
Q_PROPERTY(QString networkGraphText READ networkGraphText NOTIFY networkGraphTextChanged)
public:
static AnimStats* getInstance();
@ -43,6 +46,9 @@ public:
QString recenterText() const { return _recenterText; }
QString sittingText() const { return _sittingText; }
QString walkingText() const { return _walkingText; }
QString overrideJointText() const { return _overrideJointText; }
QString flowText() const { return _flowText; }
QString networkGraphText() const { return _networkGraphText; }
public slots:
void forceUpdateStats() { updateStats(true); }
@ -58,6 +64,9 @@ signals:
void recenterTextChanged();
void sittingTextChanged();
void walkingTextChanged();
void overrideJointTextChanged();
void flowTextChanged();
void networkGraphTextChanged();
private:
QStringList _animAlphaValues;
@ -76,6 +85,9 @@ private:
QString _recenterText;
QString _sittingText;
QString _walkingText;
QString _overrideJointText;
QString _flowText;
QString _networkGraphText;
};
#endif // hifi_AnimStats_h

View file

@ -14,10 +14,9 @@
#include <ScriptEngines.h>
#include <OffscreenUi.h>
#include <Preferences.h>
#include <RenderShadowTask.h>
#include <plugins/PluginUtils.h>
#include <display-plugins/CompositorHelper.h>
#include "scripting/RenderScriptingInterface.h"
#include "Application.h"
#include "DialogsManager.h"
#include "LODManager.h"
@ -103,6 +102,22 @@ void setupPreferences() {
preference->setItems(refreshRateProfiles);
preferences->addPreference(preference);
}
{
// Expose the Viewport Resolution Scale
auto getter = []()->float {
return RenderScriptingInterface::getInstance()->getViewportResolutionScale();
};
auto setter = [](float value) {
RenderScriptingInterface::getInstance()->setViewportResolutionScale(value);
};
auto scaleSlider = new SliderPreference(GRAPHICS_QUALITY, "Resolution Scale", getter, setter);
scaleSlider->setMin(0.25f);
scaleSlider->setMax(1.0f);
scaleSlider->setStep(0.02f);
preferences->addPreference(scaleSlider);
}
// UI
static const QString UI_CATEGORY { "User Interface" };

View file

@ -377,7 +377,7 @@ void Stats::updateStats(bool force) {
auto displayPlugin = qApp->getActiveDisplayPlugin();
if (displayPlugin) {
QVector2D dims(displayPlugin->getRecommendedRenderSize().x, displayPlugin->getRecommendedRenderSize().y);
dims *= displayPlugin->getRenderResolutionScale();
dims *= qApp->getRenderResolutionScale();
STAT_UPDATE(gpuFrameSize, dims);
STAT_UPDATE(gpuFrameTimePerPixel, (float)(gpuContext->getFrameTimerGPUAverage()*1000000.0 / double(dims.x()*dims.y())));
}

View file

@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.0)
set(ENV{MACOSX_DEPLOYMENT_TARGET} 10.9)
project(HQLauncher)
set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
set(src_files
@ -26,6 +27,8 @@ set(src_files
src/LatestBuildRequest.m
src/OrganizationRequest.m
src/OrganizationRequest.h
src/Interface.h
src/Interface.m
src/ErrorViewController.h
src/ErrorViewController.m
src/Settings.h
@ -67,7 +70,7 @@ add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${src_files})
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME}
MACOSX_BUNDLE_BUNDLE_NAME ${APP_NAME})
set_from_env(LAUNCHER_HMAC_SECRET LAUNCHER_HMAC_SECRET "")
if (LAUNCHER_HMAC_SECRET STREQUAL "")
if ("${LAUNCHER_HMAC_SECRET}" STREQUAL "")
message(FATAL_ERROR "LAUNCHER_HMAC_SECRET is not set")
endif()

View file

@ -32,6 +32,6 @@
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundleDisplayName</key>
<string>CFBundleName</string>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
</dict>
</plist>

View file

@ -69,8 +69,17 @@
<action selector="hyperLink:" target="YVh-OH-vU8" id="JfS-ot-wAP"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0CN-kS-xZ5">
<rect key="frame" x="66" y="68" width="266" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="By signing in, you agree to the High Fidelity" id="zSf-YA-osu">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xeX-qc-ccB" customClass="HFButton">
<rect key="frame" x="205" y="84" width="104" height="42"/>
<rect key="frame" x="205" y="111" width="104" height="42"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="square" title="LOG IN" bezelStyle="shadowlessSquare" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6Ba-S9-5qW">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -81,6 +90,18 @@
<action selector="login:" target="YVh-OH-vU8" id="uzF-yC-tu1"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QtF-Xs-rht" customClass="Hyperlink">
<rect key="frame" x="336" y="68" width="115" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Terms of Service" id="O5x-BW-FLk">
<font key="font" metaFont="system"/>
<color key="textColor" name="linkColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="linkColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="termsOfService:" target="YVh-OH-vU8" id="bgc-08-8Lj"/>
</connections>
</textField>
</subviews>
<point key="canvasLocation" x="138.5" y="154"/>
</customView>
@ -91,5 +112,14 @@
<outlet property="smallLogo" destination="j8K-TD-h7e" id="OVd-p3-nu6"/>
</connections>
</customObject>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="wWT-mi-6An">
<rect key="frame" x="0.0" y="0.0" width="37" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="1Uh-1I-CcU">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</objects>
</document>

View file

@ -31,4 +31,9 @@
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.highfidelity.com/hq-support"]];
}
- (IBAction)termsOfService:(id)sender
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.highfidelity.com/termsofservice"]];
}
@end

View file

@ -0,0 +1,8 @@
#import <Foundation/Foundation.h>
@interface Interface : NSObject
-(id _Nonnull) initWith:(NSString * _Nonnull) aPathToInterface;
-(NSInteger) getVersion:(out NSError * _Nullable * _Nonnull) anError;
@end

View file

@ -0,0 +1,90 @@
#import "Interface.h"
@implementation Interface
{
NSString *pathTo;
}
-(id) initWith:(NSString*)aPathToInterface
{
[self init];
self->pathTo = [NSString stringWithFormat:@"%@/Contents/MacOS/interface", aPathToInterface];
return self;
}
-(NSInteger) getVersion:(out NSError * _Nullable *) outError
{
NSTask * interface = [[NSTask alloc] init];
NSPipe * standardOut = [NSPipe pipe];
interface.launchPath = self->pathTo;
interface.arguments = @[ @"--version" ];
interface.standardOutput = standardOut;
NSLog(@"calling interface at %@", self->pathTo);
NSError *error = nil;
[interface launch];
[interface waitUntilExit];
if (0 != [interface terminationStatus]) {
*outError = [NSError errorWithDomain:@"interface"
code:-1
userInfo:@{NSUnderlyingErrorKey: error}];
return 0;
}
NSFileHandle * fh = [standardOut fileHandleForReading];
NSData * data = [fh readDataToEndOfFile];
NSString * output = [NSString stringWithUTF8String:[data bytes]];
if (output == nil) {
NSDictionary * userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't start interface", nil)
};
*outError = [NSError errorWithDomain:@"interface"
code:-1
userInfo:userInfo];
return 0;
}
// Interface returns the build version as a string like this:
// "Interface 33333-DEADBEEF". This code grabs the substring
// between "Interface " and the hyphon ("-")
NSRange start = [output rangeOfString:@"Interface "];
if (start.length == 0) {
NSDictionary * userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil)
};
*outError = [NSError errorWithDomain:@"interface"
code:-2
userInfo:userInfo];
return 0;
}
NSRange end = [output rangeOfString:@"-"];
if (end.length == 0) {
NSDictionary * userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil)
};
*outError = [NSError errorWithDomain:@"interface"
code:-2
userInfo:userInfo];
return 0;
}
NSRange subRange = {start.length, end.location - start.length};
NSString * versionStr;
@try {
versionStr = [output substringWithRange:subRange];
}
@catch (NSException *) {
NSDictionary * userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil)
};
*outError = [NSError errorWithDomain:@"interface"
code:-2
userInfo:userInfo];
return 0;
}
return versionStr.integerValue;
}
@end

View file

@ -1,29 +1,58 @@
#import "LatestBuildRequest.h"
#import "Launcher.h"
#import "Settings.h"
#import "Interface.h"
@implementation LatestBuildRequest
- (NSInteger) getCurrentVersion {
NSInteger currentVersion;
@try {
NSString* interfaceAppPath = [[Launcher.sharedLauncher getAppPath] stringByAppendingString:@"interface.app"];
NSError * error = nil;
Interface * interface = [[Interface alloc] initWith:interfaceAppPath];
currentVersion = [interface getVersion:&error];
if (currentVersion == 0 && error != nil) {
NSLog(@"can't get version from interface, falling back to settings: %@", error);
currentVersion = [Settings.sharedSettings latestBuildVersion];
}
} @catch (NSException *exception) {
NSLog(@"an exception was thrown: %@", exception);
currentVersion = [Settings.sharedSettings latestBuildVersion];
}
return currentVersion;
}
- (void) requestLatestBuildInfo {
NSMutableURLRequest *request = [NSMutableURLRequest new];
[request setURL:[NSURL URLWithString:@"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"]];
[request setHTTPMethod:@"GET"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
NSURLSession* session = [NSURLSession sharedSession];
// We're using an ephermeral session here to ensure the tags api response is never cached.
NSURLSession * session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration];
NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"Latest Build Request error: %@", error);
NSLog(@"Latest Build Request Data: %@", data);
NSHTTPURLResponse *ne = (NSHTTPURLResponse *)response;
NSLog(@"Latest Build Request Response: %ld", [ne statusCode]);
Launcher* sharedLauncher = [Launcher sharedLauncher];
NSLog(@"credentials request finished");
NSMutableData* webData = [NSMutableData data];
[webData appendData:data];
NSString* jsonString = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[data length] encoding:NSUTF8StringEncoding];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
NSLog(@"Latest Build Request -> json string: %@", jsonString);
NSError *jsonError = nil;
id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError];
if (jsonError) {
NSLog(@"Latest Build request: Failed to convert Json to data");
}
NSFileManager* fileManager = [NSFileManager defaultManager];
NSArray *values = [json valueForKey:@"results"];
NSArray *values = [json valueForKey:@"results"];
NSDictionary *value = [values objectAtIndex:0];
@ -35,12 +64,17 @@
BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]];
dispatch_async(dispatch_get_main_queue(), ^{
Settings* settings = [Settings sharedSettings];
NSInteger currentVersion = [settings latestBuildVersion];
NSInteger currentVersion = [self getCurrentVersion];
NSLog(@"Latest Build Request -> does build directory exist: %@", appDirectoryExist ? @"TRUE" : @"FALSE");
NSLog(@"Latest Build Request -> current version: %ld", currentVersion);
NSLog(@"Latest Build Request -> latest version: %ld", buildNumber.integerValue);
NSLog(@"Latest Build Request -> mac url: %@", macInstallerUrl);
BOOL latestVersionAvailable = (currentVersion != buildNumber.integerValue);
[[Settings sharedSettings] buildVersion:buildNumber.integerValue];
BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist);
NSLog(@"Latest Build Request -> SHOULD DOWNLOAD: %@", shouldDownloadInterface ? @"TRUE" : @"FALSE");
[sharedLauncher shouldDownloadLatestBuild:shouldDownloadInterface :macInstallerUrl];
});
}];
@ -90,11 +124,10 @@
NSDictionary* macInstallerObject = [installers objectForKey:@"mac"];
NSString* macInstallerUrl = [macInstallerObject valueForKey:@"zip_url"];
BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]];
Settings* settings = [Settings sharedSettings];
NSInteger currentVersion = [settings latestBuildVersion];
BOOL latestVersionAvailable = (currentVersion != buildNumber.integerValue);
NSString* interfaceAppPath = [[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"];
BOOL appDirectoryExist = [fileManager fileExistsAtPath:interfaceAppPath];
BOOL latestVersionAvailable = ([self getCurrentVersion] != buildNumber.integerValue);
[[Settings sharedSettings] buildVersion:buildNumber.integerValue];
BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist);

View file

@ -5,13 +5,13 @@ void redirectLogToDocuments()
{
NSString* filePath = [[NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingString:@"/Launcher/"];
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSError * error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:filePath withIntermediateDirectories:TRUE attributes:nil error:&error];
}
NSString *pathForLog = [filePath stringByAppendingPathComponent:@"log.txt"];
freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}
@ -23,12 +23,12 @@ int main(int argc, const char* argv[]) {
NSLog(@"launcher is already running");
return 0;
}
[NSApplication sharedApplication];
Launcher* sharedLauncher = [Launcher sharedLauncher];
[Settings sharedSettings];
[NSApp setDelegate: sharedLauncher];
// Referenced from https://stackoverflow.com/questions/9155015/handle-cmd-q-in-cocoa-application-and-menu-item-quit-application-programmatic
id menubar = [[NSMenu new] autorelease];
id appMenuItem = [[NSMenuItem new] autorelease];
@ -40,7 +40,7 @@ int main(int argc, const char* argv[]) {
id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:quitTitle action:@selector(terminate:) keyEquivalent:@"q"] autorelease];
[appMenu addItem:quitMenuItem];
[appMenuItem setSubmenu:appMenu];
[[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE];
return NSApplicationMain(argc, argv);
}

View file

@ -103,7 +103,7 @@ BEGIN
CTEXT "",IDC_MESSAGE2_LABEL,35,172,239,15,NOT WS_VISIBLE
CTEXT "",IDC_ACTION2_LABEL,15,147,278,25,NOT WS_VISIBLE
RTEXT "",IDC_TERMS,15,172,180,15,NOT WS_VISIBLE
LTEXT "",IDC_TERMS2,197,172,80,15,NOT WS_VISIBLE
CONTROL "",IDC_TERMS_LINK,"Button", BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,197,172,80,15
CTEXT "",IDC_TROUBLE,65,203,174,15,NOT WS_VISIBLE
CONTROL "NEXT",IDC_BUTTON_NEXT,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,107,158,94,16
CONTROL "Having Trouble?",IDC_TROUBLE_LINK,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,126,203,56,11

View file

@ -37,6 +37,7 @@ static CString GRAPHIK_REGULAR = _T("Graphik-Regular");
static CString GRAPHIK_SEMIBOLD = _T("Graphik-Semibold");
static CString TROUBLE_URL = _T("https://www.highfidelity.com/hq-support");
static CString TERMS_URL = _T("https://www.highfidelity.com/termsofservice");
CLauncherDlg::CLauncherDlg(CWnd* pParent)
@ -54,6 +55,7 @@ void CLauncherDlg::DoDataExchange(CDataExchange* pDX)
{
DDX_Control(pDX, IDC_BUTTON_NEXT, m_btnNext);
DDX_Control(pDX, IDC_TROUBLE_LINK, m_trouble_link);
DDX_Control(pDX, IDC_TERMS_LINK, m_terms_link);
DDX_Control(pDX, IDC_ORGNAME, m_orgname);
DDX_Control(pDX, IDC_USERNAME, m_username);
DDX_Control(pDX, IDC_PASSWORD, m_password);
@ -69,6 +71,7 @@ BEGIN_MESSAGE_MAP(CLauncherDlg, CDialog)
ON_EN_SETFOCUS(IDC_PASSWORD, &CLauncherDlg::OnPassEditChangeFocus)
ON_BN_CLICKED(IDC_BUTTON_NEXT, &CLauncherDlg::OnNextClicked)
ON_BN_CLICKED(IDC_TROUBLE_LINK, &CLauncherDlg::OnTroubleClicked)
ON_BN_CLICKED(IDC_TERMS_LINK, &CLauncherDlg::OnTermsClicked)
ON_WM_CTLCOLOR()
ON_WM_DRAWITEM()
ON_WM_SETCURSOR()
@ -103,7 +106,6 @@ BOOL CLauncherDlg::OnInitDialog() {
m_password_banner = (CStatic *)GetDlgItem(IDC_PASSWORD_BANNER);
m_terms = (CStatic *)GetDlgItem(IDC_TERMS);
m_terms2 = (CStatic *)GetDlgItem(IDC_TERMS2);
m_trouble = (CStatic *)GetDlgItem(IDC_TROUBLE);
m_voxel = (CStatic *)GetDlgItem(IDC_VOXEL);
@ -213,6 +215,9 @@ BOOL CLauncherDlg::getHQInfo(const CString& orgname) {
CString lowerOrgName = orgname;
lowerOrgName.MakeLower();
LauncherUtils::hMac256(lowerOrgName, LAUNCHER_HMAC_SECRET, hash);
CString msg;
msg.Format(_T("Calculated hash: \"%s\" => \"%s\""), lowerOrgName, hash);
theApp._manager.addToLog(msg);
return theApp._manager.readOrganizationJSON(hash) == LauncherUtils::ResponseError::NoError;
}
@ -220,6 +225,10 @@ afx_msg void CLauncherDlg::OnTroubleClicked() {
LauncherUtils::executeOnForeground(TROUBLE_URL, _T(""));
}
afx_msg void CLauncherDlg::OnTermsClicked() {
LauncherUtils::executeOnForeground(TERMS_URL, _T(""));
}
afx_msg void CLauncherDlg::OnNextClicked() {
if (_drawStep != DrawStep::DrawChoose) {
CString token;
@ -272,7 +281,7 @@ void CLauncherDlg::drawLogo(CHwndRenderTarget* pRenderTarget) {
CD2DBitmap m_pBitmamLogo(pRenderTarget, IDB_PNG2, _T("PNG"));
auto size = pRenderTarget->GetSize();
int logoWidth = 231;
int logoHeight = 181;
int logoHeight = 173;
float logoPosX = 0.5f * (size.width - logoWidth);
float logoPosY = 0.95f * (size.height - logoHeight);
CD2DRectF logoRec(logoPosX, logoPosY, logoPosX + logoWidth, logoPosY + logoHeight);
@ -359,9 +368,9 @@ void CLauncherDlg::prepareChoose() {
m_action_label->SetWindowTextW(_T("Choose a display name"));
m_message_label->SetWindowTextW(_T("This is the name that your teammates will see."));
m_terms->ShowWindow(SW_SHOW);
m_terms2->ShowWindow(SW_SHOW);
m_terms_link.ShowWindow(SW_SHOW);
m_terms->SetWindowTextW(_T("By signing in, you agree to the High Fidelity"));
m_terms2->SetWindowTextW(_T("Terms of Service"));
m_terms_link.SetWindowTextW(_T("Terms of Service"));
CRect rec;
m_btnNext.GetWindowRect(&rec);
ScreenToClient(&rec);
@ -377,7 +386,7 @@ void CLauncherDlg::prepareProcess(DrawStep step) {
m_trouble->ShowWindow(SW_HIDE);
m_trouble_link.ShowWindow(SW_HIDE);
m_terms->ShowWindow(SW_HIDE);
m_terms2->ShowWindow(SW_HIDE);
m_terms_link.ShowWindow(SW_HIDE);
m_orgname_banner->ShowWindow(SW_HIDE);
m_username_banner->ShowWindow(SW_HIDE);
m_password_banner->ShowWindow(SW_HIDE);
@ -462,7 +471,7 @@ BOOL CLauncherDlg::getTextFormat(int resID, TextFormat& formatOut) {
case IDC_TERMS:
formatOut.size = TERMS_FONT_SIZE;
break;
case IDC_TERMS2:
case IDC_TERMS_LINK:
formatOut.size = TERMS_FONT_SIZE;
formatOut.isBold = true;
break;
@ -539,6 +548,14 @@ void CLauncherDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
dc.SelectObject(buttonFont);
}
dc.DrawText(_T("Having Trouble"), CRect(rect.left, rect.top, rect.right, rect.bottom), DT_CENTER | DT_VCENTER | DT_SINGLELINE);
} else if (nIDCtl == IDC_TERMS_LINK) {
dc.FillSolidRect(rect, COLOR_BLACK);
dc.SetTextColor(COLOR_LIGHT_GREY);
CFont buttonFont;
if (LauncherUtils::getFont(GRAPHIK_SEMIBOLD, TERMS_FONT_SIZE, true, buttonFont)) {
dc.SelectObject(buttonFont);
}
dc.DrawText(_T("Terms of Service"), CRect(rect.left, rect.top, rect.right, rect.bottom), DT_LEFT | DT_TOP | DT_SINGLELINE);
}
}

View file

@ -72,13 +72,13 @@ protected:
HICON m_hIcon;
CButton m_btnNext;
CButton m_trouble_link;
CButton m_terms_link;
CStatic* m_message_label;
CStatic* m_action_label;
CStatic* m_message2_label;
CStatic* m_action2_label;
CStatic* m_terms;
CStatic* m_terms2;
CStatic* m_trouble;
CStatic* m_voxel;
@ -111,6 +111,7 @@ protected:
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnNextClicked();
afx_msg void OnTroubleClicked();
afx_msg void OnTermsClicked();
afx_msg void OnOrgEditChangeFocus();
afx_msg void OnUserEditChangeFocus();
afx_msg void OnPassEditChangeFocus();

View file

@ -427,6 +427,11 @@ BOOL LauncherManager::extractApplication() {
LauncherUtils::cStringToStd(installPath), [&](int type, int size) {
onZipExtracted((ZipType)type, size);
});
if (success) {
addToLog(_T("Created thread for unzipping application."));
} else {
addToLog(_T("Failed to create thread for unzipping application."));
}
return success;
}
@ -449,6 +454,11 @@ BOOL LauncherManager::installContent() {
LauncherUtils::cStringToStd(contentPath), [&](int type, int size) {
onZipExtracted((ZipType)type, size);
});
if (success) {
addToLog(_T("Created thread for unzipping content."));
} else {
addToLog(_T("Failed to create thread for unzipping content."));
}
return success;
}

View file

@ -16,6 +16,7 @@
#pragma comment(lib, "winhttp")
#include "LauncherApp.h"
#include "LauncherUtils.h"
CString LauncherUtils::urlEncodeString(const CString& url) {
@ -183,6 +184,17 @@ LauncherUtils::ResponseError LauncherUtils::makeHTTPCall(const CString& callerNa
BOOL haveContentLength = WinHttpQueryHeaders(hrequest, WINHTTP_QUERY_CONTENT_LENGTH, NULL,
&szContentLength, &bufferBytes, &dwHeaderIndex);
DWORD statusCode;
DWORD statusCodeSize = sizeof(statusCode);
WinHttpQueryHeaders(hrequest,
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
NULL,
&statusCode, &statusCodeSize, WINHTTP_NO_HEADER_INDEX);
CString msg;
msg.Format(_T("Status code response (%s%s): %lu"), mainUrl, dirUrl, statusCode);
theApp._manager.addToLog(msg);
DWORD dwContentLength;
if (haveContentLength) {
dwContentLength = _wtoi(szContentLength);
@ -225,19 +237,37 @@ BOOL LauncherUtils::getFont(const CString& fontName, int fontSize, bool isBold,
}
uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string& path, std::vector<std::string>& files) {
{
CString msg;
msg.Format(_T("Reading zip file %s, extracting to %s"), CString(zipFile.c_str()), CString(path.c_str()));
theApp._manager.addToLog(msg);
}
mz_zip_archive zip_archive;
memset(&zip_archive, 0, sizeof(zip_archive));
auto status = mz_zip_reader_init_file(&zip_archive, zipFile.c_str(), 0);
if (!status) return 0;
if (!status) {
auto zip_error = mz_zip_get_last_error(&zip_archive);
auto zip_error_msg = mz_zip_get_error_string(zip_error);
CString msg;
msg.Format(_T("Failed to initialize miniz: %d %s"), zip_error, CString(zip_error_msg));
theApp._manager.addToLog(msg);
return 0;
}
int fileCount = (int)mz_zip_reader_get_num_files(&zip_archive);
if (fileCount == 0) {
theApp._manager.addToLog(_T("Zip archive has a file count of 0"));
mz_zip_reader_end(&zip_archive);
return 0;
}
mz_zip_archive_file_stat file_stat;
if (!mz_zip_reader_file_stat(&zip_archive, 0, &file_stat)) {
theApp._manager.addToLog(_T("Zip archive cannot be stat'd"));
mz_zip_reader_end(&zip_archive);
return 0;
}
@ -263,6 +293,12 @@ uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string
}
}
{
CString msg;
msg.Format(_T("Done unzipping archive, total size: %llu"), totalSize);
theApp._manager.addToLog(msg);
}
// Close the archive, freeing any resources it was using
mz_zip_reader_end(&zip_archive);
return totalSize;

View file

@ -23,7 +23,7 @@
#define IDC_USERNAME_BANNER 1019
#define IDC_PASSWORD_BANNER 1020
#define IDC_TERMS 1021
#define IDC_TERMS2 1022
#define IDC_TERMS_LINK 1022
#define IDC_TROUBLE 1023
#define IDC_VOXEL 1024
#define IDC_TROUBLE_LINK 1027

View file

@ -2025,6 +2025,9 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
if (params.isTalking) {
if (_talkIdleInterpTime < 1.0f) {
_talkIdleInterpTime += dt / TOTAL_EASE_IN_TIME;
if (_talkIdleInterpTime > 1.0f) {
_talkIdleInterpTime = 1.0f;
}
float easeOutInValue = _talkIdleInterpTime < 0.5f ? 4.0f * powf(_talkIdleInterpTime, 3.0f) : 4.0f * powf((_talkIdleInterpTime - 1.0f), 3.0f) + 1.0f;
_animVars.set("idleOverlayAlpha", easeOutInValue);
} else {
@ -2033,6 +2036,9 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
} else {
if (_talkIdleInterpTime < 1.0f) {
_talkIdleInterpTime += dt / TOTAL_EASE_OUT_TIME;
if (_talkIdleInterpTime > 1.0f) {
_talkIdleInterpTime = 1.0f;
}
float easeOutInValue = _talkIdleInterpTime < 0.5f ? 4.0f * powf(_talkIdleInterpTime, 3.0f) : 4.0f * powf((_talkIdleInterpTime - 1.0f), 3.0f) + 1.0f;
float talkAlpha = 1.0f - easeOutInValue;
_animVars.set("idleOverlayAlpha", talkAlpha);
@ -2287,6 +2293,24 @@ void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& a
}
}
int Rig::getOverrideJointCount() const {
int count = 0;
for (size_t i = 0; i < _internalPoseSet._overrideFlags.size(); i++) {
if (_internalPoseSet._overrideFlags[i]) {
count++;
}
}
return count;
}
bool Rig::getFlowActive() const {
return _internalFlow.getActive();
}
bool Rig::getNetworkGraphActive() const {
return _sendNetworkNode;
}
glm::mat4 Rig::getJointTransform(int jointIndex) const {
static const glm::mat4 IDENTITY;
if (isIndexValid(jointIndex)) {

View file

@ -246,6 +246,10 @@ public:
float getUnscaledEyeHeight() const;
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const;
int getOverrideJointCount() const;
bool getFlowActive() const;
bool getNetworkGraphActive() const;
signals:
void onLoadComplete();

View file

@ -375,6 +375,9 @@ AudioClient::AudioClient() :
}
AudioClient::~AudioClient() {
stop();
if (_codec && _encoder) {
_codec->releaseEncoder(_encoder);
_encoder = nullptr;

View file

@ -109,23 +109,20 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() {
return Parent::internalActivate();
}
gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getCompositeScenePipeline() {
gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getRenderTexturePipeline() {
#if defined(Q_OS_ANDROID)
return _linearToSRGBPipeline;
return _linearToSRGBPipeline;
#else
return _SRGBToLinearPipeline;
#ifndef USE_GLES
return _SRGBToLinearPipeline;
#else
return _drawTexturePipeline;
#endif
#endif
}
gpu::Element Basic2DWindowOpenGLDisplayPlugin::getCompositeFBColorSpace() {
#if defined(Q_OS_ANDROID)
return gpu::Element::COLOR_SRGBA_32;
#else
return gpu::Element::COLOR_RGBA_32;
#endif
}
void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() {
#if defined(Q_OS_ANDROID)
auto& virtualPadManager = VirtualPad::Manager::instance();

View file

@ -37,8 +37,7 @@ public:
virtual void pluginUpdate() override {};
virtual gpu::PipelinePointer getCompositeScenePipeline() override;
virtual gpu::Element getCompositeFBColorSpace() override;
virtual gpu::PipelinePointer getRenderTexturePipeline() override;
protected:
mutable bool _isThrottled = false;

View file

@ -62,7 +62,7 @@ public:
PresentThread() {
connect(qApp, &QCoreApplication::aboutToQuit, [this] {
shutdown();
shutdown();
});
setObjectName("Present");
@ -82,12 +82,11 @@ public:
Lock lock(_mutex);
_shutdown = true;
_condition.wait(lock, [&] { return !_shutdown; });
_condition.wait(lock, [&] { return !_shutdown; });
qCDebug(displayPlugins) << "Present thread shutdown";
}
}
void setNewDisplayPlugin(OpenGLDisplayPlugin* plugin) {
Lock lock(_mutex);
if (isRunning()) {
@ -104,7 +103,6 @@ public:
_context->moveToThread(this);
}
virtual void run() override {
PROFILE_SET_THREAD_NAME("Present Thread");
@ -131,7 +129,6 @@ public:
_condition.notify_one();
}
{
// Main thread does it's thing while we wait on the lock to release
Lock lock(_mutex);
@ -201,7 +198,7 @@ public:
#if defined(Q_OS_MAC)
_context->doneCurrent();
#endif
_refreshRateController->sleepThreadIfNeeded(this, currentPlugin->isHmd());
}
@ -235,7 +232,6 @@ public:
_condition.notify_one();
}
private:
void makeCurrent();
void doneCurrent();
@ -245,7 +241,6 @@ private:
// Used to allow the main thread to perform context operations
Condition _condition;
QThread* _targetOperationThread { nullptr };
bool _pendingOtherThreadOperation { false };
bool _finishedOtherThreadOperation { false };
@ -302,7 +297,6 @@ bool OpenGLDisplayPlugin::activate() {
return false;
}
// This should not return until the new context has been customized
// and the old context (if any) has been uncustomized
presentThread->setNewDisplayPlugin(this);
@ -334,7 +328,7 @@ void OpenGLDisplayPlugin::deactivate() {
_container->showDisplayPluginsTools(false);
if (!_container->currentDisplayActions().isEmpty()) {
foreach(auto itemInfo, _container->currentDisplayActions()) {
foreach (auto itemInfo, _container->currentDisplayActions()) {
_container->removeMenuItem(itemInfo.first, itemInfo.second);
}
_container->currentDisplayActions().clear();
@ -368,7 +362,6 @@ void OpenGLDisplayPlugin::customizeContext() {
image = image.convertToFormat(QImage::Format_ARGB32);
}
if ((image.width() > 0) && (image.height() > 0)) {
cursorData.texture = gpu::Texture::createStrict(
gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
image.width(), image.height(),
@ -384,7 +377,7 @@ void OpenGLDisplayPlugin::customizeContext() {
}
}
if (!_drawTexturePipeline) {
if (!_linearToSRGBPipeline) {
gpu::StatePointer blendState = gpu::StatePointer(new gpu::State());
blendState->setDepthTest(gpu::State::DepthTest(false));
blendState->setBlendFunction(true,
@ -397,17 +390,17 @@ void OpenGLDisplayPlugin::customizeContext() {
scissorState->setDepthTest(gpu::State::DepthTest(false));
scissorState->setScissorEnable(true);
_drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState);
_drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState);
_linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaLinearToSRGB), scissorState);
_linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaLinearToSRGB), scissorState);
_SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaSRGBToLinear), scissorState);
_SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaSRGBToLinear), scissorState);
_hudPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), blendState);
_hudPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), blendState);
_mirrorHUDPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureMirroredX), blendState);
_mirrorHUDPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureMirroredX), blendState);
_cursorPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTransformedTexture), blendState);
_cursorPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTransformedTexture), blendState);
}
updateCompositeFramebuffer();
@ -418,9 +411,9 @@ void OpenGLDisplayPlugin::uncustomizeContext() {
_drawTexturePipeline.reset();
_linearToSRGBPipeline.reset();
_SRGBToLinearPipeline.reset();
_cursorPipeline.reset();
_hudPipeline.reset();
_mirrorHUDPipeline.reset();
_cursorPipeline.reset();
_compositeFramebuffer.reset();
withPresentThreadLock([&] {
@ -433,7 +426,6 @@ void OpenGLDisplayPlugin::uncustomizeContext() {
});
}
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to
// receive keyPress events for the Alt (and Meta) key in a reliable manner.
@ -514,11 +506,18 @@ void OpenGLDisplayPlugin::captureFrame(const std::string& filename) const {
});
}
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor) {
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch,
const gpu::TexturePointer& texture,
const glm::ivec4& viewport,
const glm::ivec4& scissor) {
renderFromTexture(batch, texture, viewport, scissor, nullptr);
}
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& copyFbo /*=gpu::FramebufferPointer()*/) {
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch,
const gpu::TexturePointer& texture,
const glm::ivec4& viewport,
const glm::ivec4& scissor,
const gpu::FramebufferPointer& copyFbo /*=gpu::FramebufferPointer()*/) {
auto fbo = gpu::FramebufferPointer();
batch.enableStereo(false);
batch.resetViewTransform();
@ -528,13 +527,13 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur
batch.setViewportTransform(viewport);
batch.setResourceTexture(0, texture);
batch.setPipeline(_drawTexturePipeline);
batch.setPipeline(getRenderTexturePipeline());
batch.draw(gpu::TRIANGLE_STRIP, 4);
if (copyFbo) {
gpu::Vec4i copyFboRect(0, 0, copyFbo->getWidth(), copyFbo->getHeight());
gpu::Vec4i sourceRect(scissor.x, scissor.y, scissor.x + scissor.z, scissor.y + scissor.w);
float aspectRatio = (float)scissor.w / (float) scissor.z; // height/width
float aspectRatio = (float)scissor.w / (float)scissor.z; // height/width
// scale width first
int xOffset = 0;
int yOffset = 0;
@ -593,9 +592,10 @@ std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> OpenGL
hudEyeViewports[eye] = eyeViewport(eye);
});
return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) {
if (hudPipeline && hudTexture) {
auto pipeline = mirror ? hudMirrorPipeline : hudPipeline;
if (pipeline && hudTexture) {
batch.enableStereo(false);
batch.setPipeline(mirror ? hudMirrorPipeline : hudPipeline);
batch.setPipeline(pipeline);
batch.setResourceTexture(0, hudTexture);
if (hudStereo) {
for_each_eye([&](Eye eye) {
@ -634,11 +634,6 @@ void OpenGLDisplayPlugin::compositePointer() {
});
}
// Overridden by Basic2DWindowDisplayPlugin and OculusDisplayPlugin
gpu::PipelinePointer OpenGLDisplayPlugin::getCompositeScenePipeline() {
return _drawTexturePipeline;
}
void OpenGLDisplayPlugin::compositeScene() {
render([&](gpu::Batch& batch) {
batch.enableStereo(false);
@ -661,17 +656,6 @@ void OpenGLDisplayPlugin::compositeLayers() {
compositeScene();
}
#ifdef HIFI_ENABLE_NSIGHT_DEBUG
if (false) // do not draw the HUD if running nsight debug
#endif
{
PROFILE_RANGE_EX(render_detail, "handleHUDBatch", 0xff0077ff, (uint64_t)presentCount())
auto hudOperator = getHUDOperator();
withPresentThreadLock([&] {
_hudOperator = hudOperator;
});
}
{
PROFILE_RANGE_EX(render_detail, "compositeExtra", 0xff0077ff, (uint64_t)presentCount())
compositeExtra();
@ -692,7 +676,7 @@ void OpenGLDisplayPlugin::internalPresent() {
render([&](gpu::Batch& batch) {
// Note: _displayTexture must currently be the same size as the display.
uvec2 dims = _displayTexture ? uvec2(_displayTexture->getDimensions()) : getSurfacePixels();
auto viewport = ivec4(uvec2(0), dims);
auto viewport = ivec4(uvec2(0), dims);
renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, viewport);
});
swapBuffers();
@ -775,7 +759,7 @@ float OpenGLDisplayPlugin::presentRate() const {
return _presentRate.rate();
}
std::function<void(int)> OpenGLDisplayPlugin::getRefreshRateOperator() {
std::function<void(int)> OpenGLDisplayPlugin::getRefreshRateOperator() {
return [](int targetRefreshRate) {
auto refreshRateController = DependencyManager::get<PresentThread>()->getRefreshRateController();
refreshRateController->setRefreshRateLimitPeriod(targetRefreshRate);
@ -791,7 +775,6 @@ float OpenGLDisplayPlugin::renderRate() const {
return _renderRate.rate();
}
void OpenGLDisplayPlugin::swapBuffers() {
static auto context = _container->getPrimaryWidget()->context();
context->swapBuffers();
@ -919,17 +902,10 @@ void OpenGLDisplayPlugin::render(std::function<void(gpu::Batch& batch)> f) {
OpenGLDisplayPlugin::~OpenGLDisplayPlugin() {
}
// Added this to allow desktop composite framebuffer to be RGBA while mobile is SRGBA
// Overridden by Basic2DWindowDisplayPlugin
// FIXME: Eventually it would be ideal to have both framebuffers be of the same type
gpu::Element OpenGLDisplayPlugin::getCompositeFBColorSpace() {
return gpu::Element::COLOR_RGBA_32;
}
void OpenGLDisplayPlugin::updateCompositeFramebuffer() {
auto renderSize = glm::uvec2(getRecommendedRenderSize());
if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) {
_compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", getCompositeFBColorSpace(), renderSize.x, renderSize.y));
_compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y));
}
}
@ -960,14 +936,13 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// maintain aspect ratio, filling the width first if possible. If that makes the height too
// much, fill height instead. TODO: only do this when texture changes
GLint newX = 0;
GLint newY = 0;
float aspectRatio = (float)texHeight / (float)texWidth;
GLint newWidth = target->width();
GLint newHeight = std::round(aspectRatio * (float) target->width());
GLint newHeight = std::round(aspectRatio * (float)target->width());
if (newHeight > target->height()) {
newHeight = target->height();
newWidth = std::round((float)target->height() / aspectRatio);
@ -976,7 +951,7 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
newY = (target->height() - newHeight) / 2;
}
glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newX + newWidth, newY + newHeight, GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newX + newWidth, newY + newHeight, GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, GL_NEAREST);
// don't delete the textures!
glDeleteFramebuffers(2, fbo);
@ -985,3 +960,11 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
#endif
}
gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() {
return _drawTexturePipeline;
}
gpu::PipelinePointer OpenGLDisplayPlugin::getCompositeScenePipeline() {
return _drawTexturePipeline;
}

View file

@ -23,11 +23,9 @@
#include <gpu/Batch.h>
namespace gpu {
namespace gl {
class GLBackend;
}
}
namespace gpu { namespace gl {
class GLBackend;
}} // namespace gpu::gl
class RefreshRateController;
@ -35,10 +33,12 @@ class OpenGLDisplayPlugin : public DisplayPlugin {
Q_OBJECT
Q_PROPERTY(float hudAlpha MEMBER _hudAlpha)
using Parent = DisplayPlugin;
protected:
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
using Condition = std::condition_variable;
public:
~OpenGLDisplayPlugin();
// These must be final to ensure proper ordering of operations
@ -55,13 +55,9 @@ public:
void captureFrame(const std::string& outputName) const override;
void submitFrame(const gpu::FramePointer& newFrame) override;
glm::uvec2 getRecommendedRenderSize() const override {
return getSurfacePixels();
}
glm::uvec2 getRecommendedRenderSize() const override { return getSurfacePixels(); }
glm::uvec2 getRecommendedUiSize() const override {
return getSurfaceSize();
}
glm::uvec2 getRecommendedUiSize() const override { return getSurfaceSize(); }
virtual bool setDisplayTexture(const QString& name) override;
virtual bool onDisplayTextureReset() { return false; };
@ -84,7 +80,10 @@ public:
// Three threads, one for rendering, one for texture transfers, one reserved for the GL driver
int getRequiredThreadCount() const override { return 3; }
void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override;
virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator() override;
void copyTextureToQuickFramebuffer(NetworkTexturePointer source,
QOpenGLFramebufferObject* target,
GLsync* fenceSync) override;
protected:
friend class PresentThread;
@ -102,12 +101,8 @@ protected:
virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; }
virtual void compositeLayers();
virtual void compositeScene();
virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator();
virtual void compositePointer();
virtual void compositeExtra() {};
virtual gpu::PipelinePointer getCompositeScenePipeline();
virtual gpu::Element getCompositeFBColorSpace();
virtual void compositeExtra(){};
// These functions must only be called on the presentation thread
virtual void customizeContext();
@ -124,8 +119,15 @@ protected:
// Plugin specific functionality to send the composed scene to the output window or device
virtual void internalPresent();
void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& fbo);
void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor);
void renderFromTexture(gpu::Batch& batch,
const gpu::TexturePointer& texture,
const glm::ivec4& viewport,
const glm::ivec4& scissor,
const gpu::FramebufferPointer& fbo);
void renderFromTexture(gpu::Batch& batch,
const gpu::TexturePointer& texture,
const glm::ivec4& viewport,
const glm::ivec4& scissor);
virtual void updateFrameData();
virtual glm::mat4 getViewCorrection() { return glm::mat4(); }
@ -137,7 +139,7 @@ protected:
void render(std::function<void(gpu::Batch& batch)> f);
bool _vsyncEnabled { true };
bool _vsyncEnabled{ true };
QThread* _presentThread{ nullptr };
std::queue<gpu::FramePointer> _newFrameQueue;
RateCounter<200> _droppedFrameRate;
@ -146,7 +148,7 @@ protected:
RateCounter<200> _renderRate;
gpu::FramePointer _currentFrame;
gpu::Frame* _lastFrame { nullptr };
gpu::Frame* _lastFrame{ nullptr };
mat4 _prevRenderView;
gpu::FramebufferPointer _compositeFramebuffer;
gpu::PipelinePointer _hudPipeline;
@ -156,9 +158,11 @@ protected:
gpu::PipelinePointer _linearToSRGBPipeline;
gpu::PipelinePointer _SRGBToLinearPipeline;
gpu::PipelinePointer _cursorPipeline;
gpu::TexturePointer _displayTexture{};
float _compositeHUDAlpha { 1.0f };
float _compositeHUDAlpha{ 1.0f };
virtual gpu::PipelinePointer getRenderTexturePipeline();
virtual gpu::PipelinePointer getCompositeScenePipeline();
struct CursorData {
QImage image;
@ -168,19 +172,19 @@ protected:
};
std::map<uint16_t, CursorData> _cursorsData;
bool _lockCurrentTexture { false };
bool _lockCurrentTexture{ false };
void assertNotPresentThread() const;
void assertIsPresentThread() const;
template<typename F>
template <typename F>
void withPresentThreadLock(F f) const {
assertIsPresentThread();
Lock lock(_presentMutex);
f();
}
template<typename F>
template <typename F>
void withNonPresentThreadLock(F f) const {
assertNotPresentThread();
Lock lock(_presentMutex);
@ -197,4 +201,3 @@ protected:
QImage getScreenshot(float aspectRatio);
QImage getSecondaryCameraScreenshot();
};

View file

@ -1,4 +1,4 @@
//
//
// Created by Bradley Austin Davis on 2016/02/15
// Copyright 2016 High Fidelity, Inc.
//
@ -402,25 +402,18 @@ void HmdDisplayPlugin::HUDRenderer::build() {
format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
format->setAttribute(gpu::Stream::TEXCOORD, gpu::Stream::TEXCOORD, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV));
uniformsBuffer = std::make_shared<gpu::Buffer>(sizeof(Uniforms), nullptr);
updatePipeline();
auto program = gpu::Shader::createProgram(shader::render_utils::program::hmd_ui);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(gpu::State::DepthTest(true, true, gpu::LESS_EQUAL));
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
pipeline = gpu::Pipeline::create(program, state);
}
void HmdDisplayPlugin::HUDRenderer::updatePipeline() {
if (!pipeline) {
auto program = gpu::Shader::createProgram(shader::render_utils::program::hmd_ui);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(gpu::State::DepthTest(true, true, gpu::LESS_EQUAL));
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
pipeline = gpu::Pipeline::create(program, state);
}
}
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) {
updatePipeline();
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDisplayPlugin::HUDRenderer::render() {
auto hudPipeline = pipeline;
auto hudFormat = format;
auto hudVertices = vertices;
@ -479,7 +472,7 @@ void HmdDisplayPlugin::compositePointer() {
}
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDisplayPlugin::getHUDOperator() {
return _hudRenderer.render(*this);
return _hudRenderer.render();
}
HmdDisplayPlugin::~HmdDisplayPlugin() {

View file

@ -48,6 +48,7 @@ public:
void pluginUpdate() override {};
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator() override;
virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::PAINT; }
signals:
@ -62,7 +63,6 @@ protected:
bool internalActivate() override;
void internalDeactivate() override;
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator() override;
void compositePointer() override;
void internalPresent() override;
void customizeContext() override;
@ -105,7 +105,7 @@ private:
gpu::BufferPointer vertices;
gpu::BufferPointer indices;
uint32_t indexCount { 0 };
gpu::PipelinePointer pipeline;
gpu::PipelinePointer pipeline { nullptr };
gpu::BufferPointer uniformsBuffer;
@ -123,7 +123,6 @@ private:
static const int VERTEX_STRIDE { sizeof(Vertex) };
void build();
void updatePipeline();
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> render(HmdDisplayPlugin& plugin);
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> render();
} _hudRenderer;
};

View file

@ -207,7 +207,7 @@ void EntityTreeRenderer::stopDomainAndNonOwnedEntities() {
if (entityItem && !entityItem->getScript().isEmpty()) {
if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
if (entityItem->contains(_avatarPosition)) {
if (_currentEntitiesInside.contains(entityID)) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
}
_entitiesScriptEngine->unloadEntityScript(entityID, true);
@ -222,6 +222,7 @@ void EntityTreeRenderer::clearDomainAndNonOwnedEntities() {
auto sessionUUID = getTree()->getMyAvatarSessionUUID();
std::unordered_map<EntityItemID, EntityRendererPointer> savedEntities;
std::unordered_set<EntityRendererPointer> savedRenderables;
// remove all entities from the scene
auto scene = _viewState->getMain3DScene();
if (scene) {
@ -232,11 +233,12 @@ void EntityTreeRenderer::clearDomainAndNonOwnedEntities() {
fadeOutRenderable(renderer);
} else {
savedEntities[entry.first] = entry.second;
savedRenderables.insert(entry.second);
}
}
}
_renderablesToUpdate = savedEntities;
_renderablesToUpdate = savedRenderables;
_entitiesInScene = savedEntities;
if (_layeredZones.clearDomainAndNonOwnedZones(sessionUUID)) {
@ -256,18 +258,28 @@ void EntityTreeRenderer::clear() {
}
// reset the engine
if (_wantScripts && !_shuttingDown) {
resetEntitiesScriptEngine();
}
// remove all entities from the scene
auto scene = _viewState->getMain3DScene();
if (scene) {
for (const auto& entry : _entitiesInScene) {
const auto& renderer = entry.second;
fadeOutRenderable(renderer);
if (_shuttingDown) {
if (scene) {
render::Transaction transaction;
for (const auto& entry : _entitiesInScene) {
const auto& renderer = entry.second;
renderer->removeFromScene(scene, transaction);
}
scene->enqueueTransaction(transaction);
}
} else {
qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown";
if (_wantScripts) {
resetEntitiesScriptEngine();
}
if (scene) {
for (const auto& entry : _entitiesInScene) {
const auto& renderer = entry.second;
fadeOutRenderable(renderer);
}
} else {
qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene";
}
}
_entitiesInScene.clear();
_renderablesToUpdate.clear();
@ -379,13 +391,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
PerformanceTimer pt("change");
std::unordered_set<EntityItemID> changedEntities;
_changedEntitiesGuard.withWriteLock([&] {
#if 0
// FIXME Weird build failure in latest VC update that fails to compile when using std::swap
changedEntities.swap(_changedEntities);
#else
changedEntities.insert(_changedEntities.begin(), _changedEntities.end());
_changedEntities.clear();
#endif
});
{
@ -394,7 +400,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
auto renderable = renderableForEntityId(entityId);
if (renderable) {
// only add valid renderables _renderablesToUpdate
_renderablesToUpdate.insert({ entityId, renderable });
_renderablesToUpdate.insert(renderable);
}
}
}
@ -404,8 +410,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
// we expect to update all renderables within available time budget
PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
uint64_t updateStart = usecTimestampNow();
for (const auto& entry : _renderablesToUpdate) {
const auto& renderable = entry.second;
for (const auto& renderable : _renderablesToUpdate) {
assert(renderable); // only valid renderables are added to _renderablesToUpdate
renderable->updateInScene(scene, transaction);
}
@ -414,8 +419,8 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
// compute average per-renderable update cost
float cost = (float)(usecTimestampNow() - updateStart) / (float)(numRenderables);
const float blend = 0.1f;
_avgRenderableUpdateCost = (1.0f - blend) * _avgRenderableUpdateCost + blend * cost;
const float BLEND = 0.1f;
_avgRenderableUpdateCost = (1.0f - BLEND) * _avgRenderableUpdateCost + BLEND * cost;
} else {
// we expect the cost to updating all renderables to exceed available time budget
// so we first sort by priority and update in order until out of time
@ -440,43 +445,40 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
PrioritySortUtil::PriorityQueue<SortableRenderer> sortedRenderables(views);
sortedRenderables.reserve(_renderablesToUpdate.size());
{
PROFILE_RANGE_EX(simulation_physics, "SortRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
std::unordered_map<EntityItemID, EntityRendererPointer>::iterator itr = _renderablesToUpdate.begin();
while (itr != _renderablesToUpdate.end()) {
assert(itr->second); // only valid renderables are added to _renderablesToUpdate
sortedRenderables.push(SortableRenderer(itr->second));
++itr;
PROFILE_RANGE_EX(simulation_physics, "BuildSortedRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
for (const auto& renderable : _renderablesToUpdate) {
assert(renderable); // only valid renderables are added to _renderablesToUpdate
sortedRenderables.push(SortableRenderer(renderable));
}
}
{
PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, sortedRenderables.size());
PROFILE_RANGE_EX(simulation_physics, "SortAndUpdateRenderables", 0xffff00ff, sortedRenderables.size());
// compute remaining time budget
const auto& sortedRenderablesVector = sortedRenderables.getSortedVector();
uint64_t updateStart = usecTimestampNow();
uint64_t timeBudget = MIN_SORTED_UPDATE_RENDERABLES_TIME_BUDGET;
uint64_t sortCost = updateStart - sortStart;
uint64_t timeBudget = MIN_SORTED_UPDATE_RENDERABLES_TIME_BUDGET;
if (sortCost < MAX_UPDATE_RENDERABLES_TIME_BUDGET - MIN_SORTED_UPDATE_RENDERABLES_TIME_BUDGET) {
timeBudget = MAX_UPDATE_RENDERABLES_TIME_BUDGET - sortCost;
}
uint64_t expiry = updateStart + timeBudget;
// process the sorted renderables
size_t numSorted = sortedRenderables.size();
const auto& sortedRenderablesVector = sortedRenderables.getSortedVector();
for (const auto& sortedRenderable : sortedRenderablesVector) {
if (usecTimestampNow() > expiry) {
break;
}
const auto& renderable = sortedRenderable.getRenderer();
renderable->updateInScene(scene, transaction);
_renderablesToUpdate.erase(renderable->getEntity()->getID());
_renderablesToUpdate.erase(renderable);
}
// compute average per-renderable update cost
size_t numUpdated = numSorted - sortedRenderables.size() + 1; // add one to avoid divide by zero
size_t numUpdated = sortedRenderables.size() - _renderablesToUpdate.size() + 1; // add one to avoid divide by zero
float cost = (float)(usecTimestampNow() - updateStart) / (float)(numUpdated);
const float blend = 0.1f;
_avgRenderableUpdateCost = (1.0f - blend) * _avgRenderableUpdateCost + blend * cost;
const float BLEND = 0.1f;
_avgRenderableUpdateCost = (1.0f - BLEND) * _avgRenderableUpdateCost + BLEND * cost;
}
}
}
@ -980,7 +982,6 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
// If it's in a pending queue, remove it
_renderablesToUpdate.erase(entityID);
_entitiesToAdd.erase(entityID);
auto itr = _entitiesInScene.find(entityID);
@ -990,7 +991,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
}
if (_tree && !_shuttingDown && _entitiesScriptEngine && !itr->second->getEntity()->getScript().isEmpty()) {
if (itr->second->getEntity()->contains(_avatarPosition)) {
if (_currentEntitiesInside.contains(entityID)) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
}
_entitiesScriptEngine->unloadEntityScript(entityID, true);
@ -1003,6 +1004,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
}
auto renderable = itr->second;
_renderablesToUpdate.erase(renderable);
_entitiesInScene.erase(itr);
if (!renderable) {
@ -1037,7 +1039,7 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool
QString scriptUrl = entity->getScript();
if ((shouldLoad && unloadFirst) || scriptUrl.isEmpty()) {
if (_entitiesScriptEngine) {
if (entity->contains(_avatarPosition)) {
if (_currentEntitiesInside.contains(entityID)) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
}
_entitiesScriptEngine->unloadEntityScript(entityID);
@ -1056,10 +1058,14 @@ void EntityTreeRenderer::fadeOutRenderable(const EntityRendererPointer& renderab
render::Transaction transaction;
auto scene = _viewState->getMain3DScene();
transaction.setTransitionFinishedOperator(renderable->getRenderItemID(), [scene, renderable]() {
render::Transaction transaction;
renderable->removeFromScene(scene, transaction);
scene->enqueueTransaction(transaction);
EntityRendererWeakPointer weakRenderable = renderable;
transaction.setTransitionFinishedOperator(renderable->getRenderItemID(), [scene, weakRenderable]() {
auto renderable = weakRenderable.lock();
if (renderable) {
render::Transaction transaction;
renderable->removeFromScene(scene, transaction);
scene->enqueueTransaction(transaction);
}
});
scene->enqueueTransaction(transaction);

View file

@ -246,7 +246,7 @@ private:
ReadWriteLockable _changedEntitiesGuard;
std::unordered_set<EntityItemID> _changedEntities;
std::unordered_map<EntityItemID, EntityRendererPointer> _renderablesToUpdate;
std::unordered_set<EntityRendererPointer> _renderablesToUpdate;
std::unordered_map<EntityItemID, EntityRendererPointer> _entitiesInScene;
std::unordered_map<EntityItemID, EntityItemWeakPointer> _entitiesToAdd;

View file

@ -70,7 +70,7 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
return true;
}
if (_color != entity->getColor()) {
if (_color != toGlm(entity->getColor())) {
return true;
}
if (_alpha != entity->getAlpha()) {
@ -130,12 +130,12 @@ void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
}
});
glm::u8vec3 color = entity->getColor();
glm::vec3 color = toGlm(entity->getColor());
float alpha = entity->getAlpha();
if (_color != color || _alpha != alpha) {
_color = color;
_alpha = alpha;
_material->setAlbedo(toGlm(_color));
_material->setAlbedo(color);
_material->setOpacity(_alpha);
auto materials = _materials.find("0");

View file

@ -43,7 +43,7 @@ private:
PulsePropertyGroup _pulseProperties;
std::shared_ptr<graphics::Material> _material { std::make_shared<graphics::Material>() };
glm::u8vec3 _color;
glm::vec3 _color { NAN };
float _alpha;
glm::vec3 _position;

View file

@ -7,6 +7,7 @@
//
#include "RenderableWebEntityItem.h"
#include <atomic>
#include <QtCore/QTimer>
#include <QtGui/QOpenGLContext>
@ -46,7 +47,7 @@ static uint64_t MAX_NO_RENDER_INTERVAL = 30 * USECS_PER_SECOND;
static uint8_t YOUTUBE_MAX_FPS = 30;
// Don't allow more than 20 concurrent web views
static uint32_t _currentWebCount { 0 };
static std::atomic<uint32_t> _currentWebCount(0);
static const uint32_t MAX_CONCURRENT_WEB_VIEWS = 20;
static QTouchDevice _touchDevice;
@ -356,16 +357,15 @@ void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const Q
void WebEntityRenderer::destroyWebSurface() {
QSharedPointer<OffscreenQmlSurface> webSurface;
ContentType contentType = ContentType::NoContent;
withWriteLock([&] {
webSurface.swap(_webSurface);
_contentType = contentType;
});
_contentType = ContentType::NoContent;
if (webSurface) {
--_currentWebCount;
WebEntityRenderer::releaseWebSurface(webSurface, _cachedWebSurface, _connections);
}
if (webSurface) {
--_currentWebCount;
WebEntityRenderer::releaseWebSurface(webSurface, _cachedWebSurface, _connections);
}
});
}
glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) const {

View file

@ -28,7 +28,7 @@ class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
/**jsdoc
* Ambient light is defined by the following properties.
* Ambient light is defined by the following properties:
* @typedef {object} Entities.AmbientLight
* @property {number} ambientIntensity=0.5 - The intensity of the light.
* @property {string} ambientURL="" - A cube map image that defines the color of the light coming from each direction. If

View file

@ -48,16 +48,18 @@ bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b
/**jsdoc
* The AnimationProperties are used to configure an animation.
* An animation is configured by the following properties:
* @typedef {object} Entities.AnimationProperties
* @property {string} url="" - The URL of the FBX file that has the animation.
* @property {boolean} allowTranslation=true - <code>true</code> to enable translations contained in the animation to be
* played, <code>false</code> to disable translations.
* @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.
* @property {number} lastFrame=100000 - The last frame to play in the animation.
* @property {number} currentFrame=0 - The current frame being played in the animation.
* @property {boolean} running=false - If <code>true</code> then the animation should play.
* @property {boolean} loop=true - If <code>true</code> then the animation should be continuously repeated in a loop.
* @property {boolean} hold=false - If <code>true</code> then the rotations and translations of the last frame played should be
* @property {boolean} loop=true - If <code>true</code> then the animation is continuously repeated in a loop.
* @property {boolean} hold=false - If <code>true</code> then the rotations and translations of the last frame played are
* maintained when the animation stops playing.
*/
void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {

View file

@ -31,9 +31,8 @@ static const float INITIAL_BLOOM_THRESHOLD { 0.7f };
static const float INITIAL_BLOOM_SIZE { 0.9f };
/**jsdoc
* Bloom is defined by the following properties.
* Bloom is defined by the following properties:
* @typedef {object} Entities.Bloom
*
* @property {number} bloomIntensity=0.25 - The intensity of the bloom effect.
* @property {number} bloomThreshold=0.7 - The threshold for the bloom effect.
* @property {number} bloomSize=0.9 - The size of the bloom effect.

View file

@ -94,47 +94,48 @@ variables. These argument variables are used by the code which is run when bull
#include "EntityItem.h"
/**jsdoc
* <p>An entity action may be one of the following types:</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Type</th><th>Description</th><th>Arguments</th></tr>
* </thead>
* <tbody>
* <tr><td><code>"far-grab"</code></td><td>Avatar action</td>
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity. Collisions
* between the entity and the user's avatar are disabled during the far-grab.</td>
* <td>{@link Entities.ActionArguments-FarGrab}</td></tr>
* <tr><td><code>"hold"</code></td><td>Avatar action</td>
* <td>Positions and rotates an entity relative to an avatar's hand. Collisions between the entity and the user's avatar
* are disabled during the hold.</td>
* <td>{@link Entities.ActionArguments-Hold}</td></tr>
* <tr><td><code>"offset"</code></td><td>Object action</td>
* <td>Moves an entity so that it is a set distance away from a target point.</td>
* <td>{@link Entities.ActionArguments-Offset}</td></tr>
* <tr><td><code>"tractor"</code></td><td>Object action</td>
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity.</td>
* <td>{@link Entities.ActionArguments-Tractor}</td></tr>
* <tr><td><code>"travel-oriented"</code></td><td>Object action</td>
* <td>Orients an entity to align with its direction of travel.</td>
* <td>{@link Entities.ActionArguments-TravelOriented}</td></tr>
* <tr><td><code>"hinge"</code></td><td>Object constraint</td>
* <td>Lets an entity pivot about an axis or connects two entities with a hinge joint.</td>
* <td>{@link Entities.ActionArguments-Hinge}</td></tr>
* <tr><td><code>"slider"</code></td><td>Object constraint</td>
* <td>Lets an entity slide and rotate along an axis, or connects two entities that slide and rotate along a shared
* axis.</td>
* <td>{@link Entities.ActionArguments-Slider|ActionArguments-Slider}</td></tr>
* <tr><td><code>"cone-twist"</code></td><td>Object constraint</td>
* <td>Connects two entities with a joint that can move through a cone and can twist.</td>
* <td>{@link Entities.ActionArguments-ConeTwist}</td></tr>
* <tr><td><code>"ball-socket"</code></td><td>Object constraint</td>
* <td>Connects two entities with a ball and socket joint.</td>
* <td>{@link Entities.ActionArguments-BallSocket}</td></tr>
* <tr><td><code>"spring"</code></td><td colspan="3">Synonym for <code>"tractor"</code>. <em>Legacy value.</em></td></tr>
* </tbody>
* </table>
* @typedef {string} Entities.ActionType
*/
* <p>An entity action may be one of the following types:</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Type</th><th>Description</th><th>Arguments</th></tr>
* </thead>
* <tbody>
* <tr><td><code>"far-grab"</code></td><td>Avatar action</td>
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity. Collisions
* between the entity and the user's avatar are disabled during the far-grab.</td>
* <td>{@link Entities.ActionArguments-FarGrab}</td></tr>
* <tr><td><code>"hold"</code></td><td>Avatar action</td>
* <td>Positions and rotates an entity relative to an avatar's hand. Collisions between the entity and the user's avatar
* are disabled during the hold.</td>
* <td>{@link Entities.ActionArguments-Hold}</td></tr>
* <tr><td><code>"offset"</code></td><td>Object action</td>
* <td>Moves an entity so that it is a set distance away from a target point.</td>
* <td>{@link Entities.ActionArguments-Offset}</td></tr>
* <tr><td><code>"tractor"</code></td><td>Object action</td>
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity.</td>
* <td>{@link Entities.ActionArguments-Tractor}</td></tr>
* <tr><td><code>"travel-oriented"</code></td><td>Object action</td>
* <td>Orients an entity to align with its direction of travel.</td>
* <td>{@link Entities.ActionArguments-TravelOriented}</td></tr>
* <tr><td><code>"hinge"</code></td><td>Object constraint</td>
* <td>Lets an entity pivot about an axis or connects two entities with a hinge joint.</td>
* <td>{@link Entities.ActionArguments-Hinge}</td></tr>
* <tr><td><code>"slider"</code></td><td>Object constraint</td>
* <td>Lets an entity slide and rotate along an axis, or connects two entities that slide and rotate along a shared
* axis.</td>
* <td>{@link Entities.ActionArguments-Slider|ActionArguments-Slider}</td></tr>
* <tr><td><code>"cone-twist"</code></td><td>Object constraint</td>
* <td>Connects two entities with a joint that can move through a cone and can twist.</td>
* <td>{@link Entities.ActionArguments-ConeTwist}</td></tr>
* <tr><td><code>"ball-socket"</code></td><td>Object constraint</td>
* <td>Connects two entities with a ball and socket joint.</td>
* <td>{@link Entities.ActionArguments-BallSocket}</td></tr>
* <tr><td><code>"spring"</code></td><td colspan="3">Synonym for <code>"tractor"</code>.
* <span class="important">Deprecated.</span></td></tr>
* </tbody>
* </table>
* @typedef {string} Entities.ActionType
*/
// Note: The "none" action type is not listed because it's an internal "uninitialized" value and not useful for scripts.
EntityDynamicType EntityDynamicInterface::dynamicTypeFromString(QString dynamicTypeString) {
QString normalizedDynamicTypeString = dynamicTypeString.toLower().remove('-').remove('_');

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2121,9 +2121,10 @@ void EntityTree::fixupNeedsParentFixups() {
_needsParentFixup.clear();
}
std::unordered_set<QUuid> seenEntityIds;
QMutableVectorIterator<EntityItemWeakPointer> iter(entitiesToFixup);
while (iter.hasNext()) {
EntityItemWeakPointer entityWP = iter.next();
const auto& entityWP = iter.next();
EntityItemPointer entity = entityWP.lock();
if (!entity) {
// entity was deleted before we found its parent
@ -2131,6 +2132,17 @@ void EntityTree::fixupNeedsParentFixups() {
continue;
}
const auto id = entity->getID();
// BUGZ-771 some entities seem to never be removed by the below logic and further seem to accumulate dupes within the _needsParentFixup list
// This block ensures that duplicates are removed from entitiesToFixup before it's re-appended to _needsParentFixup
if (0 != seenEntityIds.count(id)) {
// Entity was duplicated inside entitiesToFixup
iter.remove();
continue;
}
seenEntityIds.insert(id);
entity->requiresRecalcBoxes();
bool queryAACubeSuccess { false };
bool maxAACubeSuccess { false };

View file

@ -42,7 +42,10 @@ public:
* <tr><th>Value</th><th>Description</th><th>Properties</th></tr>
* </thead>
* <tbody>
* <tr><td><code>"Box"</code></td><td>A rectangular prism. This is a synonym of <code>"Shape"</code> for the case
* <tr><td><code>"Shape"</code></td><td>A basic entity such as a cube.
* See also, the <code>"Box"</code> and <code>"Sphere"</code> entity types.</td>
* <td>{@link Entities.EntityProperties-Shape|EntityProperties-Shape}</td></tr>
* <tr><td><code>"Box"</code></td><td>A rectangular prism. This is a synonym of <code>"Shape"</code> for the case
* where the entity's <code>shape</code> property value is <code>"Cube"</code>.<br />
* If an entity is created with its <code>type</code>
* set to <code>"Box"</code> it will always be created with a <code>shape</code> property value of
@ -56,16 +59,13 @@ public:
* <code>"Sphere"</code>. If an entity of type <code>Box</code> or <code>Shape</code> has its <code>shape</code> set
* to <code>"Sphere"</code> then its <code>type</code> will be reported as <code>"Sphere"</code>.
* <td>{@link Entities.EntityProperties-Sphere|EntityProperties-Sphere}</td></tr>
* <tr><td><code>"Shape"</code></td><td>A basic entity such as a cube.
* See also, the <code>"Box"</code> and <code>"Sphere"</code> entity types.</td>
* <td>{@link Entities.EntityProperties-Shape|EntityProperties-Shape}</td></tr>
* <tr><td><code>"Model"</code></td><td>A mesh model from an FBX or OBJ file.</td>
* <tr><td><code>"Model"</code></td><td>A mesh model from a glTf, FBX, or OBJ file.</td>
* <td>{@link Entities.EntityProperties-Model|EntityProperties-Model}</td></tr>
* <tr><td><code>"Text"</code></td><td>A pane of text oriented in space.</td>
* <td>{@link Entities.EntityProperties-Text|EntityProperties-Text}</td></tr>
* <tr><td><code>"Image"</code></td><td>An image oriented in space.</td>
* <td>{@link Entities.EntityProperties-Image|EntityProperties-Image}</td></tr>
* <tr><td><code>"Web"</code></td><td>A browsable Web page.</td>
* <tr><td><code>"Web"</code></td><td>A browsable web page.</td>
* <td>{@link Entities.EntityProperties-Web|EntityProperties-Web}</td></tr>
* <tr><td><code>"ParticleEffect"</code></td><td>A particle system that can be used to simulate things such as fire,
* smoke, snow, magic spells, etc.</td>
@ -78,7 +78,7 @@ public:
* <td>{@link Entities.EntityProperties-PolyVox|EntityProperties-PolyVox}</td></tr>
* <tr><td><code>"Grid"</code></td><td>A grid of lines in a plane.</td>
* <td>{@link Entities.EntityProperties-Grid|EntityProperties-Grid}</td></tr>
* <tr><td><code>"Gizmo"</code></td><td>An entity with various UI-related properties.</td>
* <tr><td><code>"Gizmo"</code></td><td>A gizmo intended for UI.</td>
* <td>{@link Entities.EntityProperties-Gizmo|EntityProperties-Gizmo}</td></tr>
* <tr><td><code>"Light"</code></td><td>A local lighting effect.</td>
* <td>{@link Entities.EntityProperties-Light|EntityProperties-Light}</td></tr>

View file

@ -41,35 +41,33 @@ static const glm::vec3 INITIAL_EQUIPPABLE_INDICATOR_OFFSET { glm::vec3(0.0f) };
/**jsdoc
* Grab is defined by the following properties.
* Grabbing behavior is defined by the following properties:
*
* @typedef {object} Entities.Grab
*
* @property {boolean} grabbable=true - If <code>true</code> the entity can be grabbed.
* @property {boolean} grabKinematic=true - If <code>true</code> the entity is updated in a kinematic manner.
* If <code>false</code> it will be grabbed using a tractor action. A kinematic grab will make the item appear more
* tightly held, but will cause it to behave poorly when interacting with dynamic entities.
* @property {boolean} grabFollowsController=true - If <code>true</code> the entity will follow the motions of the
* hand-controller even if the avatar's hand can't get to the implied position. This should be <code>true</code>
* for tools, pens, etc and false for things meant to decorate the hand.
*
* @property {boolean} triggerable=false - If <code>true</code> the entity will receive calls to trigger
* @property {boolean} grabbable=true - If <code>true</code> then the entity can be grabbed.
* @property {boolean} grabKinematic=true - If <code>true</code> then the entity will be updated in a kinematic manner when
* grabbed; if <code>false</code> it will be grabbed using a tractor action. A kinematic grab will make the item appear
* more tightly held but will cause it to behave poorly when interacting with dynamic entities.
* @property {boolean} grabFollowsController=true - If <code>true</code> then the entity will follow the motions of the hand
* controller even if the avatar's hand can't get to the implied position. This should be set <code>true</code> for tools,
* pens, etc. and <code>false</code> for things meant to decorate the hand.
* @property {boolean} triggerable=false - If <code>true</code> then the entity will receive calls to trigger
* {@link Controller|Controller entity methods}.
*
* @property {boolean} equippable=true - If <code>true</code> the entity can be equipped.
* @property {boolean} grabDelegateToParent=true - If <code>true</code> and the entity is grabbed, the grab will be transferred
* to its parent entity if there is one; if <code>false</code>, a child entity can be grabbed and moved relative to its
* parent.
* @property {boolean} equippable=true - If <code>true</code> then the entity can be equipped.
* @property {Vec3} equippableLeftPosition=0,0,0 - Positional offset from the left hand, when equipped.
* @property {Quat} equippableLeftRotation=0,0,0,1 - Rotational offset from the left hand, when equipped.
* @property {Vec3} equippableRightPosition=0,0,0 - Positional offset from the right hand, when equipped.
* @property {Quat} equippableRightRotation=0,0,0,1 - Rotational offset from the right hand, when equipped.
*
* @property {string} equippableIndicatorURL="" - If non-empty, this model will be used to indicate that an
* entity is equippable, rather than the default.
* @property {Vec3} equippableIndicatorScale=1,1,1 - If equippableIndicatorURL is non-empty, this controls the
* @property {Vec3} equippableIndicatorScale=1,1,1 - If <code>equippableIndicatorURL</code> is non-empty, this controls the
scale of the displayed indicator.
* @property {Vec3} equippableIndicatorOffset=0,0,0 - If equippableIndicatorURL is non-empty, this controls the
* @property {Vec3} equippableIndicatorOffset=0,0,0 - If <code>equippableIndicatorURL</code> is non-empty, this controls the
relative offset of the displayed object from the equippable entity.
*/
class GrabPropertyGroup : public PropertyGroup {
public:
// EntityItemProperty related helpers

View file

@ -43,7 +43,7 @@ static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f };
// FIXME: Document hazeAttenuationKeyLight, hazeKeyLightRange, and hazeKeyLightAltitude once they're working and are provided
// in the Create app's UI.
/**jsdoc
* Haze is defined by the following properties.
* Haze is defined by the following properties:
* @typedef {object} Entities.Haze
*
* @property {number} hazeRange=1000 - The horizontal distance at which visibility is reduced to 95%; i.e., 95% of each pixel's
@ -56,7 +56,7 @@ static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f };
* haze color are blended 50/50.
*
* @property {boolean} hazeAltitudeEffect=false - If <code>true</code> then haze decreases with altitude as defined by the
* entity's local coordinate system; <code>hazeBaseRef</code> and </code>hazeCeiling</code> are used.
* entity's local coordinate system; <code>hazeBaseRef</code> and <code>hazeCeiling</code> are used.
* @property {number} hazeBaseRef=0 - The y-axis value in the entity's local coordinate system at which the haze density starts
* reducing with altitude.
* @property {number} hazeCeiling=200 - The y-axis value in the entity's local coordinate system at which the haze density has
@ -65,9 +65,11 @@ static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f };
* @property {number} hazeBackgroundBlend=0 - The proportion of the skybox image to show through the haze: <code>0.0</code>
* displays no skybox image; <code>1.0</code> displays no haze.
*
* @property {boolean} hazeAttenuateKeyLight=false - <em>Currently not supported.</em>
* @property {number} hazeKeyLightRange=1000 - <em>Currently not supported.</em>
* @property {number} hazeKeyLightAltitude=200 - <em>Currently not supported.</em>
* @property {boolean} hazeAttenuateKeyLight=false - If <code>true</code> then the haze attenuates the key light;
* <code>hazeKeyLightRange</code> and <code>hazeKeyLightAltitude</code> are used.
* @property {number} hazeKeyLightRange=1000 - The distance at which the haze attenuates the key light by 95%.
* @property {number} hazeKeyLightAltitude=200 - The altitude at which the haze starts attenuating the key light (i.e., the
* altitude at which the distance starts being calculated).
*/
class HazePropertyGroup : public PropertyGroup {
public:

View file

@ -28,13 +28,13 @@ class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
/**jsdoc
* A key light is defined by the following properties.
* A key light is defined by the following properties:
* @typedef {object} Entities.KeyLight
* @property {Color} color=255,255,255 - The color of the light.
* @property {number} intensity=1 - The intensity of the light.
* @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
* {@link Entities.EntityProperties-Model|Model} and {@link Entities.EntityProperties-Shape|Shape} entities that have their
* <code>{@link Entities.EntityProperties|canCastShadow}</code> property set to <code>true</code>.
*/
class KeyLightPropertyGroup : public PropertyGroup {

View file

@ -63,7 +63,7 @@ class PolyVoxEntityItem : public EntityItem {
virtual int getOnCount() const { return 0; }
/**jsdoc
* <p>A <code>PolyVoxSurfaceStyle</code> may be one of the following:</p>
* <p>The surface of a {@link Entities.EntityProperties-PolyVox|PolyVox} entity may be one of the following styles:</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Type</th><th>Description</th></tr>

View file

@ -26,19 +26,17 @@ class OctreePacketData;
class ReadBitstreamToTreeParams;
/**jsdoc
* Pulse is defined by the following properties.
* A color and alpha pulse that an entity may have.
* @typedef {object} Entities.Pulse
*
* @property {number} min=0 - The minimum value of the pulse multiplier.
* @property {number} max=1 - The maximum value of the pulse multiplier.
* @property {number} period=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
* <code>min</code> to <code>max</code>, then <code>max</code> to <code>min</code> in one period.
* @property {PulseMode} colorMode="none" - If "in", the color is pulsed in phase with the pulse period; if "out"
* @property {Entities.PulseMode} colorMode="none" - If "in", the color is pulsed in phase with the pulse period; if "out"
* the color is pulsed out of phase with the pulse period.
* @property {PulseMode} alphaMode="none" - If "in", the alpha is pulsed in phase with the pulse period; if "out"
* @property {Entities.PulseMode} alphaMode="none" - If "in", the alpha is pulsed in phase with the pulse period; if "out"
* the alpha is pulsed out of phase with the pulse period.
*/
class PulsePropertyGroup : public PropertyGroup {
public:
// EntityItemProperty related helpers

View file

@ -25,31 +25,32 @@ class ReadBitstreamToTreeParams;
using u8vec3Color = glm::u8vec3;
/**jsdoc
* A RingGizmo is defined by the following properties.
* A {@link Entities.EntityProperties-Gizmo|ring Gizmo} entity is defined by the following properties:
* @typedef {object} Entities.RingGizmo
*
* @property {number} startAngle=0 - The angle at which the ring will start, in degrees.
* @property {number} endAngle=360 - The angle at which the ring will end, in degrees.
* @property {number} innerRadius=0 - The inner radius of the ring as a fraction of the total radius. 0-1.
* @property {number} startAngle=0 - The angle at which the ring starts, in degrees.
* @property {number} endAngle=360 - The angle at which the ring ends, in degrees.
* @property {number} innerRadius=0 - The inner radius of the ring as a fraction of the total radius, range <code>0.0</code>
* &mdash; <code>1.0</code>.
* @property {Color} innerStartColor - The color at the inner start point of the ring.
* @property {Color} innerEndColor - The color at the inner end point of the ring.
* @property {Color} outerStartColor - The color at the outer start point of the ring.
* @property {Color} outerEndColor - The color at the outer end point of the ring.
* @property {number} innerStartAlpha=1 - The alpha at the inner start point of the ring.
* @property {number} innerEndAlpha=1 - The alpha at the inner end point of the ring.
* @property {number} outerStartAlpha=1 - The alpha at the outer start point of the ring.
* @property {number} outerEndAlpha=1 - The alpha at the outer end point of the ring.
* @property {Color} innerStartColor=255,255,255 - The color at the inner start point of the ring.
* @property {Color} innerEndColor=255,255,255 - The color at the inner end point of the ring.
* @property {Color} outerStartColor=255,255,255 - The color at the outer start point of the ring.
* @property {Color} outerEndColor=255,255,255 - The color at the outer end point of the ring.
* @property {number} innerStartAlpha=1 - The opacity at the inner start point of the ring.
* @property {number} innerEndAlpha=1 - The opacity at the inner end point of the ring.
* @property {number} outerStartAlpha=1 - The opacity at the outer start point of the ring.
* @property {number} outerEndAlpha=1 - The opacity at the outer end point of the ring.
* @property {boolean} hasTickMarks=false - Whether or not to render tick marks.
* @property {number} majorTickMarksAngle - The angle between major tick marks, in degrees.
* @property {number} minorTickMarksAngle - The angle between minor tick marks, in degrees.
* @property {number} majorTickMarksLength - The length of the major tick marks, as a fraction of the radius. A positive value draws tick marks
* outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
* @property {number} minorTickMarksLength - The length of the minor tick marks, as a fraction of the radius. A positive value draws tick marks
* outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
* @property {Color} majorTickMarksColor - The color of the major tick marks.
* @property {Color} minorTickMarksColor - The color of the minor tick marks.
* @property {boolean} hasTickMarks=false - <code>true</code> to render tick marks, otherwise <code>false</code>.
* @property {number} majorTickMarksAngle=0 - The angle between major tick marks, in degrees.
* @property {number} minorTickMarksAngle=0 - The angle between minor tick marks, in degrees.
* @property {number} majorTickMarksLength=0 - The length of the major tick marks as a fraction of the radius. A positive value
* draws tick marks outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
* @property {number} minorTickMarksLength=0 - The length of the minor tick marks, as a fraction of the radius. A positive
* value draws tick marks outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
* @property {Color} majorTickMarksColor=255,255,255 - The color of the major tick marks.
* @property {Color} minorTickMarksColor=255,255,255 - The color of the minor tick marks.
*/
class RingGizmoPropertyGroup : public PropertyGroup {

View file

@ -22,8 +22,8 @@
namespace entity {
/**jsdoc
* <p>A <code>Shape</code>, <code>Box</code>, or <code>Sphere</code> {@link Entities.EntityType|EntityType} may display as
* one of the following geometrical shapes:</p>
* <p>A <code>"Shape"</code>, <code>"Box"</code>, or <code>"Sphere"</code> {@link Entities.EntityType|EntityType} may
* display as one of the following geometrical shapes:</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Dimensions</th><th>Notes</th></tr>

View file

@ -30,7 +30,7 @@ class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
/**jsdoc
* A skybox is defined by the following properties.
* A skybox is defined by the following properties:
* @typedef {object} Entities.Skybox
* @property {Color} color=0,0,0 - Sets the color of the sky if <code>url</code> is <code>""</code>, otherwise modifies the
* color of the cube map image.

View file

@ -27,6 +27,10 @@
#include "GLHelpers.h"
#include "QOpenGLContextWrapper.h"
#if defined(GL_CUSTOM_CONTEXT)
#include <QtPlatformHeaders/QWGLNativeContext>
#endif
using namespace gl;
#if defined(GL_CUSTOM_CONTEXT)
@ -42,7 +46,10 @@ std::atomic<size_t> Context::_totalSwapchainMemoryUsage { 0 };
size_t Context::getSwapchainMemoryUsage() { return _totalSwapchainMemoryUsage.load(); }
size_t Context::evalSurfaceMemoryUsage(uint32_t width, uint32_t height, uint32_t pixelSize) {
return width * height * pixelSize;
size_t result = width;
result *= height;
result *= pixelSize;
return result;
}
void Context::updateSwapchainMemoryUsage(size_t prevSize, size_t newSize) {
@ -126,7 +133,7 @@ void Context::clear() {
#if defined(GL_CUSTOM_CONTEXT)
static void setupPixelFormatSimple(HDC hdc) {
// FIXME build the PFD based on the
// FIXME build the PFD based on the
static const PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
@ -176,6 +183,7 @@ static void setupPixelFormatSimple(HDC hdc) {
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
// Context create flag bits
#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
@ -196,17 +204,17 @@ GLAPI PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context();
#if defined(GL_CUSTOM_CONTEXT)
bool Context::makeCurrent() {
BOOL result = wglMakeCurrent(_hdc, _hglrc);
assert(result);
updateSwapchainMemoryCounter();
return result;
}
void Context::swapBuffers() {
SwapBuffers(_hdc);
}
void Context::doneCurrent() {
wglMakeCurrent(0, 0);
bool Context::makeCurrent() {
BOOL result = wglMakeCurrent(_hdc, _hglrc);
assert(result);
updateSwapchainMemoryCounter();
return result;
}
void Context::swapBuffers() {
SwapBuffers(_hdc);
}
void Context::doneCurrent() {
wglMakeCurrent(0, 0);
}
#endif
@ -305,11 +313,18 @@ void Context::create(QOpenGLContext* shareContext) {
#else
contextAttribs.push_back(WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
#endif
contextAttribs.push_back(WGL_CONTEXT_FLAGS_ARB);
if (enableDebugLogger()) {
contextAttribs.push_back(WGL_CONTEXT_DEBUG_BIT_ARB);
} else {
contextAttribs.push_back(0);
{
int contextFlags = 0;
if (enableDebugLogger()) {
contextFlags |= WGL_CONTEXT_DEBUG_BIT_ARB;
}
#ifdef USE_KHR_ROBUSTNESS
contextFlags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
#endif
if (contextFlags != 0) {
contextAttribs.push_back(WGL_CONTEXT_FLAGS_ARB);
contextAttribs.push_back(contextFlags);
}
}
contextAttribs.push_back(0);
HGLRC shareHglrc = nullptr;
@ -323,8 +338,8 @@ void Context::create(QOpenGLContext* shareContext) {
if (_hglrc != 0) {
createWrapperContext();
}
}
}
if (_hglrc == 0) {
// fallback, if the context creation failed, or USE_CUSTOM_CONTEXT is false
qtCreate(shareContext);

View file

@ -23,7 +23,7 @@ class QOpenGLContext;
class QThread;
class QOpenGLDebugMessage;
#if defined(Q_OS_WIN) && defined(USE_GLES)
#if defined(Q_OS_WIN) && (defined(USE_GLES) || defined(USE_KHR_ROBUSTNESS))
//#if defined(Q_OS_WIN)
#define GL_CUSTOM_CONTEXT
#endif

View file

@ -70,10 +70,10 @@ bool NetworkMaterialResource::parseJSONColor(const QJsonValue& array, glm::vec3&
}
/**jsdoc
* A material or set of materials such as may be used by a {@link Entities.EntityType|Material} entity.
* @typedef {object} MaterialResource
* A material or set of materials used by a {@link Entities.EntityType|Material entity}.
* @typedef {object} Entities.MaterialResource
* @property {number} materialVersion=1 - The version of the material. <em>Currently not used.</em>
* @property {Material|Material[]} materials - The details of the material or materials.
* @property {Entities.Material|Entities.Material[]} materials - The details of the material or materials.
*/
NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl) {
ParsedMaterials toReturn;
@ -109,60 +109,72 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
}
/**jsdoc
* A material such as may be used by a {@link Entities.EntityType|Material} entity.
* @typedef {object} Material
* A material used in a {@link Entities.MaterialResource|MaterialResource}.
* @typedef {object} Entities.Material
* @property {string} model="hifi_pbr" - Different material models support different properties and rendering modes.
* Supported models are: "hifi_pbr"
* Supported models are: <code>"hifi_pbr"</code>.
* @property {string} name="" - A name for the material. Supported by all material models.
* @property {Color|RGBS|string} emissive - The emissive color, i.e., the color that the material emits. A {@link Color} value
* is treated as sRGB. A {@link RGBS} value can be either RGB or sRGB. Set to <code>"fallthrough"</code> to fallthrough to
* the material below. "hifi_pbr" model only.
* @property {number|string} opacity=1.0 - The opacity, <code>0.0</code> &ndash; <code>1.0</code>. Set to <code>"fallthrough"</code> to fallthrough to
* the material below. "hifi_pbr" model only.
* @property {boolean|string} unlit=false - If <code>true</code>, the material is not lit. Set to <code>"fallthrough"</code> to fallthrough to
* the material below. "hifi_pbr" model only.
* @property {Color|RGBS|string} albedo - The albedo color. A {@link Color} value is treated as sRGB. A {@link RGBS} value can
* be either RGB or sRGB. Set to <code>"fallthrough"</code> to fallthrough to the material below. Set to <code>"fallthrough"</code> to fallthrough to
* the material below. "hifi_pbr" model only.
* @property {number|string} roughness - The roughness, <code>0.0</code> &ndash; <code>1.0</code>. Set to <code>"fallthrough"</code> to fallthrough to
* the material below. "hifi_pbr" model only.
* @property {number|string} metallic - The metallicness, <code>0.0</code> &ndash; <code>1.0</code>. Set to <code>"fallthrough"</code> to fallthrough to
* the material below. "hifi_pbr" model only.
* @property {number|string} scattering - The scattering, <code>0.0</code> &ndash; <code>1.0</code>. Set to <code>"fallthrough"</code> to fallthrough to
* the material below. "hifi_pbr" model only.
* @property {string} emissiveMap - URL of emissive texture image. Set to <code>"fallthrough"</code> to fallthrough to
* the material below. "hifi_pbr" model only.
* @property {string} albedoMap - URL of albedo texture image. Set to <code>"fallthrough"</code> to fallthrough to
* the material below. "hifi_pbr" model only.
* @property {string} opacityMap - URL of opacity texture image. Set value the same as the <code>albedoMap</code> value for
* transparency. "hifi_pbr" model only.
* @property {string} roughnessMap - URL of roughness texture image. Can use this or <code>glossMap</code>, but not both. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} glossMap - URL of gloss texture image. Can use this or <code>roughnessMap</code>, but not both. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} metallicMap - URL of metallic texture image. Can use this or <code>specularMap</code>, but not both. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} specularMap - URL of specular texture image. Can use this or <code>metallicMap</code>, but not both. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} normalMap - URL of normal texture image. Can use this or <code>bumpMap</code>, but not both. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} bumpMap - URL of bump texture image. Can use this or <code>normalMap</code>, but not both. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} occlusionMap - URL of occlusion texture image. Set to <code>"fallthrough"</code> to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} scatteringMap - URL of scattering texture image. Only used if <code>normalMap</code> or
* <code>bumpMap</code> is specified. Set to <code>"fallthrough"</code> to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} lightMap - URL of light map texture image. <em>Currently not used.</em>. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} texCoordTransform0 - The transform to use for all of the maps besides occlusionMap and lightMap. Currently unused. Set to
* <code>"fallthrough"</code> to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} texCoordTransform1 - The transform to use for occlusionMap and lightMap. Currently unused. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} lightmapParams - Parameters for controlling how lightMap is used. Currently unused. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} materialParams - Parameters for controlling the material projection and repition. Currently unused. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {bool} defaultFallthrough=false - If <code>true</code>, all properties will fallthrough to the material below unless they are set. If
* <code>false</code>, they will respect the individual properties' fallthrough state. "hifi_pbr" model only.
* @property {ColorFloat|RGBS|string} emissive - The emissive color, i.e., the color that the material emits. A
* {@link ColorFloat} value is treated as sRGB and must have component values in the range <code>0.0</code> &mdash;
* <code>1.0</code>. A {@link RGBS} value can be either RGB or sRGB.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {number|string} opacity=1.0 - The opacity, range <code>0.0</code> &ndash; <code>1.0</code>.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {boolean|string} unlit=false - If <code>true</code>, the material is not lit, otherwise it is.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {ColorFloat|RGBS|string} albedo - The albedo color. A {@link ColorFloat} value is treated as sRGB and must have
* component values in the range <code>0.0</code> &mdash; <code>1.0</code>. A {@link RGBS} value can be either RGB or sRGB.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {number|string} roughness - The roughness, range <code>0.0</code> &ndash; <code>1.0</code>.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {number|string} metallic - The metallicness, range <code>0.0</code> &ndash; <code>1.0</code>.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {number|string} scattering - The scattering, range <code>0.0</code> &ndash; <code>1.0</code>.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} emissiveMap - The URL of the emissive texture image.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} albedoMap - The URL of the albedo texture image.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} opacityMap - The URL of the opacity texture image. Set the value the same as the <code>albedoMap</code>
* value for transparency.
* <code>"hifi_pbr"</code> model only.
* @property {string} roughnessMap - The URL of the roughness texture image. You can use this or <code>glossMap</code>, but not
* both.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} glossMap - The URL of the gloss texture image. You can use this or <code>roughnessMap</code>, but not
* both.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} metallicMap - The URL of the metallic texture image. You can use this or <code>specularMap</code>, but
* not both.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} specularMap - The URL of the specular texture image. You can use this or <code>metallicMap</code>, but
* not both.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} normalMap - The URL of the normal texture image. You can use this or <code>bumpMap</code>, but not both.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} bumpMap - The URL of the bump texture image. You can use this or <code>normalMap</code>, but not both.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} occlusionMap - The URL of the occlusion texture image.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} scatteringMap - The URL of the scattering texture image. Only used if <code>normalMap</code> or
* <code>bumpMap</code> is specified.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} lightMap - The URL of the light map texture image.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {Mat4|string} texCoordTransform0 - The transform to use for all of the maps apart from <code>occlusionMap</code>
* and <code>lightMap</code>.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {Mat4|string} texCoordTransform1 - The transform to use for <code>occlusionMap</code> and <code>lightMap</code>.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} lightmapParams - Parameters for controlling how lightMap is used.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* <p><em>Currently not used.</em></p>
* @property {string} materialParams - Parameters for controlling the material projection and repetition.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* <p><em>Currently not used.</em></p>
* @property {boolean} defaultFallthrough=false - If <code>true</code>, all properties fall through to the material below
* unless they are set. If <code>false</code>, they respect their individual fall-through setting. <code>"hifi_pbr"</code>
* model only.
*/
// Note: See MaterialEntityItem.h for default values used in practice.
std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource::parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl) {
@ -399,7 +411,7 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::LIGHTMAP_PARAMS);
}
}
// TODO: implement lightmapParams
// TODO: implement lightmapParams and update JSDoc
} else if (key == "materialParams") {
auto value = materialJSON.value(key);
if (value.isString()) {
@ -408,7 +420,7 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::MATERIAL_PARAMS);
}
}
// TODO: implement materialParams
// TODO: implement materialParams and update JSDoc
} else if (key == "defaultFallthrough") {
auto value = materialJSON.value(key);
if (value.isBool()) {

View file

@ -1,6 +1,6 @@
set(TARGET_NAME networking)
setup_hifi_library(Network)
link_hifi_libraries(shared)
link_hifi_libraries(shared platform)
target_openssl()
target_tbb()

View file

@ -956,7 +956,7 @@ void AccountManager::saveLoginStatus(bool isLoggedIn) {
QProcess launcher;
launcher.setProgram(launcherPath);
launcher.startDetached();
qApp->quit();
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
}
}
}

View file

@ -26,6 +26,8 @@
#include <ThreadHelpers.h>
#include <LogHandler.h>
#include <UUID.h>
#include <platform/Platform.h>
#include <platform/PlatformKeys.h>
#include "AccountManager.h"
#include "AddressManager.h"
@ -42,6 +44,7 @@
using namespace std::chrono;
const int KEEPALIVE_PING_INTERVAL_MS = 1000;
const int MAX_SYSTEM_INFO_SIZE = 1000;
NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) :
LimitedNodeList(socketListenPort, dtlsListenPort),
@ -418,19 +421,20 @@ void NodeList::sendDomainServerCheckIn() {
auto accountManager = DependencyManager::get<AccountManager>();
packetStream << FingerprintUtils::getMachineFingerprint();
QString systemInfo;
#if defined Q_OS_WIN
systemInfo = "OS:Windows";
#elif defined Q_OS_OSX
systemInfo = "OS:OSX";
#elif defined Q_OS_LINUX
systemInfo = "OS:Linux";
#elif defined Q_OS_ANDROID
systemInfo = "OS:Android";
#else
systemInfo = "OS:Unknown";
#endif
packetStream << systemInfo;
auto desc = platform::getAll();
QByteArray systemInfo(desc.dump().c_str());
QByteArray compressedSystemInfo = qCompress(systemInfo);
if (compressedSystemInfo.size() > MAX_SYSTEM_INFO_SIZE) {
// Highly unlikely, as not even unreasonable machines will
// overflow the max size, but prevent MTU overflow anyway.
// We could do something sophisticated like clearing specific
// values if they're too big, but we'll save that for later.
compressedSystemInfo.clear();
}
packetStream << compressedSystemInfo;
packetStream << _connectReason;

View file

@ -20,6 +20,7 @@
#include <LogHandler.h>
#include <shared/QtHelpers.h>
#include <platform/Platform.h>
#include "NetworkLogging.h"
ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) :
@ -38,6 +39,16 @@ ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) :
// if the NL tells us we got a DS response, clear our member variable of queued check-ins
auto nodeList = DependencyManager::get<NodeList>();
connect(nodeList.data(), &NodeList::receivedDomainServerList, this, &ThreadedAssignment::clearQueuedCheckIns);
platform::create();
if (!platform::enumeratePlatform()) {
qCDebug(networking) << "Failed to enumerate platform.";
}
}
ThreadedAssignment::~ThreadedAssignment() {
stop();
platform::destroy();
}
void ThreadedAssignment::setFinished(bool isFinished) {

View file

@ -22,7 +22,7 @@ class ThreadedAssignment : public Assignment {
Q_OBJECT
public:
ThreadedAssignment(ReceivedMessage& message);
~ThreadedAssignment() { stop(); }
~ThreadedAssignment();
virtual void aboutToFinish() { };
void addPacketStatsAndSendStatsPacket(QJsonObject statsObject);

View file

@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
return static_cast<PacketVersion>(DomainConnectionDeniedVersion::IncludesExtraInfo);
case PacketType::DomainConnectRequest:
return static_cast<PacketVersion>(DomainConnectRequestVersion::HasSystemInfo);
return static_cast<PacketVersion>(DomainConnectRequestVersion::HasCompressedSystemInfo);
case PacketType::DomainServerAddedNode:
return static_cast<PacketVersion>(DomainServerAddedNodeVersion::PermissionsGrid);

View file

@ -347,7 +347,8 @@ enum class DomainConnectRequestVersion : PacketVersion {
AlwaysHasMachineFingerprint,
HasTimestamp,
HasReason,
HasSystemInfo
HasSystemInfo,
HasCompressedSystemInfo
};
enum class DomainConnectionDeniedVersion : PacketVersion {

View file

@ -46,6 +46,7 @@ bool OctreeEditPacketSender::serversExist() const {
void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, std::unique_ptr<NLPacket> packet) {
bool wantDebug = false;
QMutexLocker lock(&_packetsQueueLock);
DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& node){
// only send to the NodeTypes that are getMyNodeType()
if (node->getType() == getMyNodeType()
@ -324,6 +325,8 @@ bool OctreeEditPacketSender::process() {
void OctreeEditPacketSender::processNackPacket(ReceivedMessage& message, SharedNodePointer sendingNode) {
// parse sending node from packet, retrieve packet history for that node
QMutexLocker lock(&_packetsQueueLock);
// if packet history doesn't exist for the sender node (somehow), bail
if (_sentPacketHistories.count(sendingNode->getUUID()) == 0) {
return;
@ -345,7 +348,7 @@ void OctreeEditPacketSender::processNackPacket(ReceivedMessage& message, SharedN
}
void OctreeEditPacketSender::nodeKilled(SharedNodePointer node) {
// TODO: add locks
QMutexLocker lock(&_packetsQueueLock);
QUuid nodeUUID = node->getUUID();
_pendingEditPackets.erase(nodeUUID);
_outgoingSequenceNumbers.erase(nodeUUID);

View file

@ -86,19 +86,20 @@ protected:
void processPreServerExistsPackets();
// These are packets which are destined from know servers but haven't been released because they're still too small
// protected by _packetsQueueLock
std::unordered_map<QUuid, PacketOrPacketList> _pendingEditPackets;
// These are packets that are waiting to be processed because we don't yet know if there are servers
int _maxPendingMessages;
bool _releaseQueuedMessagesPending;
QMutex _pendingPacketsLock;
QMutex _packetsQueueLock; // don't let different threads release the queue while another thread is writing to it
QMutex _packetsQueueLock{ QMutex::Recursive }; // don't let different threads release the queue while another thread is writing to it
std::list<EditMessagePair> _preServerEdits; // these will get packed into other larger packets
std::list<std::unique_ptr<NLPacket>> _preServerSingleMessagePackets; // these will go out as is
QMutex _releaseQueuedPacketMutex;
// TODO: add locks for this and _pendingEditPackets
// protected by _packetsQueueLock
std::unordered_map<QUuid, SentPacketHistory> _sentPacketHistories;
std::unordered_map<QUuid, quint16> _outgoingSequenceNumbers;
};

View file

@ -37,7 +37,7 @@ private slots:
public slots:
/**jsdoc
* Set the maximum number of entity packets that the client can send per second.
* Sets the maximum number of entity packets that the client can send per second.
* @function Entities.setPacketsPerSecond
* @param {number} packetsPerSecond - Integer maximum number of entity packets that the client can send per second.
*/
@ -45,7 +45,7 @@ public slots:
void setPacketsPerSecond(int packetsPerSecond) { return _packetSender->setPacketsPerSecond(packetsPerSecond); }
/**jsdoc
* Get the maximum number of entity packets that the client can send per second.
* Gets the maximum number of entity packets that the client can send per second.
* @function Entities.getPacketsPerSecond
* @returns {number} Integer maximum number of entity packets that the client can send per second.
*/
@ -53,7 +53,7 @@ public slots:
int getPacketsPerSecond() const { return _packetSender->getPacketsPerSecond(); }
/**jsdoc
* Check whether servers exist for the client to send entity packets to, i.e., whether you are connected to a domain and
* Checks whether servers exist for the client to send entity packets to, i.e., whether you are connected to a domain and
* its entity server is working.
* @function Entities.serversExist
* @returns {boolean} <code>true</code> if servers exist for the client to send entity packets to, otherwise
@ -63,7 +63,7 @@ public slots:
bool serversExist() const { return _packetSender->serversExist(); }
/**jsdoc
* Check whether the client has entity packets waiting to be sent.
* Checks whether the client has entity packets waiting to be sent.
* @function Entities.hasPacketsToSend
* @returns {boolean} <code>true</code> if the client has entity packets waiting to be sent, otherwise <code>false</code>.
*/
@ -71,7 +71,7 @@ public slots:
bool hasPacketsToSend() const { return _packetSender->hasPacketsToSend(); }
/**jsdoc
* Get the number of entity packets the client has waiting to be sent.
* Gets the number of entity packets the client has waiting to be sent.
* @function Entities.packetsToSendCount
* @returns {number} Integer number of entity packets the client has waiting to be sent.
*/
@ -79,7 +79,7 @@ public slots:
int packetsToSendCount() const { return (int)_packetSender->packetsToSendCount(); }
/**jsdoc
* Get the entity packets per second send rate of the client over its lifetime.
* Gets the entity packets per second send rate of the client over its lifetime.
* @function Entities.getLifetimePPS
* @returns {number} Entity packets per second send rate of the client over its lifetime.
*/
@ -87,7 +87,7 @@ public slots:
float getLifetimePPS() const { return _packetSender->getLifetimePPS(); }
/**jsdoc
* Get the entity bytes per second send rate of the client over its lifetime.
* Gets the entity bytes per second send rate of the client over its lifetime.
* @function Entities.getLifetimeBPS
* @returns {number} Entity bytes per second send rate of the client over its lifetime.
*/
@ -95,7 +95,7 @@ public slots:
float getLifetimeBPS() const { return _packetSender->getLifetimeBPS(); }
/**jsdoc
* Get the entity packets per second queued rate of the client over its lifetime.
* Gets the entity packets per second queued rate of the client over its lifetime.
* @function Entities.getLifetimePPSQueued
* @returns {number} Entity packets per second queued rate of the client over its lifetime.
*/
@ -103,7 +103,7 @@ public slots:
float getLifetimePPSQueued() const { return _packetSender->getLifetimePPSQueued(); }
/**jsdoc
* Get the entity bytes per second queued rate of the client over its lifetime.
* Gets the entity bytes per second queued rate of the client over its lifetime.
* @function Entities.getLifetimeBPSQueued
* @returns {number} Entity bytes per second queued rate of the client over its lifetime.
*/
@ -111,7 +111,7 @@ public slots:
float getLifetimeBPSQueued() const { return _packetSender->getLifetimeBPSQueued(); }
/**jsdoc
* Get the lifetime of the client from the first entity packet sent until now, in microseconds.
* Gets the lifetime of the client from the first entity packet sent until now, in microseconds.
* @function Entities.getLifetimeInUsecs
* @returns {number} Lifetime of the client from the first entity packet sent until now, in microseconds.
*/
@ -119,7 +119,7 @@ public slots:
long long unsigned int getLifetimeInUsecs() const { return _packetSender->getLifetimeInUsecs(); }
/**jsdoc
* Get the lifetime of the client from the first entity packet sent until now, in seconds.
* Gets the lifetime of the client from the first entity packet sent until now, in seconds.
* @function Entities.getLifetimeInSeconds
* @returns {number} Lifetime of the client from the first entity packet sent until now, in seconds.
*/
@ -127,7 +127,7 @@ public slots:
float getLifetimeInSeconds() const { return _packetSender->getLifetimeInSeconds(); }
/**jsdoc
* Get the total number of entity packets sent by the client over its lifetime.
* Gets the total number of entity packets sent by the client over its lifetime.
* @function Entities.getLifetimePacketsSent
* @returns {number} The total number of entity packets sent by the client over its lifetime.
*/
@ -135,7 +135,7 @@ public slots:
long long unsigned int getLifetimePacketsSent() const { return _packetSender->getLifetimePacketsSent(); }
/**jsdoc
* Get the total bytes of entity packets sent by the client over its lifetime.
* Gets the total bytes of entity packets sent by the client over its lifetime.
* @function Entities.getLifetimeBytesSent
* @returns {number} The total bytes of entity packets sent by the client over its lifetime.
*/
@ -143,7 +143,7 @@ public slots:
long long unsigned int getLifetimeBytesSent() const { return _packetSender->getLifetimeBytesSent(); }
/**jsdoc
* Get the total number of entity packets queued by the client over its lifetime.
* Gets the total number of entity packets queued by the client over its lifetime.
* @function Entities.getLifetimePacketsQueued
* @returns {number} The total number of entity packets queued by the client over its lifetime.
*/
@ -151,7 +151,7 @@ public slots:
long long unsigned int getLifetimePacketsQueued() const { return _packetSender->getLifetimePacketsQueued(); }
/**jsdoc
* Get the total bytes of entity packets queued by the client over its lifetime.
* Gets the total bytes of entity packets queued by the client over its lifetime.
* @function Entities.getLifetimeBytesQueued
* @returns {number} The total bytes of entity packets queued by the client over its lifetime.
*/

View file

@ -145,7 +145,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
/**jsdoc
* The <code>"offset"</code> {@link Entities.ActionType|ActionType} moves an entity so that it is a set distance away from a
* target point.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
*
* @typedef {object} Entities.ActionArguments-Offset
* @property {Vec3} pointToOffsetFrom=0,0,0 - The target point to offset the entity from.

View file

@ -341,15 +341,15 @@ bool ObjectActionTractor::updateArguments(QVariantMap arguments) {
/**jsdoc
* The <code>"tractor"</code> {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and
* orientation, optionally relative to another entity.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
*
* @typedef {object} Entities.ActionArguments-Tractor
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
* relative to the entity's position and rotation.
* @property {Uuid} otherJointIndex=null - If a joint index in the <code>otherID</code> entity, the <code>targetPosition</code>
* and <code>targetRotation</code> are relative to the entity joint's position and rotation.
* @property {Vec3} targetPosition=0,0,0 - The target position.
* @property {Quat} targetRotation=0,0,0,1 - The target rotation.
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
* relative to this entity's position and rotation.
* @property {Uuid} otherJointIndex=null - If an entity JointIndex, the <code>targetPosition</code> and
* <code>targetRotation</code> are relative to this entity's joint's position and rotation.
* @property {number} linearTimeScale=3.4e+38 - Controls how long it takes for the entity's position to catch up with the
* target position. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action
* is applied using an exponential decay.

View file

@ -152,7 +152,7 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) {
/**jsdoc
* The <code>"travel-oriented"</code> {@link Entities.ActionType|ActionType} orients an entity to align with its direction of
* travel.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
*
* @typedef {object} Entities.ActionArguments-TravelOriented
* @property {Vec3} forward=0,0,0 - The axis of the entity to align with the entity's direction of travel.

View file

@ -183,11 +183,11 @@ bool ObjectConstraintBallSocket::updateArguments(QVariantMap arguments) {
/**jsdoc
* The <code>"ball-socket"</code> {@link Entities.ActionType|ActionType} connects two entities with a ball and socket joint.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
*
* @typedef {object} Entities.ActionArguments-BallSocket
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint.
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
* @property {Vec3} otherPivot=0,0,0 - The local offset of the joint relative to the other entity's position.
*/
QVariantMap ObjectConstraintBallSocket::getArguments() {

View file

@ -264,17 +264,18 @@ bool ObjectConstraintConeTwist::updateArguments(QVariantMap arguments) {
/**jsdoc
* The <code>"cone-twist"</code> {@link Entities.ActionType|ActionType} connects two entities with a joint that can move
* through a cone and can twist.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
*
* @typedef {object} Entities.ActionArguments-ConeTwist
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint.
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
* @property {Vec3} axis=1,0,0 - The axis of the entity that moves through the cone. Must be a non-zero vector.
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint.
* @property {Vec3} otherPivot=0,0,0 - The local offset of the joint relative to the other entity's position.
* @property {Vec3} otherAxis=1,0,0 - The axis of the other entity that moves through the cone. Must be a non-zero vector.
* @property {number} swingSpan1=6.238 - The angle through which the joint can move in one axis of the cone, in radians.
* @property {number} swingSpan2=6.238 - The angle through which the joint can move in the other axis of the cone, in radians.
* @property {number} twistSpan=6.238 - The angle through with the joint can twist, in radians.
* @property {number} swingSpan1=2*Math.PI - The angle through which the joint can move in one axis of the cone, in radians.
* @property {number} swingSpan2=2*Math.PI - The angle through which the joint can move in the other axis of the cone, in
* radians.
* @property {number} twistSpan=2*Math.PI - The angle through with the joint can twist, in radians.
*/
QVariantMap ObjectConstraintConeTwist::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();

View file

@ -248,18 +248,19 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) {
/**jsdoc
* The <code>"hinge"</code> {@link Entities.ActionType|ActionType} lets an entity pivot about an axis or connects two entities
* with a hinge joint.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
*
* @typedef {object} Entities.ActionArguments-Hinge
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If none is
* specified then the first entity simply pivots about its specified <code>axis</code>.
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
* @property {Vec3} axis=1,0,0 - The axis of the entity that it pivots about. Must be a non-zero vector.
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If none is
* specified then the first entity simply pivots about its specified <code>axis</code>.
* @property {Vec3} otherPivot=0,0,0 - The local offset of the joint relative to the other entity's position.
* @property {Vec3} otherAxis=1,0,0 - The axis of the other entity that it pivots about. Must be a non-zero vector.
* @property {number} low=-6.283 - The most negative angle that the hinge can take, in radians.
* @property {number} high=6.283 - The most positive angle that the hinge can take, in radians.
* @property {number} angle=0 - The current angle of the hinge. <em>Read-only.</em>
* @property {number} low=-2*Math.PI - The most negative angle that the hinge can take, in radians.
* @property {number} high=2*Math.PI - The most positive angle that the hinge can take, in radians.
* @property {number} angle=0 - The current angle of the hinge, in radians, range <code>-Math.PI</code> &ndash;
* <code>Math.PI</code>. <em>Read-only.</em>
*/
QVariantMap ObjectConstraintHinge::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();

View file

@ -264,27 +264,27 @@ bool ObjectConstraintSlider::updateArguments(QVariantMap arguments) {
/**jsdoc
* The <code>"slider"</code> {@link Entities.ActionType|ActionType} lets an entity slide and rotate along an axis, or connects
* two entities that slide and rotate along a shared axis.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
*
* @typedef {object} Entities.ActionArguments-Slider
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If none is
* specified then the first entity simply slides and rotates about its specified <code>axis</code>.
* @property {Vec3} point=0,0,0 - The local position of a point in the entity that slides along the axis.
* @property {Vec3} axis=1,0,0 - The axis of the entity that slides along the joint. Must be a non-zero vector.
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If non is
* specified then the first entity simply slides and rotates about its specified <code>axis</code>.
* @property {Vec3} otherPoint=0,0,0 - The local position of a point in the other entity that slides along the axis.
* @property {Vec3} axis=1,0,0 - The axis of the other entity that slides along the joint. Must be a non-zero vector.
* @property {Vec3} otherAxis=1,0,0 - The axis of the other entity that slides along the joint. Must be a non-zero vector.
* @property {number} linearLow=1.17e-38 - The most negative linear offset from the entity's initial point that the entity can
* have along the slider.
* @property {number} linearHigh=3.40e+38 - The most positive linear offset from the entity's initial point that the entity can
* have along the slider.
* @property {number} angularLow=-6.283 - The most negative angle that the entity can rotate about the axis if the action
* @property {number} angularLow=-2*Math.PI - The most negative angle that the entity can rotate about the axis if the action
* involves only one entity, otherwise the most negative angle the rotation can be between the two entities. In radians.
* @property {number} angularHigh=6.283 - The most positive angle that the entity can rotate about the axis if the action
* @property {number} angularHigh=Math.PI - The most positive angle that the entity can rotate about the axis if the action
* involves only one entity, otherwise the most positive angle the rotation can be between the two entities. In radians.
* @property {number} linearPosition=0 - The current linear offset the entity is from its initial point if the action involves
* only one entity, otherwise the linear offset between the two entities' action points. <em>Read-only.</em>
* @property {number} angularPosition=0 - The current angular offset of the entity from its initial rotation if the action
* involves only one entity, otherwise the angular offset between the two entities. <em>Read-only.</em>
* involves only one entity, otherwise the angular offset between the two entities. In radians. <em>Read-only.</em>
*/
QVariantMap ObjectConstraintSlider::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();

View file

@ -94,36 +94,36 @@ bool ObjectDynamic::updateArguments(QVariantMap arguments) {
}
/**jsdoc
* Different entity action types have different arguments: some common to all actions (listed below) and some specific to each
* {@link Entities.ActionType|ActionType} (linked to below). The arguments are accessed as an object of property names and
* values.
*
* @typedef {object} Entities.ActionArguments
* @property {Entities.ActionType} type - The type of action.
* @property {string} tag="" - A string that a script can use for its own purposes.
* @property {number} ttl=0 - How long the action should exist, in seconds, before it is automatically deleted. A value of
* <code>0</code> means that the action should not be deleted.
* @property {boolean} isMine=true - Is <code>true</code> if you created the action during your current Interface session,
* <code>false</code> otherwise. <em>Read-only.</em>
* @property {boolean} ::no-motion-state - Is present when the entity hasn't been registered with the physics engine yet (e.g.,
* if the action hasn't been properly configured), otherwise <code>undefined</code>. <em>Read-only.</em>
* @property {boolean} ::active - Is <code>true</code> when the action is modifying the entity's motion, <code>false</code>
* otherwise. Is present once the entity has been registered with the physics engine, otherwise <code>undefined</code>.
* <em>Read-only.</em>
* @property {Entities.PhysicsMotionType} ::motion-type - How the entity moves with the action. Is present once the entity has
* been registered with the physics engine, otherwise <code>undefined</code>. <em>Read-only.</em>
*
* @see The different action types have additional arguments as follows:
* @see {@link Entities.ActionArguments-FarGrab|ActionArguments-FarGrab}
* @see {@link Entities.ActionArguments-Hold|ActionArguments-Hold}
* @see {@link Entities.ActionArguments-Offset|ActionArguments-Offset}
* @see {@link Entities.ActionArguments-Tractor|ActionArguments-Tractor}
* @see {@link Entities.ActionArguments-TravelOriented|ActionArguments-TravelOriented}
* @see {@link Entities.ActionArguments-Hinge|ActionArguments-Hinge}
* @see {@link Entities.ActionArguments-Slider|ActionArguments-Slider}
* @see {@link Entities.ActionArguments-ConeTwist|ActionArguments-ConeTwist}
* @see {@link Entities.ActionArguments-BallSocket|ActionArguments-BallSocket}
*/
* Different entity action types have different arguments: some common to all actions (listed in the table) and some specific
* to each {@link Entities.ActionType|ActionType} (linked to below). The arguments are accessed as an object of property names
* and values.
*
* @typedef {object} Entities.ActionArguments
* @property {Entities.ActionType} type - The type of action.
* @property {string} tag="" - A string that a script can use for its own purposes.
* @property {number} ttl=0 - How long the action should exist, in seconds, before it is automatically deleted. A value of
* <code>0</code> means that the action should not be deleted.
* @property {boolean} isMine=true - Is <code>true</code> if the action was created during the current client session,
* <code>false</code> otherwise. <em>Read-only.</em>
* @property {boolean} ::no-motion-state - Is present when the entity hasn't been registered with the physics engine yet (e.g.,
* if the action hasn't been properly configured), otherwise <code>undefined</code>. <em>Read-only.</em>
* @property {boolean} ::active - Is <code>true</code> when the action is modifying the entity's motion, <code>false</code>
* otherwise. Is present once the entity has been registered with the physics engine, otherwise <code>undefined</code>.
* <em>Read-only.</em>
* @property {Entities.PhysicsMotionType} ::motion-type - How the entity moves with the action. Is present once the entity has
* been registered with the physics engine, otherwise <code>undefined</code>. <em>Read-only.</em>
*
* @comment The different action types have additional arguments as follows:
* @see {@link Entities.ActionArguments-FarGrab|ActionArguments-FarGrab}
* @see {@link Entities.ActionArguments-Hold|ActionArguments-Hold}
* @see {@link Entities.ActionArguments-Offset|ActionArguments-Offset}
* @see {@link Entities.ActionArguments-Tractor|ActionArguments-Tractor}
* @see {@link Entities.ActionArguments-TravelOriented|ActionArguments-TravelOriented}
* @see {@link Entities.ActionArguments-Hinge|ActionArguments-Hinge}
* @see {@link Entities.ActionArguments-Slider|ActionArguments-Slider}
* @see {@link Entities.ActionArguments-ConeTwist|ActionArguments-ConeTwist}
* @see {@link Entities.ActionArguments-BallSocket|ActionArguments-BallSocket}
*/
// Note: The "type" property is set in EntityItem::getActionArguments().
QVariantMap ObjectDynamic::getArguments() {
QVariantMap arguments;

View file

@ -309,20 +309,28 @@ void PhysicalEntitySimulation::buildMotionStatesForEntitiesThatNeedThem() {
SetOfEntities::iterator entityItr = _entitiesToAddToPhysics.begin();
while (entityItr != _entitiesToAddToPhysics.end()) {
EntityItemPointer entity = (*entityItr);
assert(!entity->getPhysicsInfo());
if (entity->isDead()) {
prepareEntityForDelete(entity);
entityItr = _entitiesToAddToPhysics.erase(entityItr);
} else if (!entity->shouldBePhysical()) {
// this entity should no longer be on _entitiesToAddToPhysics
continue;
}
if (entity->getPhysicsInfo()) {
entityItr = _entitiesToAddToPhysics.erase(entityItr);
continue;
}
if (!entity->shouldBePhysical()) {
// this entity should no longer be on _entitiesToAddToPhysics
if (entity->isMovingRelativeToParent()) {
SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity);
if (itr == _simpleKinematicEntities.end()) {
_simpleKinematicEntities.insert(entity);
}
}
} else if (entity->isReadyToComputeShape()) {
entityItr = _entitiesToAddToPhysics.erase(entityItr);
continue;
}
if (entity->isReadyToComputeShape()) {
ShapeRequest shapeRequest(entity);
ShapeRequests::iterator requestItr = _shapeRequests.find(shapeRequest);
if (requestItr == _shapeRequests.end()) {
@ -332,18 +340,7 @@ void PhysicalEntitySimulation::buildMotionStatesForEntitiesThatNeedThem() {
uint32_t requestCount = ObjectMotionState::getShapeManager()->getWorkRequestCount();
btCollisionShape* shape = const_cast<btCollisionShape*>(ObjectMotionState::getShapeManager()->getShape(shapeInfo));
if (shape) {
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
if (!motionState) {
buildMotionState(shape, entity);
} else {
// Is it possible to fall in here?
// entity shouldn't be on _entitiesToAddToPhysics list if it already has a motionState.
// but just in case...
motionState->setShape(shape);
motionState->setRegion(_space->getRegion(entity->getSpaceIndex()));
_physicalObjects.insert(motionState);
_incomingChanges.insert(motionState);
}
buildMotionState(shape, entity);
} else if (requestCount != ObjectMotionState::getShapeManager()->getWorkRequestCount()) {
// shape doesn't exist but a new worker has been spawned to build it --> add to shapeRequests and wait
shapeRequest.shapeHash = shapeInfo.getHash();
@ -354,6 +351,7 @@ void PhysicalEntitySimulation::buildMotionStatesForEntitiesThatNeedThem() {
}
entityItr = _entitiesToAddToPhysics.erase(entityItr);
} else {
// skip for later
++entityItr;
}
}

View file

@ -181,7 +181,7 @@ void ThreadSafeDynamicsWorld::drawConnectedSpheres(btIDebugDraw* drawer, btScala
btVector3 xAxis = direction.cross(btVector3(0.0f, 1.0f, 0.0f));
xAxis = xAxis.length() < EPSILON ? btVector3(1.0f, 0.0f, 0.0f) : xAxis.normalize();
btVector3 zAxis = xAxis.cross(btVector3(0.0f, 1.0f, 0.0f));
zAxis = (direction.normalize().getY() < EPSILON) ? btVector3(0.0f, 1.0f, 0.0f) : zAxis.normalize();
zAxis = (direction.length2() < EPSILON || direction.normalize().getY() < EPSILON) ? btVector3(0.0f, 1.0f, 0.0f) : zAxis.normalize();
float fullCircle = 2.0f * PI;
for (float i = 0; i < fullCircle; i += stepRadians) {
float x1 = btSin(btScalar(i)) * radius1;

View file

@ -5,3 +5,11 @@ link_hifi_libraries(shared)
GroupSources("src")
target_json()
if (APPLE)
# link in required OS X frameworks and include the right GL headers
find_library(OpenGL OpenGL)
find_library(AppKit AppKit)
target_link_libraries(${TARGET_NAME} ${OpenGL} ${AppKit})
endif ()

View file

@ -27,12 +27,13 @@ json getGPU(int index);
int getNumDisplays();
json getDisplay(int index);
int getNumMemories();
json getMemory(int index);
json getMemory();
json getComputer();
json getAll();
} // namespace platform
#endif // hifi_platform_h

View file

@ -9,6 +9,9 @@
#define hifi_platform_PlatformKeys_h
namespace platform { namespace keys{
// "UNKNOWN"
extern const char* UNKNOWN;
namespace cpu {
extern const char* vendor;
extern const char* vendor_Intel;
@ -36,8 +39,9 @@ namespace platform { namespace keys{
extern const char* coordsTop;
extern const char* coordsBottom;
}
namespace memory {
extern const char* memTotal;
}
namespace computer {
extern const char* OS;
extern const char* OS_WINDOWS;
@ -45,6 +49,8 @@ namespace platform { namespace keys{
extern const char* OS_LINUX;
extern const char* OS_ANDROID;
extern const char* OSVersion;
extern const char* vendor;
extern const char* vendor_Apple;
@ -52,6 +58,14 @@ namespace platform { namespace keys{
extern const char* profileTier;
}
} } // namespace plaform::keys
// Keys for categories used in json returned by getAll()
extern const char* CPUS;
extern const char* GPUS;
extern const char* DISPLAYS;
extern const char* MEMORY;
extern const char* COMPUTER;
} } // namespace plaform::keys
#endif

View file

@ -9,39 +9,45 @@
#include "AndroidPlatform.h"
#include "../PlatformKeys.h"
#include <GPUIdent.h>
#include <QSysInfo>
using namespace platform;
void AndroidInstance::enumerateCpu() {
void AndroidInstance::enumerateCpus() {
json cpu;
cpu[keys::cpu::vendor] = "";
cpu[keys::cpu::model] = "";
cpu[keys::cpu::clockSpeed] = "";
cpu[keys::cpu::numCores] = 0;
_cpu.push_back(cpu);
_cpus.push_back(cpu);
}
void AndroidInstance::enumerateGpu() {
void AndroidInstance::enumerateGpus() {
GPUIdent* ident = GPUIdent::getInstance();
json gpu = {};
gpu[keys::gpu::vendor] = ident->getName().toUtf8().constData();
gpu[keys::gpu::model] = ident->getName().toUtf8().constData();
gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get<std::string>());
gpu[keys::gpu::videoMemory] = ident->getMemory();
gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData();
_gpu.push_back(gpu);
_display = ident->getOutput();
_gpus.push_back(gpu);
_displays = ident->getOutput();
}
void AndroidInstance::enumerateMemory() {
json ram = {};
ram[keys::memTotal]=0;
_memory.push_back(ram);
ram[keys::memory::memTotal]=0;
_memory = ram;
}
void AndroidInstance::enumerateComputer(){
_computer[keys::computer::OS] = keys::computer::OS_ANDROID;
_computer[keys::computer::vendor] = "";
_computer[keys::computer::model] = "";
auto sysInfo = QSysInfo();
_computer[keys::computer::OSVersion] = sysInfo.kernelVersion().toStdString();
}

View file

@ -15,10 +15,10 @@ namespace platform {
class AndroidInstance : public Instance {
public:
void enumerateCpu() override;
void enumerateCpus() override;
void enumerateGpus() override;
void enumerateMemory() override;
void enumerateGpu() override;
void enumerateComputer () override;
void enumerateComputer() override;
};
} // namespace platform

View file

@ -13,36 +13,37 @@
#include <string>
#include <CPUIdent.h>
#include <GPUIdent.h>
#include <QSysInfo>
using namespace platform;
void LinuxInstance::enumerateCpu() {
void LinuxInstance::enumerateCpus() {
json cpu = {};
cpu[keys::cpu::vendor] = CPUIdent::Vendor();
cpu[keys::cpu::model] = CPUIdent::Brand();
cpu[keys::cpu::numCores] = std::thread::hardware_concurrency();
_cpu.push_back(cpu);
_cpus.push_back(cpu);
}
void LinuxInstance::enumerateGpu() {
void LinuxInstance::enumerateGpus() {
GPUIdent* ident = GPUIdent::getInstance();
json gpu = {};
gpu[keys::gpu::vendor] = ident->getName().toUtf8().constData();
gpu[keys::gpu::model] = ident->getName().toUtf8().constData();
gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get<std::string>());
gpu[keys::gpu::videoMemory] = ident->getMemory();
gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData();
_gpu.push_back(gpu);
_display = ident->getOutput();
_gpus.push_back(gpu);
_displays = ident->getOutput();
}
void LinuxInstance::enumerateMemory() {
json ram = {};
ram[keys::memTotal]=0;
ram[keys::memory::memTotal]=0;
_memory.push_back(ram);
_memory = ram;
}
void LinuxInstance::enumerateComputer(){
@ -50,5 +51,9 @@ void LinuxInstance::enumerateComputer(){
_computer[keys::computer::OS] = keys::computer::OS_LINUX;
_computer[keys::computer::vendor] = "";
_computer[keys::computer::model] = "";
auto sysInfo = QSysInfo();
_computer[keys::computer::OSVersion] = sysInfo.kernelVersion().toStdString();
}

View file

@ -15,10 +15,10 @@ namespace platform {
class LinuxInstance : public Instance {
public:
void enumerateCpu() override;
void enumerateCpus() override;
void enumerateGpus() override;
void enumerateMemory() override;
void enumerateGpu() override;
void enumerateComputer () override;
void enumerateComputer() override;
};
} // namespace platform

View file

@ -21,32 +21,33 @@
#include <CoreFoundation/CoreFoundation.h>
#include <ApplicationServices/ApplicationServices.h>
#include <QSysInfo>
#endif
using namespace platform;
void MACOSInstance::enumerateCpu() {
void MACOSInstance::enumerateCpus() {
json cpu = {};
cpu[keys::cpu::vendor] = CPUIdent::Vendor();
cpu[keys::cpu::model] = CPUIdent::Brand();
cpu[keys::cpu::numCores] = std::thread::hardware_concurrency();
_cpu.push_back(cpu);
_cpus.push_back(cpu);
}
void MACOSInstance::enumerateGpu() {
void MACOSInstance::enumerateGpus() {
#ifdef Q_OS_MAC
GPUIdent* ident = GPUIdent::getInstance();
json gpu = {};
gpu[keys::gpu::vendor] = ident->getName().toUtf8().constData();
gpu[keys::gpu::model] = ident->getName().toUtf8().constData();
gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get<std::string>());
gpu[keys::gpu::videoMemory] = ident->getMemory();
gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData();
_gpu.push_back(gpu);
_gpus.push_back(gpu);
#endif
@ -101,7 +102,7 @@ void MACOSInstance::enumerateDisplays() {
display["modeWidth"] = displayModeWidth;
display["modeHeight"] = displayModeHeight;
_display.push_back(display);
_displays.push_back(display);
#endif
}
@ -111,9 +112,9 @@ void MACOSInstance::enumerateMemory() {
#ifdef Q_OS_MAC
long pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGE_SIZE);
ram[keys::memTotal] = pages * page_size;
ram[keys::memory::memTotal] = pages * page_size;
#endif
_memory.push_back(ram);
_memory = ram;
}
void MACOSInstance::enumerateComputer(){
@ -133,5 +134,9 @@ void MACOSInstance::enumerateComputer(){
free(model);
#endif
auto sysInfo = QSysInfo();
_computer[keys::computer::OSVersion] = sysInfo.kernelVersion().toStdString();
}

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