mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
Merge branch 'master' into 21568
This commit is contained in:
commit
1e3a2b3e4e
56 changed files with 658 additions and 164 deletions
|
@ -235,7 +235,8 @@ void updateConsumedCores() {
|
|||
AssetServer::AssetServer(ReceivedMessage& message) :
|
||||
ThreadedAssignment(message),
|
||||
_transferTaskPool(this),
|
||||
_bakingTaskPool(this)
|
||||
_bakingTaskPool(this),
|
||||
_filesizeLimit(MAX_UPLOAD_SIZE)
|
||||
{
|
||||
// store the current state of image compression so we can reset it when this assignment is complete
|
||||
_wasColorTextureCompressionEnabled = image::isColorTexturesCompressionEnabled();
|
||||
|
@ -343,8 +344,8 @@ void AssetServer::completeSetup() {
|
|||
auto maxBandwidthValue = assetServerObject[MAX_BANDWIDTH_OPTION];
|
||||
auto maxBandwidthFloat = maxBandwidthValue.toDouble(-1);
|
||||
|
||||
const int BITS_PER_MEGABITS = 1000 * 1000;
|
||||
if (maxBandwidthFloat > 0.0) {
|
||||
const int BITS_PER_MEGABITS = 1000 * 1000;
|
||||
int maxBandwidth = maxBandwidthFloat * BITS_PER_MEGABITS;
|
||||
nodeList->setConnectionMaxBandwidth(maxBandwidth);
|
||||
qCInfo(asset_server) << "Set maximum bandwith per connection to" << maxBandwidthFloat << "Mb/s."
|
||||
|
@ -406,6 +407,15 @@ void AssetServer::completeSetup() {
|
|||
qCCritical(asset_server) << "Asset Server assignment will not continue because mapping file could not be loaded.";
|
||||
setFinished(true);
|
||||
}
|
||||
|
||||
// get file size limit for an asset
|
||||
static const QString ASSETS_FILESIZE_LIMIT_OPTION = "assets_filesize_limit";
|
||||
auto assetsFilesizeLimitJSONValue = assetServerObject[ASSETS_FILESIZE_LIMIT_OPTION];
|
||||
auto assetsFilesizeLimit = (uint64_t)assetsFilesizeLimitJSONValue.toInt(MAX_UPLOAD_SIZE);
|
||||
|
||||
if (assetsFilesizeLimit != 0 && assetsFilesizeLimit < MAX_UPLOAD_SIZE) {
|
||||
_filesizeLimit = assetsFilesizeLimit * BITS_PER_MEGABITS;
|
||||
}
|
||||
}
|
||||
|
||||
void AssetServer::cleanupUnmappedFiles() {
|
||||
|
@ -730,7 +740,7 @@ void AssetServer::handleAssetUpload(QSharedPointer<ReceivedMessage> message, Sha
|
|||
if (senderNode->getCanWriteToAssetServer()) {
|
||||
qCDebug(asset_server) << "Starting an UploadAssetTask for upload from" << uuidStringWithoutCurlyBraces(senderNode->getUUID());
|
||||
|
||||
auto task = new UploadAssetTask(message, senderNode, _filesDirectory);
|
||||
auto task = new UploadAssetTask(message, senderNode, _filesDirectory, _filesizeLimit);
|
||||
_transferTaskPool.start(task);
|
||||
} else {
|
||||
// this is a node the domain told us is not allowed to rez entities
|
||||
|
|
|
@ -127,6 +127,8 @@ private:
|
|||
bool _wasGrayscaleTextureCompressionEnabled { false };
|
||||
bool _wasNormalTextureCompressionEnabled { false };
|
||||
bool _wasCubeTextureCompressionEnabled { false };
|
||||
|
||||
uint64_t _filesizeLimit;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,10 +22,11 @@
|
|||
|
||||
|
||||
UploadAssetTask::UploadAssetTask(QSharedPointer<ReceivedMessage> receivedMessage, SharedNodePointer senderNode,
|
||||
const QDir& resourcesDir) :
|
||||
const QDir& resourcesDir, uint64_t filesizeLimit) :
|
||||
_receivedMessage(receivedMessage),
|
||||
_senderNode(senderNode),
|
||||
_resourcesDir(resourcesDir)
|
||||
_resourcesDir(resourcesDir),
|
||||
_filesizeLimit(filesizeLimit)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -48,7 +49,7 @@ void UploadAssetTask::run() {
|
|||
auto replyPacket = NLPacket::create(PacketType::AssetUploadReply, -1, true);
|
||||
replyPacket->writePrimitive(messageID);
|
||||
|
||||
if (fileSize > MAX_UPLOAD_SIZE) {
|
||||
if (fileSize > _filesizeLimit) {
|
||||
replyPacket->writePrimitive(AssetServerError::AssetTooLarge);
|
||||
} else {
|
||||
QByteArray fileData = buffer.read(fileSize);
|
||||
|
|
|
@ -26,7 +26,8 @@ class Node;
|
|||
|
||||
class UploadAssetTask : public QRunnable {
|
||||
public:
|
||||
UploadAssetTask(QSharedPointer<ReceivedMessage> message, QSharedPointer<Node> senderNode, const QDir& resourcesDir);
|
||||
UploadAssetTask(QSharedPointer<ReceivedMessage> message, QSharedPointer<Node> senderNode,
|
||||
const QDir& resourcesDir, uint64_t filesizeLimit);
|
||||
|
||||
void run() override;
|
||||
|
||||
|
@ -34,6 +35,7 @@ private:
|
|||
QSharedPointer<ReceivedMessage> _receivedMessage;
|
||||
QSharedPointer<Node> _senderNode;
|
||||
QDir _resourcesDir;
|
||||
uint64_t _filesizeLimit;
|
||||
};
|
||||
|
||||
#endif // hifi_UploadAssetTask_h
|
||||
|
|
|
@ -858,6 +858,14 @@
|
|||
"help": "The path to the directory assets are stored in.<br/>If this path is relative, it will be relative to the application data directory.<br/>If you change this path you will need to manually copy any existing assets from the previous directory.",
|
||||
"default": "",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "assets_filesize_limit",
|
||||
"type": "int",
|
||||
"label": "File Size Limit",
|
||||
"help": "The file size limit of an asset that can be imported into the asset server in MBytes. 0 (default) means no limit on file size.",
|
||||
"default": 0,
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -2,14 +2,14 @@ name = mannequin
|
|||
type = body+head
|
||||
scale = 1
|
||||
filename = mannequin/mannequin.baked.fbx
|
||||
joint = jointEyeLeft = LeftEye
|
||||
joint = jointRightHand = RightHand
|
||||
joint = jointHead = Head
|
||||
joint = jointEyeRight = RightEye
|
||||
joint = jointLean = Spine
|
||||
joint = jointNeck = Neck
|
||||
joint = jointLeftHand = LeftHand
|
||||
joint = jointRoot = Hips
|
||||
joint = jointLean = Spine
|
||||
joint = jointLeftHand = LeftHand
|
||||
joint = jointHead = Head
|
||||
joint = jointEyeLeft = LeftEye
|
||||
joint = jointEyeRight = RightEye
|
||||
joint = jointRightHand = RightHand
|
||||
joint = jointNeck = Neck
|
||||
freeJoint = LeftArm
|
||||
freeJoint = LeftForeArm
|
||||
freeJoint = RightArm
|
||||
|
@ -18,72 +18,72 @@ bs = EyeBlink_L = blink = 1
|
|||
bs = JawOpen = mouth_Open = 1
|
||||
bs = LipsFunnel = Oo = 1
|
||||
bs = BrowsU_L = brow_Up = 1
|
||||
jointIndex = RightHandIndex2 = 27
|
||||
jointIndex = LeftHandIndex2 = 51
|
||||
jointIndex = RightUpLeg = 6
|
||||
jointIndex = RightToe_End = 10
|
||||
jointIndex = RightEye = 65
|
||||
jointIndex = LeftHandPinky1 = 42
|
||||
jointIndex = RightHandRing1 = 22
|
||||
jointIndex = face = 67
|
||||
jointIndex = LeftUpLeg = 1
|
||||
jointIndex = LeftHand = 41
|
||||
jointIndex = LeftHandMiddle1 = 58
|
||||
jointIndex = LeftHandIndex1 = 50
|
||||
jointIndex = LeftEye = 64
|
||||
jointIndex = RightHandIndex1 = 26
|
||||
jointIndex = LeftHandPinky4 = 45
|
||||
jointIndex = RightArm = 15
|
||||
jointIndex = LeftShoulder = 38
|
||||
jointIndex = RightHandPinky2 = 19
|
||||
jointIndex = RightHandThumb1 = 30
|
||||
jointIndex = RightForeArm = 16
|
||||
jointIndex = LeftHandMiddle3 = 60
|
||||
jointIndex = Neck = 62
|
||||
jointIndex = LeftHandThumb1 = 54
|
||||
jointIndex = RightHandMiddle2 = 35
|
||||
jointIndex = LeftHandMiddle4 = 61
|
||||
jointIndex = mannequin = 68
|
||||
jointIndex = Spine1 = 12
|
||||
jointIndex = LeftHand = 41
|
||||
jointIndex = LeftHandRing4 = 49
|
||||
jointIndex = RightHandMiddle3 = 36
|
||||
jointIndex = LeftHandThumb4 = 57
|
||||
jointIndex = RightToe_End = 10
|
||||
jointIndex = LeftHandRing1 = 46
|
||||
jointIndex = LeftForeArm = 40
|
||||
jointIndex = RightHandIndex4 = 29
|
||||
jointIndex = LeftShoulder = 38
|
||||
jointIndex = RightHandMiddle4 = 37
|
||||
jointIndex = RightShoulder = 14
|
||||
jointIndex = LeftLeg = 2
|
||||
jointIndex = LeftToe_End = 5
|
||||
jointIndex = Hips = 0
|
||||
jointIndex = RightFoot = 8
|
||||
jointIndex = RightHandThumb2 = 31
|
||||
jointIndex = LeftHandMiddle3 = 60
|
||||
jointIndex = RightHandThumb1 = 30
|
||||
jointIndex = Neck = 62
|
||||
jointIndex = Spine = 11
|
||||
jointIndex = RightHandThumb4 = 33
|
||||
jointIndex = RightHandMiddle1 = 34
|
||||
jointIndex = LeftHandIndex4 = 53
|
||||
jointIndex = face = 68
|
||||
jointIndex = RightHandRing3 = 24
|
||||
jointIndex = LeftHandPinky4 = 45
|
||||
jointIndex = LeftHandMiddle2 = 59
|
||||
jointIndex = RightHandThumb3 = 32
|
||||
jointIndex = LeftHandPinky3 = 44
|
||||
jointIndex = HeadTop_End = 66
|
||||
jointIndex = Spine1 = 12
|
||||
jointIndex = LeftHandRing3 = 48
|
||||
jointIndex = mannequin1 = 67
|
||||
jointIndex = RightEye = 65
|
||||
jointIndex = RightHandRing4 = 25
|
||||
jointIndex = RightHandPinky4 = 21
|
||||
jointIndex = LeftHandRing2 = 47
|
||||
jointIndex = RightHandIndex3 = 28
|
||||
jointIndex = RightUpLeg = 6
|
||||
jointIndex = LeftArm = 39
|
||||
jointIndex = LeftHandThumb3 = 56
|
||||
jointIndex = RightHandIndex2 = 27
|
||||
jointIndex = RightForeArm = 16
|
||||
jointIndex = RightArm = 15
|
||||
jointIndex = RightHandRing2 = 23
|
||||
jointIndex = LeftHandMiddle1 = 58
|
||||
jointIndex = Spine2 = 13
|
||||
jointIndex = LeftHandThumb2 = 55
|
||||
jointIndex = RightHandMiddle2 = 35
|
||||
jointIndex = RightHandPinky1 = 18
|
||||
jointIndex = LeftUpLeg = 1
|
||||
jointIndex = RightLeg = 7
|
||||
jointIndex = LeftHandIndex2 = 51
|
||||
jointIndex = RightHand = 17
|
||||
jointIndex = LeftHandIndex3 = 52
|
||||
jointIndex = RightHandIndex3 = 28
|
||||
jointIndex = RightHandMiddle4 = 37
|
||||
jointIndex = LeftLeg = 2
|
||||
jointIndex = RightHandMiddle1 = 34
|
||||
jointIndex = Spine2 = 13
|
||||
jointIndex = LeftHandMiddle2 = 59
|
||||
jointIndex = LeftHandPinky3 = 44
|
||||
jointIndex = LeftHandThumb3 = 56
|
||||
jointIndex = LeftHandRing4 = 49
|
||||
jointIndex = RightHandThumb2 = 31
|
||||
jointIndex = LeftHandRing3 = 48
|
||||
jointIndex = HeadTop_End = 66
|
||||
jointIndex = LeftHandThumb4 = 57
|
||||
jointIndex = RightHandThumb3 = 32
|
||||
jointIndex = RightHandPinky1 = 18
|
||||
jointIndex = RightLeg = 7
|
||||
jointIndex = RightHandMiddle3 = 36
|
||||
jointIndex = RightHandPinky3 = 20
|
||||
jointIndex = LeftToeBase = 4
|
||||
jointIndex = LeftForeArm = 40
|
||||
jointIndex = RightShoulder = 14
|
||||
jointIndex = LeftHandRing2 = 47
|
||||
jointIndex = LeftHandThumb2 = 55
|
||||
jointIndex = Head = 63
|
||||
jointIndex = RightHandRing4 = 25
|
||||
jointIndex = LeftHandRing1 = 46
|
||||
jointIndex = LeftFoot = 3
|
||||
jointIndex = RightHandRing3 = 24
|
||||
jointIndex = RightHandThumb4 = 33
|
||||
jointIndex = LeftArm = 39
|
||||
jointIndex = LeftToe_End = 5
|
||||
jointIndex = RightHandPinky3 = 20
|
||||
jointIndex = RightHandIndex1 = 26
|
||||
jointIndex = LeftHandPinky1 = 42
|
||||
jointIndex = RightToeBase = 9
|
||||
jointIndex = RightHandPinky4 = 21
|
||||
jointIndex = Spine = 11
|
||||
jointIndex = LeftHandIndex4 = 53
|
||||
jointIndex = LeftHandIndex1 = 50
|
||||
jointIndex = LeftToeBase = 4
|
||||
jointIndex = LeftHandPinky2 = 43
|
||||
jointIndex = RightHandIndex4 = 29
|
||||
jointIndex = Hips = 0
|
||||
jointIndex = RightHandRing2 = 23
|
||||
jointIndex = RightHandRing1 = 22
|
||||
jointIndex = LeftHandThumb1 = 54
|
||||
jointIndex = LeftEye = 64
|
||||
jointIndex = Head = 63
|
||||
|
|
BIN
interface/resources/meshes/mannequin/Eyes.ktx
Executable file → Normal file
BIN
interface/resources/meshes/mannequin/Eyes.ktx
Executable file → Normal file
Binary file not shown.
BIN
interface/resources/meshes/mannequin/lambert1_Base_Color.ktx
Executable file → Normal file
BIN
interface/resources/meshes/mannequin/lambert1_Base_Color.ktx
Executable file → Normal file
Binary file not shown.
BIN
interface/resources/meshes/mannequin/lambert1_Normal_OpenGL.ktx
Executable file → Normal file
BIN
interface/resources/meshes/mannequin/lambert1_Normal_OpenGL.ktx
Executable file → Normal file
Binary file not shown.
BIN
interface/resources/meshes/mannequin/lambert1_Roughness.ktx
Executable file → Normal file
BIN
interface/resources/meshes/mannequin/lambert1_Roughness.ktx
Executable file → Normal file
Binary file not shown.
BIN
interface/resources/meshes/mannequin/mannequin.baked.fbx
Executable file → Normal file
BIN
interface/resources/meshes/mannequin/mannequin.baked.fbx
Executable file → Normal file
Binary file not shown.
|
@ -17,6 +17,7 @@ import "./hifi/audio" as HifiAudio
|
|||
Hifi.AvatarInputs {
|
||||
id: root;
|
||||
objectName: "AvatarInputs"
|
||||
property int modality: Qt.NonModal
|
||||
width: audio.width;
|
||||
height: audio.height;
|
||||
x: 10; y: 5;
|
||||
|
|
|
@ -8,6 +8,9 @@ Item {
|
|||
|
||||
anchors.leftMargin: 300
|
||||
objectName: "StatsItem"
|
||||
property int modality: Qt.NonModal
|
||||
implicitHeight: row.height
|
||||
implicitWidth: row.width
|
||||
|
||||
Component.onCompleted: {
|
||||
stats.parentChanged.connect(fill);
|
||||
|
@ -18,8 +21,9 @@ Item {
|
|||
}
|
||||
|
||||
function fill() {
|
||||
// Explicitly fill in order to avoid warnings at shutdown
|
||||
anchors.fill = parent;
|
||||
// This will cause a warning at shutdown, need to find another way to remove
|
||||
// the warning other than filling the anchors to the parent
|
||||
anchors.horizontalCenter = parent.horizontalCenter
|
||||
}
|
||||
|
||||
Hifi.Stats {
|
||||
|
|
|
@ -13,6 +13,7 @@ import "."
|
|||
|
||||
Rectangle {
|
||||
id: keyboardBase
|
||||
objectName: "keyboard"
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
@ -27,6 +28,8 @@ Rectangle {
|
|||
|
||||
readonly property int mirrorTextHeight: keyboardRowHeight
|
||||
|
||||
property bool password: false
|
||||
property alias mirroredText: mirrorText.text
|
||||
property bool showMirrorText: true
|
||||
readonly property int raisedHeight: 200
|
||||
|
||||
|
@ -112,16 +115,20 @@ Rectangle {
|
|||
color: "#252525"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
TextEdit {
|
||||
TextInput {
|
||||
id: mirrorText
|
||||
visible: showMirrorText
|
||||
size: 13.5
|
||||
FontLoader { id: ralewaySemiBold; source: "../../fonts/Raleway-SemiBold.ttf"; }
|
||||
font.family: ralewaySemiBold.name
|
||||
font.pointSize: 13.5
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: "#FFFFFF";
|
||||
anchors.fill: parent
|
||||
wrapMode: Text.WordWrap
|
||||
readOnly: false // we need to leave this property read-only to allow control to accept QKeyEvent
|
||||
readOnly: false // we need this to allow control to accept QKeyEvent
|
||||
selectByMouse: false
|
||||
echoMode: password ? TextInput.Password : TextInput.Normal
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key == Qt.Key_Return || event.key == Qt.Key_Space) {
|
||||
|
|
|
@ -301,15 +301,19 @@ FocusScope {
|
|||
function isPointOnWindow(point) {
|
||||
for (var i = 0; i < desktop.visibleChildren.length; i++) {
|
||||
var child = desktop.visibleChildren[i];
|
||||
if (child.visible) {
|
||||
if (child.hasOwnProperty("modality")) {
|
||||
var mappedPoint = child.mapFromGlobal(point.x, point.y);
|
||||
if (child.hasOwnProperty("modality")) {
|
||||
var mappedPoint = mapToItem(child, point.x, point.y);
|
||||
if (child.hasOwnProperty("frame")) {
|
||||
var outLine = child.frame.children[2];
|
||||
var framePoint = outLine.mapFromGlobal(point.x, point.y);
|
||||
if (child.contains(mappedPoint) || outLine.contains(framePoint)) {
|
||||
if (outLine.contains(framePoint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (child.contains(mappedPoint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -207,6 +207,17 @@
|
|||
#if defined(Q_OS_WIN)
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
// This is a HACK that uses private headers included with the qt source distrubution.
|
||||
// To use this feature you need to add these directores to your include path:
|
||||
// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1/QtCore
|
||||
// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1
|
||||
#define QT_BOOTSTRAPPED
|
||||
#include <private/qthread_p.h>
|
||||
#include <private/qobject_p.h>
|
||||
#undef QT_BOOTSTRAPPED
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
}
|
||||
|
@ -264,9 +275,7 @@ private:
|
|||
switch ((int)event->type()) {
|
||||
case ApplicationEvent::Render:
|
||||
render();
|
||||
// Ensure we never back up the render events. Each render should be triggered only in response
|
||||
// to the NEXT render event after the last render occured
|
||||
QCoreApplication::removePostedEvents(this, ApplicationEvent::Render);
|
||||
qApp->_pendingRenderEvent.store(false);
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -2712,9 +2721,14 @@ bool Application::importFromZIP(const QString& filePath) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// thread-safe
|
||||
void Application::onPresent(quint32 frameCount) {
|
||||
postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority);
|
||||
if (_renderEventHandler && !isAboutToQuit()) {
|
||||
bool expected = false;
|
||||
if (_pendingIdleEvent.compare_exchange_strong(expected, true)) {
|
||||
postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority);
|
||||
}
|
||||
expected = false;
|
||||
if (_renderEventHandler && !isAboutToQuit() && _pendingRenderEvent.compare_exchange_strong(expected, true)) {
|
||||
postEvent(_renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render));
|
||||
}
|
||||
}
|
||||
|
@ -2781,7 +2795,26 @@ bool Application::handleFileOpenEvent(QFileOpenEvent* fileEvent) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
static int getEventQueueSize(QThread* thread) {
|
||||
auto threadData = QThreadData::get2(thread);
|
||||
QMutexLocker locker(&threadData->postEventList.mutex);
|
||||
return threadData->postEventList.size();
|
||||
}
|
||||
|
||||
static void dumpEventQueue(QThread* thread) {
|
||||
auto threadData = QThreadData::get2(thread);
|
||||
QMutexLocker locker(&threadData->postEventList.mutex);
|
||||
qDebug() << "AJT: event list, size =" << threadData->postEventList.size();
|
||||
for (auto& postEvent : threadData->postEventList) {
|
||||
QEvent::Type type = (postEvent.event ? postEvent.event->type() : QEvent::None);
|
||||
qDebug() << "AJT: " << type;
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_EVENT_QUEUE
|
||||
|
||||
bool Application::event(QEvent* event) {
|
||||
|
||||
if (!Menu::getInstance()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2801,8 +2834,18 @@ bool Application::event(QEvent* event) {
|
|||
// see (windowMinimizedChanged)
|
||||
case ApplicationEvent::Idle:
|
||||
idle();
|
||||
// Don't process extra idle events that arrived in the event queue while we were doing this idle
|
||||
QCoreApplication::removePostedEvents(this, ApplicationEvent::Idle);
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
{
|
||||
int count = getEventQueueSize(QThread::currentThread());
|
||||
if (count > 400) {
|
||||
dumpEventQueue(QThread::currentThread());
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_EVENT_QUEUE
|
||||
|
||||
_pendingIdleEvent.store(false);
|
||||
|
||||
return true;
|
||||
|
||||
case QEvent::MouseMove:
|
||||
|
@ -7203,7 +7246,7 @@ void Application::updateDisplayMode() {
|
|||
_offscreenContext->makeCurrent();
|
||||
getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
|
||||
_displayPlugin = newDisplayPlugin;
|
||||
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
|
||||
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection);
|
||||
auto desktop = offscreenUi->getDesktop();
|
||||
if (desktop) {
|
||||
desktop->setProperty("repositionLocked", wasRepositionLocked);
|
||||
|
|
|
@ -717,5 +717,8 @@ private:
|
|||
LaserPointerManager _laserPointerManager;
|
||||
|
||||
friend class RenderEventHandler;
|
||||
|
||||
std::atomic<bool> _pendingIdleEvent { false };
|
||||
std::atomic<bool> _pendingRenderEvent { false };
|
||||
};
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -72,6 +72,12 @@ void Application::paintGL() {
|
|||
{
|
||||
QMutexLocker viewLocker(&_renderArgsMutex);
|
||||
renderArgs = _appRenderArgs._renderArgs;
|
||||
|
||||
// don't render if there is no context.
|
||||
if (!_appRenderArgs._renderArgs._context) {
|
||||
return;
|
||||
}
|
||||
|
||||
HMDSensorPose = _appRenderArgs._headPose;
|
||||
eyeToWorld = _appRenderArgs._eyeToWorld;
|
||||
sensorToWorld = _appRenderArgs._sensorToWorld;
|
||||
|
|
|
@ -53,7 +53,7 @@ const QUuid MY_AVATAR_KEY; // NULL key
|
|||
|
||||
AvatarManager::AvatarManager(QObject* parent) :
|
||||
_avatarsToFade(),
|
||||
_myAvatar(std::make_shared<MyAvatar>(qApp->thread()))
|
||||
_myAvatar(new MyAvatar(qApp->thread()), [](MyAvatar* ptr) { ptr->deleteLater(); })
|
||||
{
|
||||
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
||||
qRegisterMetaType<QWeakPointer<Node> >("NodeWeakPointer");
|
||||
|
@ -297,7 +297,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
|||
}
|
||||
|
||||
AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
||||
return std::make_shared<OtherAvatar>(qApp->thread());
|
||||
return AvatarSharedPointer(new OtherAvatar(qApp->thread()), [](OtherAvatar* ptr) { ptr->deleteLater(); });
|
||||
}
|
||||
|
||||
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
|
||||
|
|
|
@ -32,6 +32,7 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
|
|||
Q_PROPERTY(bool showTablet READ getShouldShowTablet)
|
||||
Q_PROPERTY(QUuid tabletID READ getCurrentTabletFrameID WRITE setCurrentTabletFrameID)
|
||||
Q_PROPERTY(QUuid homeButtonID READ getCurrentHomeButtonID WRITE setCurrentHomeButtonID)
|
||||
Q_PROPERTY(QUuid homeButtonHighlightID READ getCurrentHomeButtonHightlightID WRITE setCurrentHomeButtonHightlightID)
|
||||
Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID)
|
||||
|
||||
public:
|
||||
|
@ -97,6 +98,9 @@ public:
|
|||
void setCurrentHomeButtonID(QUuid homeButtonID) { _homeButtonID = homeButtonID; }
|
||||
QUuid getCurrentHomeButtonID() const { return _homeButtonID; }
|
||||
|
||||
void setCurrentHomeButtonHightlightID(QUuid homeButtonHightlightID) { _homeButtonHightlightID = homeButtonHightlightID; }
|
||||
QUuid getCurrentHomeButtonHightlightID() const { return _homeButtonHightlightID; }
|
||||
|
||||
void setCurrentTabletScreenID(QUuid tabletID) { _tabletScreenID = tabletID; }
|
||||
QUuid getCurrentTabletScreenID() const { return _tabletScreenID; }
|
||||
|
||||
|
@ -105,6 +109,7 @@ private:
|
|||
QUuid _tabletUIID; // this is the entityID of the tablet frame
|
||||
QUuid _tabletScreenID; // this is the overlayID which is part of (a child of) the tablet-ui.
|
||||
QUuid _homeButtonID;
|
||||
QUuid _homeButtonHightlightID;
|
||||
QUuid _tabletEntityID;
|
||||
|
||||
// Get the position of the HMD
|
||||
|
|
|
@ -106,14 +106,15 @@ extern std::atomic<size_t> DECIMATED_TEXTURE_COUNT;
|
|||
extern std::atomic<size_t> RECTIFIED_TEXTURE_COUNT;
|
||||
|
||||
void Stats::updateStats(bool force) {
|
||||
QQuickItem* parent = parentItem();
|
||||
if (!force) {
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
||||
if (isVisible()) {
|
||||
setVisible(false);
|
||||
if (parent->isVisible()) {
|
||||
parent->setVisible(false);
|
||||
}
|
||||
return;
|
||||
} else if (!isVisible()) {
|
||||
setVisible(true);
|
||||
} else if (!parent->isVisible()) {
|
||||
parent->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -161,33 +161,33 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties)
|
|||
Overlay::Pointer thisOverlay = nullptr;
|
||||
|
||||
if (type == ImageOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<ImageOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Image3DOverlay::TYPE || type == "billboard") { // "billboard" for backwards compatibility
|
||||
thisOverlay = std::make_shared<Image3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Image3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == TextOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<TextOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Text3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Text3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Text3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Shape3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Shape3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Shape3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Cube3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Cube3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Cube3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Sphere3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Sphere3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Sphere3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Circle3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Circle3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Circle3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Rectangle3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Rectangle3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Rectangle3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Line3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Line3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Line3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Grid3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Grid3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Grid3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == ModelOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<ModelOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new ModelOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Web3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Web3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Web3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == RectangleOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<RectangleOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new RectangleOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
}
|
||||
|
||||
if (thisOverlay) {
|
||||
|
@ -230,7 +230,7 @@ OverlayID Overlays::cloneOverlay(OverlayID id) {
|
|||
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||
|
||||
if (thisOverlay) {
|
||||
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone()));
|
||||
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone(), [](Overlay* ptr) { ptr->deleteLater(); }));
|
||||
#if OVERLAY_PANELS
|
||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(thisOverlay);
|
||||
if (attachable && attachable->getParentPanel()) {
|
||||
|
|
|
@ -46,6 +46,10 @@ static const int STATS_FOR_STATS_PACKET_WINDOW_SECONDS = 30;
|
|||
// _currentJitterBufferFrames is updated with the time-weighted avg and the running time-weighted avg is reset.
|
||||
static const quint64 FRAMES_AVAILABLE_STAT_WINDOW_USECS = 10 * USECS_PER_SECOND;
|
||||
|
||||
// When the audio codec is switched, temporary codec mismatch is expected due to packets in-flight.
|
||||
// A SelectedAudioFormat packet is not sent until this threshold is exceeded.
|
||||
static const int MAX_MISMATCHED_AUDIO_CODEC_COUNT = 10;
|
||||
|
||||
InboundAudioStream::InboundAudioStream(int numChannels, int numFrames, int numBlocks, int numStaticJitterBlocks) :
|
||||
_ringBuffer(numChannels * numFrames, numBlocks),
|
||||
_numChannels(numChannels),
|
||||
|
@ -153,6 +157,7 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
|
|||
// If we recieved a SilentAudioFrame from our sender, we might want to drop
|
||||
// some of the samples in order to catch up to our desired jitter buffer size.
|
||||
writeDroppableSilentFrames(networkFrames);
|
||||
|
||||
} else {
|
||||
// note: PCM and no codec are identical
|
||||
bool selectedPCM = _selectedCodecName == "pcm" || _selectedCodecName == "";
|
||||
|
@ -160,20 +165,33 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
|
|||
if (codecInPacket == _selectedCodecName || (packetPCM && selectedPCM)) {
|
||||
auto afterProperties = message.readWithoutCopy(message.getBytesLeftToRead());
|
||||
parseAudioData(message.getType(), afterProperties);
|
||||
_mismatchedAudioCodecCount = 0;
|
||||
|
||||
} else {
|
||||
qDebug(audio) << "Codec mismatch: expected" << _selectedCodecName << "got" << codecInPacket << "writing silence";
|
||||
_mismatchedAudioCodecCount++;
|
||||
qDebug(audio) << "Codec mismatch: expected" << _selectedCodecName << "got" << codecInPacket;
|
||||
|
||||
// Since the data in the stream is using a codec that we aren't prepared for,
|
||||
// we need to let the codec know that we don't have data for it, this will
|
||||
// allow the codec to interpolate missing data and produce a fade to silence.
|
||||
lostAudioData(1);
|
||||
|
||||
// inform others of the mismatch
|
||||
auto sendingNode = DependencyManager::get<NodeList>()->nodeWithUUID(message.getSourceID());
|
||||
if (sendingNode) {
|
||||
emit mismatchedAudioCodec(sendingNode, _selectedCodecName, codecInPacket);
|
||||
if (packetPCM) {
|
||||
// If there are PCM packets in-flight after the codec is changed, use them.
|
||||
auto afterProperties = message.readWithoutCopy(message.getBytesLeftToRead());
|
||||
_ringBuffer.writeData(afterProperties.data(), afterProperties.size());
|
||||
} else {
|
||||
// Since the data in the stream is using a codec that we aren't prepared for,
|
||||
// we need to let the codec know that we don't have data for it, this will
|
||||
// allow the codec to interpolate missing data and produce a fade to silence.
|
||||
lostAudioData(1);
|
||||
}
|
||||
|
||||
if (_mismatchedAudioCodecCount > MAX_MISMATCHED_AUDIO_CODEC_COUNT) {
|
||||
_mismatchedAudioCodecCount = 0;
|
||||
|
||||
// inform others of the mismatch
|
||||
auto sendingNode = DependencyManager::get<NodeList>()->nodeWithUUID(message.getSourceID());
|
||||
if (sendingNode) {
|
||||
emit mismatchedAudioCodec(sendingNode, _selectedCodecName, codecInPacket);
|
||||
qDebug(audio) << "Codec mismatch threshold exceeded, SelectedAudioFormat(" << _selectedCodecName << " ) sent";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -186,6 +186,7 @@ protected:
|
|||
CodecPluginPointer _codec;
|
||||
QString _selectedCodecName;
|
||||
Decoder* _decoder { nullptr };
|
||||
int _mismatchedAudioCodecCount { 0 };
|
||||
};
|
||||
|
||||
float calculateRepeatedFrameFadeFactor(int indexOfRepeat);
|
||||
|
|
|
@ -237,19 +237,7 @@ void EntityTreeRenderer::update(bool simulate) {
|
|||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
tree->update(simulate);
|
||||
|
||||
if (simulate) {
|
||||
// Handle enter/leave entity logic
|
||||
checkEnterLeaveEntities();
|
||||
|
||||
// Even if we're not moving the mouse, if we started clicking on an entity and we have
|
||||
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
||||
// and we want to simulate this message here as well as in mouse move
|
||||
if (_lastPointerEventValid && !_currentClickingOnEntityID.isInvalidID()) {
|
||||
emit holdingClickOnEntity(_currentClickingOnEntityID, _lastPointerEvent);
|
||||
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", _lastPointerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the rendereable entities as needed
|
||||
{
|
||||
PerformanceTimer sceneTimer("scene");
|
||||
auto scene = _viewState->getMain3DScene();
|
||||
|
@ -269,6 +257,20 @@ void EntityTreeRenderer::update(bool simulate) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (simulate) {
|
||||
// Handle enter/leave entity logic
|
||||
checkEnterLeaveEntities();
|
||||
|
||||
// Even if we're not moving the mouse, if we started clicking on an entity and we have
|
||||
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
||||
// and we want to simulate this message here as well as in mouse move
|
||||
if (_lastPointerEventValid && !_currentClickingOnEntityID.isInvalidID()) {
|
||||
emit holdingClickOnEntity(_currentClickingOnEntityID, _lastPointerEvent);
|
||||
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", _lastPointerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,8 @@ bool ModelEntityWrapper::isModelLoaded() const {
|
|||
}
|
||||
|
||||
EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity{ new RenderableModelEntityItem(entityID, properties.getDimensionsInitialized()) };
|
||||
EntityItemPointer entity(new RenderableModelEntityItem(entityID, properties.getDimensionsInitialized()),
|
||||
[](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ void loop3(const T& start, const T& end, F f) {
|
|||
}
|
||||
|
||||
EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
std::shared_ptr<RenderablePolyVoxEntityItem> entity{ new RenderablePolyVoxEntityItem(entityID) };
|
||||
std::shared_ptr<RenderablePolyVoxEntityItem> entity(new RenderablePolyVoxEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
entity->initializePolyVox();
|
||||
return entity;
|
||||
|
|
|
@ -30,7 +30,7 @@ const float LightEntityItem::DEFAULT_CUTOFF = PI / 2.0f;
|
|||
bool LightEntityItem::_lightsArePickable = false;
|
||||
|
||||
EntityItemPointer LightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new LightEntityItem(entityID) };
|
||||
EntityItemPointer entity(new LightEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ const int LineEntityItem::MAX_POINTS_PER_LINE = 70;
|
|||
|
||||
|
||||
EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new LineEntityItem(entityID) };
|
||||
EntityItemPointer entity(new LineEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
@ -214,4 +214,4 @@ void LineEntityItem::resetPointsChanged() {
|
|||
withWriteLock([&] {
|
||||
_pointsChanged = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ const QString ModelEntityItem::DEFAULT_MODEL_URL = QString("");
|
|||
const QString ModelEntityItem::DEFAULT_COMPOUND_SHAPE_URL = QString("");
|
||||
|
||||
EntityItemPointer ModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new ModelEntityItem(entityID) };
|
||||
EntityItemPointer entity(new ModelEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ uint64_t Properties::emitIntervalUsecs() const {
|
|||
|
||||
|
||||
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new ParticleEffectEntityItem(entityID) };
|
||||
EntityItemPointer entity(new ParticleEffectEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ const int PolyLineEntityItem::MAX_POINTS_PER_LINE = 70;
|
|||
|
||||
|
||||
EntityItemPointer PolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity{ new PolyLineEntityItem(entityID) };
|
||||
EntityItemPointer entity(new PolyLineEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ const QString PolyVoxEntityItem::DEFAULT_Y_TEXTURE_URL = QString("");
|
|||
const QString PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL = QString("");
|
||||
|
||||
EntityItemPointer PolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new PolyVoxEntityItem(entityID) };
|
||||
EntityItemPointer entity(new PolyVoxEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace entity {
|
|||
}
|
||||
|
||||
ShapeEntityItem::Pointer ShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
Pointer entity { new ShapeEntityItem(entityID) };
|
||||
Pointer entity(new ShapeEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ const xColor TextEntityItem::DEFAULT_BACKGROUND_COLOR = { 0, 0, 0};
|
|||
const bool TextEntityItem::DEFAULT_FACE_CAMERA = false;
|
||||
|
||||
EntityItemPointer TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new TextEntityItem(entityID) };
|
||||
EntityItemPointer entity(new TextEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
const QString WebEntityItem::DEFAULT_SOURCE_URL("http://www.google.com");
|
||||
|
||||
EntityItemPointer WebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new WebEntityItem(entityID) };
|
||||
EntityItemPointer entity(new WebEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ const bool ZoneEntityItem::DEFAULT_GHOSTING_ALLOWED = true;
|
|||
const QString ZoneEntityItem::DEFAULT_FILTER_URL = "";
|
||||
|
||||
EntityItemPointer ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new ZoneEntityItem(entityID) };
|
||||
EntityItemPointer entity(new ZoneEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -983,6 +983,9 @@ public:
|
|||
glm::vec2 dstCoord;
|
||||
glm::ivec2 srcPixel;
|
||||
for (int y = 0; y < faceWidth; ++y) {
|
||||
QRgb* destScanLineBegin = reinterpret_cast<QRgb*>( image.scanLine(y) );
|
||||
QRgb* destPixelIterator = destScanLineBegin;
|
||||
|
||||
dstCoord.y = 1.0f - (y + 0.5f) * dstInvSize.y; // Fill cube face images from top to bottom
|
||||
for (int x = 0; x < faceWidth; ++x) {
|
||||
dstCoord.x = (x + 0.5f) * dstInvSize.x;
|
||||
|
@ -995,13 +998,19 @@ public:
|
|||
srcPixel.y = floor((1.0f - srcCoord.y) * srcFaceHeight);
|
||||
|
||||
if (((uint32)srcPixel.x < (uint32)source.width()) && ((uint32)srcPixel.y < (uint32)source.height())) {
|
||||
image.setPixel(x, y, source.pixel(QPoint(srcPixel.x, srcPixel.y)));
|
||||
// We can't directly use the pixel() method because that launches a pixel color conversion to output
|
||||
// a correct RGBA8 color. But in our case we may have stored HDR values encoded in a RGB30 format which
|
||||
// are not convertible by Qt. The same goes with the setPixel method, by the way.
|
||||
const QRgb* sourcePixelIterator = reinterpret_cast<const QRgb*>(source.scanLine(srcPixel.y));
|
||||
sourcePixelIterator += srcPixel.x;
|
||||
*destPixelIterator = *sourcePixelIterator;
|
||||
|
||||
// Keep for debug, this is showing the dir as a color
|
||||
// glm::u8vec4 rgba((xyzDir.x + 1.0)*0.5 * 256, (xyzDir.y + 1.0)*0.5 * 256, (xyzDir.z + 1.0)*0.5 * 256, 256);
|
||||
// unsigned int val = 0xff000000 | (rgba.r) | (rgba.g << 8) | (rgba.b << 16);
|
||||
// image.setPixel(x, y, val);
|
||||
// *destPixelIterator = val;
|
||||
}
|
||||
++destPixelIterator;
|
||||
}
|
||||
}
|
||||
return image;
|
||||
|
@ -1192,6 +1201,10 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage&
|
|||
if ((srcImage.width() > 0) && (srcImage.height() > 0)) {
|
||||
QImage image = processSourceImage(srcImage, true);
|
||||
|
||||
if (image.format() != QIMAGE_HDR_FORMAT) {
|
||||
image = convertToHDRFormat(image, HDR_FORMAT);
|
||||
}
|
||||
|
||||
gpu::Element formatMip;
|
||||
gpu::Element formatGPU;
|
||||
if (isCubeTexturesCompressionEnabled()) {
|
||||
|
@ -1229,13 +1242,6 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage&
|
|||
faces.push_back(faceImage);
|
||||
}
|
||||
}
|
||||
|
||||
if (image.format() != QIMAGE_HDR_FORMAT) {
|
||||
for (auto& face : faces) {
|
||||
face = convertToHDRFormat(face, HDR_FORMAT);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
qCDebug(imagelogging) << "Failed to find a known cube map layout from this image:" << QString(srcImageName.c_str());
|
||||
return nullptr;
|
||||
|
|
|
@ -620,6 +620,12 @@ void NetworkTexture::ktxMipRequestFinished() {
|
|||
|
||||
texture->assignStoredMip(mipLevel, data.size(), reinterpret_cast<const uint8_t*>(data.data()));
|
||||
|
||||
// If mip level assigned above is still unavailable, then we assume future requests will also fail.
|
||||
auto minMipLevel = texture->minAvailableMipLevel();
|
||||
if (minMipLevel > mipLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(resource.data(), "setImage",
|
||||
Q_ARG(gpu::TexturePointer, texture),
|
||||
Q_ARG(int, texture->getWidth()),
|
||||
|
|
|
@ -37,7 +37,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
case PacketType::KillAvatar:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::AvatarIdentityLookAtSnapping);
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::UpdatedMannequinDefaultAvatar);
|
||||
case PacketType::MessagesData:
|
||||
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
|
||||
case PacketType::ICEServerHeartbeat:
|
||||
|
|
|
@ -300,6 +300,7 @@ enum class AvatarMixerPacketVersion : PacketVersion {
|
|||
AvatarIdentitySequenceFront,
|
||||
IsReplicatedInAvatarIdentity,
|
||||
AvatarIdentityLookAtSnapping,
|
||||
UpdatedMannequinDefaultAvatar
|
||||
};
|
||||
|
||||
enum class DomainConnectRequestVersion : PacketVersion {
|
||||
|
|
|
@ -1018,6 +1018,32 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key, QObject* targetOverrid
|
|||
}
|
||||
}
|
||||
|
||||
static void forEachKeyboard(QQuickItem* item, std::function<void(QQuickItem*)> function) {
|
||||
QObject* itemObject = item;
|
||||
while (itemObject) {
|
||||
if (itemObject->parent()) {
|
||||
itemObject = itemObject->parent();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto keyboards = itemObject->findChildren<QObject*>("keyboard");
|
||||
|
||||
for (auto keyboardObject : keyboards) {
|
||||
auto keyboard = qobject_cast<QQuickItem*>(keyboardObject);
|
||||
if (keyboard == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (function) {
|
||||
function(keyboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const int TEXTINPUT_PASSWORD = 2;
|
||||
|
||||
void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool numeric) {
|
||||
#if Q_OS_ANDROID
|
||||
return;
|
||||
|
@ -1030,6 +1056,26 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n
|
|||
// if HMD is being worn, allow keyboard to open. allow it to close, HMD or not.
|
||||
if (!raised || qApp->property(hifi::properties::HMD).toBool()) {
|
||||
QQuickItem* item = dynamic_cast<QQuickItem*>(object);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto echoMode = item->property("echoMode");
|
||||
bool isPasswordField = echoMode.isValid() && echoMode.toInt() == TEXTINPUT_PASSWORD;
|
||||
|
||||
// we need to somehow pass 'isPasswordField' to visible keyboard so it will change its 'mirror text' to asterixes
|
||||
// the issue in some cases there might be more than one keyboard in object tree and it is hard to understand which one is being used at the moment
|
||||
// unfortunately attempts to check for visibility failed becuase visibility is not updated yet. So... I don't see other way than just update properties for all the keyboards
|
||||
forEachKeyboard(item, [&](QQuickItem* keyboard) {
|
||||
keyboard->setProperty("mirroredText", QVariant::fromValue(QString("")));
|
||||
keyboard->setProperty("password", isPasswordField);
|
||||
});
|
||||
|
||||
// for future probably makes sense to consider one of the following:
|
||||
// 1. make keyboard a singleton, which will be dynamically re-parented before showing
|
||||
// 2. track currently visible keyboard somewhere, allow to subscribe for this signal
|
||||
// any of above should also eliminate need in duplicated properties and code below
|
||||
|
||||
while (item) {
|
||||
// Numeric value may be set in parameter from HTML UI; for QML UI, detect numeric fields here.
|
||||
numeric = numeric || QString(item->metaObject()->className()).left(7) == "SpinBox";
|
||||
|
|
|
@ -53,4 +53,8 @@ ScriptDiscoveryService.clearDebugWindow.connect(function() {
|
|||
window.clearDebugWindow();
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
window.close();
|
||||
})
|
||||
|
||||
}());
|
||||
|
|
|
@ -546,6 +546,12 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "releaseEquip", args);
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
|
||||
ensureDynamic(this.targetEntityID);
|
||||
this.targetEntityID = null;
|
||||
this.messageGrabEntity = false;
|
||||
|
|
|
@ -144,6 +144,12 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
Entities.deleteAction(this.targetEntityID, this.actionID);
|
||||
this.actionID = null;
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
|
||||
this.targetEntityID = null;
|
||||
};
|
||||
|
||||
|
|
|
@ -138,6 +138,11 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args);
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
};
|
||||
|
|
|
@ -148,6 +148,12 @@ Script.include("/~/system/libraries/utils.js");
|
|||
}
|
||||
}
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.grabbedThingID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
|
||||
this.grabbedThingID = null;
|
||||
};
|
||||
|
||||
|
|
|
@ -264,6 +264,8 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
if (!this.stylusTip.valid || this.overlayLaserActive(controllerData) || this.otherModuleNeedsToRun(controllerData)) {
|
||||
this.pointFinger(false);
|
||||
this.hideStylus();
|
||||
this.stylusTouchingTarget = false;
|
||||
this.relinquishTouchFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -149,6 +149,23 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
|
|||
parentJointIndex: -1
|
||||
});
|
||||
|
||||
this.homeButtonHighlightID = Overlays.addOverlay("circle3d", {
|
||||
name: "homeButtonHighlight",
|
||||
localPosition: { x: 0, y: -HOME_BUTTON_Y_OFFSET + 0.003, z: -0.0158 },
|
||||
localRotation: { x: 0, y: 1, z: 0, w: 0 },
|
||||
dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor },
|
||||
solid: true,
|
||||
outerRadius: 25 * tabletScaleFactor,
|
||||
innerRadius: 20 * tabletScaleFactor,
|
||||
ignoreIntersection: true,
|
||||
alpha: 1.0,
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
visible: visible,
|
||||
drawInFront: false,
|
||||
parentID: this.tabletEntityID,
|
||||
parentJointIndex: -1
|
||||
});
|
||||
|
||||
this.receive = function (channel, senderID, senderUUID, localOnly) {
|
||||
if (_this.homeButtonID == senderID) {
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
|
@ -169,6 +186,23 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
|
|||
}
|
||||
};
|
||||
|
||||
this.myOnHoverEnterOverlay = function (overlayID, pointerEvent) {
|
||||
_this.onHoverEnterOverlay(overlayID, pointerEvent);
|
||||
};
|
||||
|
||||
Overlays.hoverEnterOverlay.connect(this.myOnHoverEnterOverlay);
|
||||
|
||||
this.myOnHoverLeaveOverlay = function (overlayID, pointerEvent) {
|
||||
_this.onHoverLeaveOverlay(overlayID, pointerEvent);
|
||||
};
|
||||
|
||||
Overlays.hoverLeaveOverlay.connect(this.myOnHoverLeaveOverlay);
|
||||
|
||||
this.myOnHoverOverOverlay = function (overlayID, pointerEvent) {
|
||||
_this.onHoverOverOverlay(overlayID, pointerEvent);
|
||||
};
|
||||
Overlays.hoverOverOverlay.connect(this.myOnHoverOverOverlay);
|
||||
|
||||
this.state = "idle";
|
||||
|
||||
this.getRoot = function() {
|
||||
|
@ -272,9 +306,14 @@ WebTablet.prototype.setWidth = function (width) {
|
|||
};
|
||||
|
||||
WebTablet.prototype.destroy = function () {
|
||||
Overlays.hoverEnterOverlay.disconnect(this.myOnHoverEnterOverlay);
|
||||
Overlays.hoverLeaveOverlay.disconnect(this.myOnHoverLeaveOverlay);
|
||||
Overlays.hoverOverOverlay.disconnect(this.myOnHoverOverOverlay);
|
||||
|
||||
Overlays.deleteOverlay(this.webOverlayID);
|
||||
Overlays.deleteOverlay(this.tabletEntityID);
|
||||
Overlays.deleteOverlay(this.homeButtonID);
|
||||
Overlays.deleteOverlay(this.homeButtonHighlightID);
|
||||
HMD.displayModeChanged.disconnect(this.myOnHmdChanged);
|
||||
|
||||
Controller.mousePressEvent.disconnect(this.myMousePressEvent);
|
||||
|
@ -366,6 +405,24 @@ WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function (windowPos
|
|||
};
|
||||
};
|
||||
|
||||
WebTablet.prototype.onHoverEnterOverlay = function (overlayID, pointerEvent) {
|
||||
if (overlayID === this.homeButtonID) {
|
||||
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 1.0 });
|
||||
}
|
||||
}
|
||||
|
||||
WebTablet.prototype.onHoverOverOverlay = function (overlayID, pointerEvent) {
|
||||
if (overlayID !== this.homeButtonID) {
|
||||
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 0.0 });
|
||||
}
|
||||
}
|
||||
|
||||
WebTablet.prototype.onHoverLeaveOverlay = function (overlayID, pointerEvent) {
|
||||
if (overlayID === this.homeButtonID) {
|
||||
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 0.0 });
|
||||
}
|
||||
}
|
||||
|
||||
// compute position, rotation & parentJointIndex of the tablet
|
||||
WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMouse, tabletProperties) {
|
||||
if (HMD.active) {
|
||||
|
@ -503,6 +560,22 @@ WebTablet.prototype.scheduleMouseMoveProcessor = function() {
|
|||
}
|
||||
};
|
||||
|
||||
WebTablet.prototype.handleHomeButtonHover = function(x, y) {
|
||||
var pickRay = Camera.computePickRay(x, y);
|
||||
var entityPickResults;
|
||||
var homebuttonHovered = false;
|
||||
entityPickResults = Overlays.findRayIntersection(pickRay, true, [this.tabletEntityID]);
|
||||
if (entityPickResults.intersects && (entityPickResults.entityID === this.tabletEntityID ||
|
||||
entityPickResults.overlayID === this.tabletEntityID)) {
|
||||
var overlayPickResults = Overlays.findRayIntersection(pickRay, true, [this.homeButtonID], []);
|
||||
if (overlayPickResults.intersects && overlayPickResults.overlayID === this.homeButtonID) {
|
||||
homebuttonHovered = true;
|
||||
}
|
||||
}
|
||||
|
||||
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: homebuttonHovered ? 1.0 : 0.0 });
|
||||
}
|
||||
|
||||
WebTablet.prototype.mouseMoveEvent = function (event) {
|
||||
if (this.dragging) {
|
||||
this.currentMouse = {
|
||||
|
@ -510,6 +583,8 @@ WebTablet.prototype.mouseMoveEvent = function (event) {
|
|||
y: event.y
|
||||
};
|
||||
this.scheduleMouseMoveProcessor();
|
||||
} else {
|
||||
this.handleHomeButtonHover(event.x, event.y);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -536,6 +611,8 @@ WebTablet.prototype.mouseMoveProcessor = function () {
|
|||
});
|
||||
}
|
||||
this.scheduleMouseMoveProcessor();
|
||||
} else {
|
||||
this.handleHomeButtonHover(this.currentMouse.x, this.currentMouse.y);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -370,7 +370,7 @@ getTabletWidthFromSettings = function () {
|
|||
|
||||
resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride) {
|
||||
|
||||
if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID) {
|
||||
if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID || !HMD.homeButtonHighlightID) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -413,4 +413,11 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
|
|||
localPosition: {x: -0.001, y: -HOME_BUTTON_Y_OFFSET, z: 0.0},
|
||||
dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor}
|
||||
});
|
||||
|
||||
Overlays.editOverlay(HMD.homeButtonHighlightID, {
|
||||
localPosition: { x: 0, y: -HOME_BUTTON_Y_OFFSET + 0.003, z: -0.0158 },
|
||||
dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor },
|
||||
outerRadius: 25 * tabletScaleFactor,
|
||||
innerRadius: 20 * tabletScaleFactor
|
||||
});
|
||||
};
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
UIWebTablet.register();
|
||||
HMD.tabletID = UIWebTablet.tabletEntityID;
|
||||
HMD.homeButtonID = UIWebTablet.homeButtonID;
|
||||
HMD.homeButtonHighlightID = UIWebTablet.homeButtonHighlightID;
|
||||
HMD.tabletScreenID = UIWebTablet.webOverlayID;
|
||||
HMD.displayModeChanged.connect(onHmdChanged);
|
||||
MyAvatar.sensorToWorldScaleChanged.connect(onSensorToWorldScaleChanged);
|
||||
|
@ -127,6 +128,7 @@
|
|||
tabletProperties.visible = true;
|
||||
Overlays.editOverlay(HMD.tabletID, tabletProperties);
|
||||
Overlays.editOverlay(HMD.homeButtonID, { visible: true });
|
||||
Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: true });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { visible: true });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 90 });
|
||||
updateTabletWidthFromSettings(true);
|
||||
|
@ -147,6 +149,7 @@
|
|||
|
||||
Overlays.editOverlay(HMD.tabletID, { visible: false });
|
||||
Overlays.editOverlay(HMD.homeButtonID, { visible: false });
|
||||
Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: false });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { visible: false });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 1 });
|
||||
}
|
||||
|
@ -167,6 +170,7 @@
|
|||
UIWebTablet = null;
|
||||
HMD.tabletID = null;
|
||||
HMD.homeButtonID = null;
|
||||
HMD.homeButtonHighlightID = null;
|
||||
HMD.tabletScreenID = null;
|
||||
} else if (debugTablet) {
|
||||
print("TABLET closeTabletUI, UIWebTablet is null");
|
||||
|
@ -319,6 +323,7 @@
|
|||
Overlays.deleteOverlay(tabletID);
|
||||
HMD.tabletID = null;
|
||||
HMD.homeButtonID = null;
|
||||
HMD.homeButtonHighlightID = null;
|
||||
HMD.tabletScreenID = null;
|
||||
});
|
||||
}()); // END LOCAL_SCOPE
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global CreatePalette: true, App, Feedback, History, UIT */
|
||||
/* global CreatePalette:true, App, Feedback, History, Preload, UIT */
|
||||
|
||||
CreatePalette = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
||||
// Tool menu displayed on top of forearm.
|
||||
|
@ -332,6 +332,11 @@ CreatePalette = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
|||
}
|
||||
|
||||
|
||||
function getAssetURLs() {
|
||||
return Preload.findURLs([PALETTE_HEADER_HEADING_PROPERTIES, PALETTE_HEADER_BAR_PROPERTIES, PALETTE_TITLE_PROPERTIES,
|
||||
PALETTE_ITEMS]);
|
||||
}
|
||||
|
||||
function setHand(hand) {
|
||||
// Assumes UI is not displaying.
|
||||
var NUMBER_OF_HANDS = 2;
|
||||
|
@ -533,6 +538,7 @@ CreatePalette = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
|||
}
|
||||
|
||||
return {
|
||||
assetURLs: getAssetURLs,
|
||||
setHand: setHand,
|
||||
overlayIDs: getOverlayIDs,
|
||||
setVisible: setVisible,
|
||||
|
|
175
unpublishedScripts/marketplace/shapes/modules/preload.js
Normal file
175
unpublishedScripts/marketplace/shapes/modules/preload.js
Normal file
|
@ -0,0 +1,175 @@
|
|||
//
|
||||
// preload.js
|
||||
//
|
||||
// Created by David Rowe on 11 Oct 2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global Preload:true, App */
|
||||
|
||||
Preload = (function () {
|
||||
// Provide facility to preload asset files so that they are in disk cache.
|
||||
// Global object.
|
||||
|
||||
"use strict";
|
||||
|
||||
var loadTimer = null,
|
||||
urlsToLoad = [],
|
||||
nextURLToLoad = 0,
|
||||
LOAD_INTERVAL = 50, // ms
|
||||
overlays = [],
|
||||
deleteTimer = null,
|
||||
DELETE_INTERVAL = LOAD_INTERVAL; // ms
|
||||
|
||||
function findURLs(items) {
|
||||
var urls = [],
|
||||
i,
|
||||
length;
|
||||
|
||||
function findURLsInObject(item) {
|
||||
var property;
|
||||
|
||||
for (property in item) {
|
||||
if (item.hasOwnProperty(property)) {
|
||||
if (property === "url" || property === "imageURL" || property === "imageOverlayURL") {
|
||||
if (item[property]) {
|
||||
urls.push(item[property]);
|
||||
}
|
||||
} else if (typeof item[property] === "object") {
|
||||
findURLsInObject(item[property]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, length = items.length; i < length; i++) {
|
||||
switch (typeof items[i]) {
|
||||
case "string":
|
||||
urls.push(items[i]);
|
||||
break;
|
||||
case "object":
|
||||
findURLsInObject(items[i]);
|
||||
break;
|
||||
default:
|
||||
App.log("ERROR: Cannot find URL in item type " + (typeof items[i]));
|
||||
}
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
function deleteOverlay() {
|
||||
if (overlays.length === 0) { // Just in case.
|
||||
deleteTimer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Overlays.deleteOverlay(overlays[0]);
|
||||
overlays.shift();
|
||||
|
||||
if (overlays.length > 0) {
|
||||
deleteTimer = Script.setTimeout(deleteOverlay, DELETE_INTERVAL);
|
||||
} else {
|
||||
deleteTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function loadNextURL() {
|
||||
|
||||
function loadURL(url) {
|
||||
var DOMAIN_CORNER = { x: -16382, y: -16382, z: -16382 }, // Near but not right on domain corner.
|
||||
DUMMY_OVERLAY_PROPERTIES = {
|
||||
fbx: {
|
||||
overlay: "model",
|
||||
dimensions: { x: 0.001, y: 0.001, z: 0.001 },
|
||||
position: DOMAIN_CORNER,
|
||||
ignoreRayIntersection: false,
|
||||
alpha: 0.0,
|
||||
visible: false
|
||||
},
|
||||
svg: {
|
||||
overlay: "image3d",
|
||||
scale: 0.001,
|
||||
position: DOMAIN_CORNER,
|
||||
ignoreRayIntersection: true,
|
||||
alpha: 0.0,
|
||||
visible: false
|
||||
},
|
||||
png: {
|
||||
overlay: "image3d",
|
||||
scale: 0.001,
|
||||
position: DOMAIN_CORNER,
|
||||
ignoreRayIntersection: true,
|
||||
alpha: 0.0,
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
fileType,
|
||||
properties;
|
||||
|
||||
fileType = url.slice(-3);
|
||||
if (DUMMY_OVERLAY_PROPERTIES.hasOwnProperty(fileType)) {
|
||||
properties = Object.clone(DUMMY_OVERLAY_PROPERTIES[fileType]);
|
||||
properties.url = url;
|
||||
overlays.push(Overlays.addOverlay(properties.overlay, properties));
|
||||
if (deleteTimer === null) {
|
||||
// Can't delete overlay straight away otherwise asset load is abandoned.
|
||||
deleteTimer = Script.setTimeout(deleteOverlay, DELETE_INTERVAL);
|
||||
}
|
||||
} else {
|
||||
App.log("ERROR: Cannot preload asset " + url);
|
||||
}
|
||||
}
|
||||
|
||||
// Find next URL that hasn't already been loaded;
|
||||
while (nextURLToLoad < urlsToLoad.length && urlsToLoad.indexOf(urlsToLoad[nextURLToLoad]) < nextURLToLoad) {
|
||||
nextURLToLoad += 1;
|
||||
}
|
||||
|
||||
// Load the URL if there's one to load.
|
||||
if (nextURLToLoad < urlsToLoad.length) {
|
||||
// Load the URL.
|
||||
loadURL(urlsToLoad[nextURLToLoad]);
|
||||
nextURLToLoad += 1;
|
||||
|
||||
// Load the next, if any, after a short delay.
|
||||
loadTimer = Script.setTimeout(loadNextURL, LOAD_INTERVAL);
|
||||
} else {
|
||||
loadTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function load(urls) {
|
||||
urlsToLoad = urlsToLoad.concat(urls);
|
||||
if (loadTimer === null) {
|
||||
loadNextURL();
|
||||
}
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
var i,
|
||||
length;
|
||||
|
||||
if (loadTimer) {
|
||||
Script.clearTimeout(loadTimer);
|
||||
}
|
||||
|
||||
if (deleteTimer) {
|
||||
Script.clearTimeout(deleteTimer);
|
||||
for (i = 0, length = overlays.length; i < length; i++) {
|
||||
Overlays.deleteOverlay(overlays[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(tearDown);
|
||||
|
||||
return {
|
||||
findURLs: findURLs,
|
||||
load: load
|
||||
};
|
||||
|
||||
}());
|
|
@ -72,6 +72,10 @@ ToolIcon = function (side) {
|
|||
return new ToolIcon();
|
||||
}
|
||||
|
||||
function getAssetURLs() {
|
||||
return [MODEL_PROPERTIES.url];
|
||||
}
|
||||
|
||||
function setHand(side) {
|
||||
// Assumes UI is not displaying.
|
||||
if (side === LEFT_HAND) {
|
||||
|
@ -154,6 +158,7 @@ ToolIcon = function (side) {
|
|||
}
|
||||
|
||||
return {
|
||||
assetURLs: getAssetURLs,
|
||||
setHand: setHand,
|
||||
display: display,
|
||||
clear: clear,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global ToolsMenu: true, App, Feedback, UIT */
|
||||
/* global ToolsMenu:true, App, Feedback, Preload, UIT */
|
||||
|
||||
ToolsMenu = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
||||
// Tool menu displayed on top of forearm.
|
||||
|
@ -2042,6 +2042,12 @@ ToolsMenu = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
|||
return new ToolsMenu();
|
||||
}
|
||||
|
||||
function getAssetURLs() {
|
||||
return Preload.findURLs([MENU_HEADER_HEADING_PROPERTIES, MENU_HEADER_BAR_PROPERTIES, MENU_HEADER_BACK_PROPERTIES,
|
||||
MENU_HEADER_TITLE_PROPERTIES, MENU_HEADER_TITLE_BACK_URL, MENU_HEADER_ICON_PROPERTIES, UI_ELEMENTS,
|
||||
PICKLIST_UP_ARROW, PICKLIST_DOWN_ARROW, OPTONS_PANELS, MENU_ITEMS, FOOTER_ITEMS]);
|
||||
}
|
||||
|
||||
controlHand = side === LEFT_HAND ? rightInputs.hand() : leftInputs.hand();
|
||||
|
||||
function setHand(hand) {
|
||||
|
@ -3672,6 +3678,7 @@ ToolsMenu = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
|||
}
|
||||
|
||||
return {
|
||||
assetURLs: getAssetURLs,
|
||||
COLOR_TOOL: COLOR_TOOL,
|
||||
SCALE_TOOL: SCALE_TOOL,
|
||||
CLONE_TOOL: CLONE_TOOL,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global Feedback, History */
|
||||
/* global Feedback, History, Preload */
|
||||
|
||||
(function () {
|
||||
|
||||
|
@ -87,6 +87,7 @@
|
|||
Script.include("./modules/highlights.js");
|
||||
Script.include("./modules/history.js");
|
||||
Script.include("./modules/laser.js");
|
||||
Script.include("./modules/preload.js");
|
||||
Script.include("./modules/selection.js");
|
||||
Script.include("./modules/toolIcon.js");
|
||||
Script.include("./modules/toolsMenu.js");
|
||||
|
@ -235,8 +236,12 @@
|
|||
}
|
||||
|
||||
toolIcon = new ToolIcon(otherHand(side));
|
||||
toolsMenu = new ToolsMenu(side, leftInputs, rightInputs, uiCommandCallback);
|
||||
createPalette = new CreatePalette(side, leftInputs, rightInputs, uiCommandCallback);
|
||||
toolsMenu = new ToolsMenu(side, leftInputs, rightInputs, uiCommandCallback);
|
||||
|
||||
Preload.load(toolIcon.assetURLs());
|
||||
Preload.load(createPalette.assetURLs());
|
||||
Preload.load(toolsMenu.assetURLs());
|
||||
|
||||
getIntersection = side === LEFT_HAND ? rightInputs.intersection : leftInputs.intersection;
|
||||
|
||||
|
|
Loading…
Reference in a new issue