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

This commit is contained in:
Atlante45 2017-06-19 11:06:51 -07:00
commit c4c6142935
43 changed files with 201 additions and 127 deletions

View file

@ -12,12 +12,19 @@ elseif ($ENV{QT_CMAKE_PREFIX_PATH})
set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
endif () endif ()
set(QUAZIP_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON)
if (APPLE)
else ()
set(QUAZIP_CMAKE_ARGS ${QUAZIP_CMAKE_ARGS} -DCMAKE_CXX_STANDARD=11)
endif ()
ExternalProject_Add( ExternalProject_Add(
${EXTERNAL_NAME} ${EXTERNAL_NAME}
URL https://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.7.2.zip URL https://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.7.2.zip
URL_MD5 2955176048a31262c09259ca8d309d19 URL_MD5 2955176048a31262c09259ca8d309d19
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON CMAKE_ARGS ${QUAZIP_CMAKE_ARGS}
LOG_DOWNLOAD 1 LOG_DOWNLOAD 1
LOG_CONFIGURE 1 LOG_CONFIGURE 1
LOG_BUILD 1 LOG_BUILD 1

View file

@ -353,6 +353,14 @@ FocusScope {
showDesktop(); showDesktop();
} }
function ensureTitleBarVisible(targetWindow) {
// Reposition window to ensure that title bar is vertically inside window.
if (targetWindow.frame && targetWindow.frame.decoration) {
var topMargin = -targetWindow.frame.decoration.anchors.topMargin; // Frame's topMargin is a negative value.
targetWindow.y = Math.max(targetWindow.y, topMargin);
}
}
function centerOnVisible(item) { function centerOnVisible(item) {
var targetWindow = d.getDesktopWindow(item); var targetWindow = d.getDesktopWindow(item);
if (!targetWindow) { if (!targetWindow) {
@ -375,11 +383,12 @@ FocusScope {
targetWindow.x = newX; targetWindow.x = newX;
targetWindow.y = newY; targetWindow.y = newY;
ensureTitleBarVisible(targetWindow);
// If we've noticed that our recommended desktop rect has changed, record that change here. // If we've noticed that our recommended desktop rect has changed, record that change here.
if (recommendedRect != newRecommendedRect) { if (recommendedRect != newRecommendedRect) {
recommendedRect = newRecommendedRect; recommendedRect = newRecommendedRect;
} }
} }
function repositionOnVisible(item) { function repositionOnVisible(item) {
@ -394,7 +403,6 @@ FocusScope {
return; return;
} }
var oldRecommendedRect = recommendedRect; var oldRecommendedRect = recommendedRect;
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height }; var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
var newRecommendedRect = Controller.getRecommendedOverlayRect(); var newRecommendedRect = Controller.getRecommendedOverlayRect();
@ -426,7 +434,6 @@ FocusScope {
newPosition.y = -1 newPosition.y = -1
} }
if (newPosition.x === -1 && newPosition.y === -1) { if (newPosition.x === -1 && newPosition.y === -1) {
var originRelativeX = (targetWindow.x - oldRecommendedRect.x); var originRelativeX = (targetWindow.x - oldRecommendedRect.x);
var originRelativeY = (targetWindow.y - oldRecommendedRect.y); var originRelativeY = (targetWindow.y - oldRecommendedRect.y);
@ -444,6 +451,8 @@ FocusScope {
} }
targetWindow.x = newPosition.x; targetWindow.x = newPosition.x;
targetWindow.y = newPosition.y; targetWindow.y = newPosition.y;
ensureTitleBarVisible(targetWindow);
} }
Component { id: messageDialogBuilder; MessageDialog { } } Component { id: messageDialogBuilder; MessageDialog { } }

View file

@ -590,14 +590,11 @@ Item {
console.log("This avatar is no longer present. goToUserInDomain() failed."); console.log("This avatar is no longer present. goToUserInDomain() failed.");
return; return;
} }
var vector = Vec3.subtract(avatar.position, MyAvatar.position);
var distance = Vec3.length(vector);
var target = Vec3.multiply(Vec3.normalize(vector), distance - 2.0);
// FIXME: We would like the avatar to recompute the avatar's "maybe fly" test at the new position, so that if high enough up, // FIXME: We would like the avatar to recompute the avatar's "maybe fly" test at the new position, so that if high enough up,
// the avatar goes into fly mode rather than falling. However, that is not exposed to Javascript right now. // the avatar goes into fly mode rather than falling. However, that is not exposed to Javascript right now.
// FIXME: it would be nice if this used the same teleport steps and smoothing as in the teleport.js script. // FIXME: it would be nice if this used the same teleport steps and smoothing as in the teleport.js script.
// Note, however, that this script allows teleporting to a person in the air, while teleport.js is going to a grounded target. // Note, however, that this script allows teleporting to a person in the air, while teleport.js is going to a grounded target.
MyAvatar.orientation = Quat.lookAtSimple(MyAvatar.position, avatar.position); MyAvatar.position = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.orientation, {x: 0, y: 0, z: -2}));
MyAvatar.position = Vec3.sum(MyAvatar.position, target); MyAvatar.orientation = Quat.multiply(avatar.orientation, {y: 1});
} }
} }

View file

@ -955,7 +955,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
updateHeartbeat(); updateHeartbeat();
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); connect(this, SIGNAL(aboutToQuit()), this, SLOT(onAboutToQuit()));
// hook up bandwidth estimator // hook up bandwidth estimator
QSharedPointer<BandwidthRecorder> bandwidthRecorder = DependencyManager::get<BandwidthRecorder>(); QSharedPointer<BandwidthRecorder> bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
@ -1449,7 +1449,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}); });
sendStatsTimer->start(); sendStatsTimer->start();
// Periodically check for count of nearby avatars // Periodically check for count of nearby avatars
static int lastCountOfNearbyAvatars = -1; static int lastCountOfNearbyAvatars = -1;
QTimer* checkNearbyAvatarsTimer = new QTimer(this); QTimer* checkNearbyAvatarsTimer = new QTimer(this);
@ -1644,7 +1643,7 @@ void Application::updateHeartbeat() const {
static_cast<DeadlockWatchdogThread*>(_deadlockWatchdogThread)->updateHeartbeat(); static_cast<DeadlockWatchdogThread*>(_deadlockWatchdogThread)->updateHeartbeat();
} }
void Application::aboutToQuit() { void Application::onAboutToQuit() {
emit beforeAboutToQuit(); emit beforeAboutToQuit();
foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) {

View file

@ -399,7 +399,7 @@ private slots:
void showDesktop(); void showDesktop();
void clearDomainOctreeDetails(); void clearDomainOctreeDetails();
void clearDomainAvatars(); void clearDomainAvatars();
void aboutToQuit(); void onAboutToQuit();
void resettingDomain(); void resettingDomain();

View file

@ -440,17 +440,27 @@ void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) {
touchEvent->setTouchPoints(touchPoints); touchEvent->setTouchPoints(touchPoints);
touchEvent->setTouchPointStates(touchPointState); touchEvent->setTouchPointStates(touchPointState);
// Send mouse events to the Web surface so that HTML dialog elements work with mouse press and hover.
// FIXME: Scroll bar dragging is a bit unstable in the tablet (content can jump up and down at times).
// This may be improved in Qt 5.8. Release notes: "Cleaned up touch and mouse event delivery".
//
// In Qt 5.9 mouse events must be sent before touch events to make sure some QtQuick components will
// receive mouse events
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
if (!(this->_pressed && event.getType() == PointerEvent::Move)) {
QMouseEvent* mouseEvent = new QMouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent);
}
#endif
QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent);
if (this->_pressed && event.getType() == PointerEvent::Move) { #if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
if (this->_pressed && event.getType() == PointerEvent::Move) {
return; return;
} }
// Send mouse events to the Web surface so that HTML dialog elements work with mouse press and hover.
// FIXME: Scroll bar dragging is a bit unstable in the tablet (content can jump up and down at times).
// This may be improved in Qt 5.8. Release notes: "Cleaned up touch and mouse event delivery".
QMouseEvent* mouseEvent = new QMouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); QMouseEvent* mouseEvent = new QMouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent);
#endif
} }
void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) { void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) {

View file

@ -223,12 +223,21 @@ TransferJob::TransferJob(const GLTexture& parent, uint16_t sourceMip, uint16_t t
// Buffering can invoke disk IO, so it should be off of the main and render threads // Buffering can invoke disk IO, so it should be off of the main and render threads
_bufferingLambda = [=] { _bufferingLambda = [=] {
_mipData = _parent._gpuObject.accessStoredMipFace(sourceMip, face)->createView(_transferSize, _transferOffset); auto mipStorage = _parent._gpuObject.accessStoredMipFace(sourceMip, face);
if (mipStorage) {
_mipData = mipStorage->createView(_transferSize, _transferOffset);
} else {
qCWarning(gpugllogging) << "Buffering failed because mip could not be retrieved from texture " << _parent._source.c_str() ;
}
}; };
_transferLambda = [=] { _transferLambda = [=] {
_parent.copyMipFaceLinesFromTexture(targetMip, face, transferDimensions, lineOffset, internalFormat, format, type, _mipData->size(), _mipData->readData()); if (_mipData) {
_mipData.reset(); _parent.copyMipFaceLinesFromTexture(targetMip, face, transferDimensions, lineOffset, internalFormat, format, type, _mipData->size(), _mipData->readData());
_mipData.reset();
} else {
qCWarning(gpugllogging) << "Transfer failed because mip could not be retrieved from texture " << _parent._source.c_str();
}
}; };
} }

View file

@ -18,7 +18,7 @@
#include <QUrl> #include <QUrl>
#include <shared/Storage.h> #include <shared/Storage.h>
#include <shared/FileCache.h>
#include "Forward.h" #include "Forward.h"
#include "Resource.h" #include "Resource.h"
#include "Metric.h" #include "Metric.h"
@ -311,6 +311,7 @@ public:
class KtxStorage : public Storage { class KtxStorage : public Storage {
public: public:
KtxStorage(const std::string& filename); KtxStorage(const std::string& filename);
KtxStorage(const cache::FilePointer& file);
PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override; PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override;
Size getMipFaceSize(uint16 level, uint8 face = 0) const override; Size getMipFaceSize(uint16 level, uint8 face = 0) const override;
bool isMipAvailable(uint16 level, uint8 face = 0) const override; bool isMipAvailable(uint16 level, uint8 face = 0) const override;
@ -328,6 +329,7 @@ public:
mutable std::weak_ptr<storage::FileStorage> _cacheFile; mutable std::weak_ptr<storage::FileStorage> _cacheFile;
std::string _filename; std::string _filename;
cache::FilePointer _cacheEntry;
std::atomic<uint8_t> _minMipLevelAvailable; std::atomic<uint8_t> _minMipLevelAvailable;
size_t _offsetToMinMipKV; size_t _offsetToMinMipKV;
@ -499,6 +501,7 @@ public:
void setStorage(std::unique_ptr<Storage>& newStorage); void setStorage(std::unique_ptr<Storage>& newStorage);
void setKtxBacking(const std::string& filename); void setKtxBacking(const std::string& filename);
void setKtxBacking(const cache::FilePointer& cacheEntry);
// Usage is a a set of flags providing Semantic about the usage of the Texture. // Usage is a a set of flags providing Semantic about the usage of the Texture.
void setUsage(const Usage& usage) { _usage = usage; } void setUsage(const Usage& usage) { _usage = usage; }
@ -529,8 +532,9 @@ public:
// Serialize a texture into a KTX file // Serialize a texture into a KTX file
static ktx::KTXUniquePointer serialize(const Texture& texture); static ktx::KTXUniquePointer serialize(const Texture& texture);
static TexturePointer build(const ktx::KTXDescriptor& descriptor);
static TexturePointer unserialize(const std::string& ktxFile); static TexturePointer unserialize(const std::string& ktxFile);
static TexturePointer unserialize(const std::string& ktxFile, const ktx::KTXDescriptor& descriptor); static TexturePointer unserialize(const cache::FilePointer& cacheEntry);
static bool evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header); static bool evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header);
static bool evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat); static bool evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat);

View file

@ -154,6 +154,10 @@ struct IrradianceKTXPayload {
}; };
const std::string IrradianceKTXPayload::KEY{ "hifi.irradianceSH" }; const std::string IrradianceKTXPayload::KEY{ "hifi.irradianceSH" };
KtxStorage::KtxStorage(const cache::FilePointer& cacheEntry) : KtxStorage(cacheEntry->getFilepath()) {
_cacheEntry = cacheEntry;
}
KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) {
{ {
// We are doing a lot of work here just to get descriptor data // We are doing a lot of work here just to get descriptor data
@ -295,20 +299,35 @@ void KtxStorage::assignMipFaceData(uint16 level, uint8 face, const storage::Stor
throw std::runtime_error("Invalid call"); throw std::runtime_error("Invalid call");
} }
bool validKtx(const std::string& filename) {
ktx::StoragePointer storage { new storage::FileStorage(filename.c_str()) };
auto ktxPointer = ktx::KTX::create(storage);
if (!ktxPointer) {
return false;
}
return true;
}
void Texture::setKtxBacking(const std::string& filename) { void Texture::setKtxBacking(const std::string& filename) {
// Check the KTX file for validity before using it as backing storage // Check the KTX file for validity before using it as backing storage
{ if (!validKtx(filename)) {
ktx::StoragePointer storage { new storage::FileStorage(filename.c_str()) }; return;
auto ktxPointer = ktx::KTX::create(storage);
if (!ktxPointer) {
return;
}
} }
auto newBacking = std::unique_ptr<Storage>(new KtxStorage(filename)); auto newBacking = std::unique_ptr<Storage>(new KtxStorage(filename));
setStorage(newBacking); setStorage(newBacking);
} }
void Texture::setKtxBacking(const cache::FilePointer& cacheEntry) {
// Check the KTX file for validity before using it as backing storage
if (!validKtx(cacheEntry->getFilepath())) {
return;
}
auto newBacking = std::unique_ptr<Storage>(new KtxStorage(cacheEntry));
setStorage(newBacking);
}
ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
ktx::Header header; ktx::Header header;
@ -442,21 +461,10 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
return ktxBuffer; return ktxBuffer;
} }
TexturePointer Texture::unserialize(const std::string& ktxfile) { TexturePointer Texture::build(const ktx::KTXDescriptor& descriptor) {
std::unique_ptr<ktx::KTX> ktxPointer = ktx::KTX::create(std::make_shared<storage::FileStorage>(ktxfile.c_str()));
if (!ktxPointer) {
return nullptr;
}
ktx::KTXDescriptor descriptor { ktxPointer->toDescriptor() };
return unserialize(ktxfile, ktxPointer->toDescriptor());
}
TexturePointer Texture::unserialize(const std::string& ktxfile, const ktx::KTXDescriptor& descriptor) {
const auto& header = descriptor.header;
Format mipFormat = Format::COLOR_BGRA_32; Format mipFormat = Format::COLOR_BGRA_32;
Format texelFormat = Format::COLOR_SRGBA_32; Format texelFormat = Format::COLOR_SRGBA_32;
const auto& header = descriptor.header;
if (!Texture::evalTextureFormat(header, mipFormat, texelFormat)) { if (!Texture::evalTextureFormat(header, mipFormat, texelFormat)) {
return nullptr; return nullptr;
@ -485,20 +493,19 @@ TexturePointer Texture::unserialize(const std::string& ktxfile, const ktx::KTXDe
} }
auto texture = create(gpuktxKeyValue._usageType, auto texture = create(gpuktxKeyValue._usageType,
type, type,
texelFormat, texelFormat,
header.getPixelWidth(), header.getPixelWidth(),
header.getPixelHeight(), header.getPixelHeight(),
header.getPixelDepth(), header.getPixelDepth(),
1, // num Samples 1, // num Samples
header.getNumberOfSlices(), header.getNumberOfSlices(),
header.getNumberOfLevels(), header.getNumberOfLevels(),
gpuktxKeyValue._samplerDesc); gpuktxKeyValue._samplerDesc);
texture->setUsage(gpuktxKeyValue._usage); texture->setUsage(gpuktxKeyValue._usage);
// Assing the mips availables // Assing the mips availables
texture->setStoredMipFormat(mipFormat); texture->setStoredMipFormat(mipFormat);
texture->setKtxBacking(ktxfile);
IrradianceKTXPayload irradianceKtxKeyValue; IrradianceKTXPayload irradianceKtxKeyValue;
if (IrradianceKTXPayload::findInKeyValues(descriptor.keyValues, irradianceKtxKeyValue)) { if (IrradianceKTXPayload::findInKeyValues(descriptor.keyValues, irradianceKtxKeyValue)) {
@ -508,6 +515,36 @@ TexturePointer Texture::unserialize(const std::string& ktxfile, const ktx::KTXDe
return texture; return texture;
} }
TexturePointer Texture::unserialize(const cache::FilePointer& cacheEntry) {
std::unique_ptr<ktx::KTX> ktxPointer = ktx::KTX::create(std::make_shared<storage::FileStorage>(cacheEntry->getFilepath().c_str()));
if (!ktxPointer) {
return nullptr;
}
auto texture = build(ktxPointer->toDescriptor());
if (texture) {
texture->setKtxBacking(cacheEntry);
}
return texture;
}
TexturePointer Texture::unserialize(const std::string& ktxfile) {
std::unique_ptr<ktx::KTX> ktxPointer = ktx::KTX::create(std::make_shared<storage::FileStorage>(ktxfile.c_str()));
if (!ktxPointer) {
return nullptr;
}
auto texture = build(ktxPointer->toDescriptor());
if (texture) {
texture->setKtxBacking(ktxfile);
}
return texture;
}
bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header) { bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header) {
if (texelFormat == Format::COLOR_RGBA_32 && mipFormat == Format::COLOR_BGRA_32) { if (texelFormat == Format::COLOR_RGBA_32 && mipFormat == Format::COLOR_BGRA_32) {
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::BGRA, ktx::GLInternalFormat::RGBA8, ktx::GLBaseInternalFormat::RGBA); header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::BGRA, ktx::GLInternalFormat::RGBA8, ktx::GLBaseInternalFormat::RGBA);

View file

@ -14,7 +14,7 @@
#include <QUrl> #include <QUrl>
#include <FileCache.h> #include <shared/FileCache.h>
namespace ktx { namespace ktx {
class KTX; class KTX;

View file

@ -702,7 +702,7 @@ void NetworkTexture::handleFinishedInitialLoad() {
if (!texture) { if (!texture) {
KTXFilePointer ktxFile = textureCache->_ktxCache.getFile(hash); KTXFilePointer ktxFile = textureCache->_ktxCache.getFile(hash);
if (ktxFile) { if (ktxFile) {
texture = gpu::Texture::unserialize(ktxFile->getFilepath()); texture = gpu::Texture::unserialize(ktxFile);
if (texture) { if (texture) {
texture = textureCache->cacheTextureByHash(hash, texture); texture = textureCache->cacheTextureByHash(hash, texture);
} }
@ -737,8 +737,8 @@ void NetworkTexture::handleFinishedInitialLoad() {
auto newKtxDescriptor = memKtx->toDescriptor(); auto newKtxDescriptor = memKtx->toDescriptor();
texture = gpu::Texture::unserialize(file->getFilepath(), newKtxDescriptor); texture = gpu::Texture::build(newKtxDescriptor);
texture->setKtxBacking(file->getFilepath()); texture->setKtxBacking(file);
texture->setSource(filename); texture->setSource(filename);
auto& images = originalKtxDescriptor->images; auto& images = originalKtxDescriptor->images;
@ -884,7 +884,7 @@ void ImageReader::read() {
if (!texture) { if (!texture) {
KTXFilePointer ktxFile = textureCache->_ktxCache.getFile(hash); KTXFilePointer ktxFile = textureCache->_ktxCache.getFile(hash);
if (ktxFile) { if (ktxFile) {
texture = gpu::Texture::unserialize(ktxFile->getFilepath()); texture = gpu::Texture::unserialize(ktxFile);
if (texture) { if (texture) {
texture = textureCache->cacheTextureByHash(hash, texture); texture = textureCache->cacheTextureByHash(hash, texture);
} else { } else {
@ -936,7 +936,7 @@ void ImageReader::read() {
if (!file) { if (!file) {
qCWarning(modelnetworking) << _url << "file cache failed"; qCWarning(modelnetworking) << _url << "file cache failed";
} else { } else {
texture->setKtxBacking(file->getFilepath()); texture->setKtxBacking(file);
} }
} else { } else {
qCWarning(modelnetworking) << "Unable to serialize texture to KTX " << _url; qCWarning(modelnetworking) << "Unable to serialize texture to KTX " << _url;

View file

@ -21,8 +21,8 @@
#include <QtCore/QSaveFile> #include <QtCore/QSaveFile>
#include <QtCore/QStorageInfo> #include <QtCore/QStorageInfo>
#include <PathUtils.h> #include "../PathUtils.h"
#include <NumericalConstants.h> #include "../NumericalConstants.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <sys/utime.h> #include <sys/utime.h>
@ -87,6 +87,12 @@ FileCache::~FileCache() {
} }
void FileCache::initialize() { void FileCache::initialize() {
Lock lock(_mutex);
if (_initialized) {
qCWarning(file_cache) << "File cache already initialized";
return;
}
QDir dir(_dirpath.c_str()); QDir dir(_dirpath.c_str());
if (dir.exists()) { if (dir.exists()) {
@ -120,21 +126,31 @@ FilePointer FileCache::addFile(Metadata&& metadata, const std::string& filepath)
file->_cache = this; file->_cache = this;
emit dirty(); emit dirty();
Lock lock(_filesMutex);
_files[file->getKey()] = file; _files[file->getKey()] = file;
} }
return file; return file;
} }
FilePointer FileCache::writeFile(const char* data, File::Metadata&& metadata, bool overwrite) { FilePointer FileCache::writeFile(const char* data, File::Metadata&& metadata, bool overwrite) {
assert(_initialized); FilePointer file;
if (0 == metadata.length) {
qCWarning(file_cache) << "Cannot store empty files in the cache";
return file;
}
Lock lock(_mutex);
if (!_initialized) {
qCWarning(file_cache) << "File cache used before initialization";
return file;
}
std::string filepath = getFilepath(metadata.key); std::string filepath = getFilepath(metadata.key);
Lock lock(_filesMutex);
// if file already exists, return it // if file already exists, return it
FilePointer file = getFile(metadata.key); file = getFile(metadata.key);
if (file) { if (file) {
if (!overwrite) { if (!overwrite) {
qCWarning(file_cache, "[%s] Attempted to overwrite %s", _dirname.c_str(), metadata.key.c_str()); qCWarning(file_cache, "[%s] Attempted to overwrite %s", _dirname.c_str(), metadata.key.c_str());
@ -158,12 +174,15 @@ FilePointer FileCache::writeFile(const char* data, File::Metadata&& metadata, bo
return file; return file;
} }
FilePointer FileCache::getFile(const Key& key) { FilePointer FileCache::getFile(const Key& key) {
assert(_initialized); Lock lock(_mutex);
FilePointer file; FilePointer file;
if (!_initialized) {
Lock lock(_filesMutex); qCWarning(file_cache) << "File cache used before initialization";
return file;
}
// check if file exists // check if file exists
const auto it = _files.find(key); const auto it = _files.find(key);
@ -172,7 +191,10 @@ FilePointer FileCache::getFile(const Key& key) {
if (file) { if (file) {
file->touch(); file->touch();
// if it exists, it is active - remove it from the cache // if it exists, it is active - remove it from the cache
removeUnusedFile(file); if (_unusedFiles.erase(file)) {
_numUnusedFiles -= 1;
_unusedFilesSize -= file->getLength();
}
qCDebug(file_cache, "[%s] Found %s", _dirname.c_str(), key.c_str()); qCDebug(file_cache, "[%s] Found %s", _dirname.c_str(), key.c_str());
emit dirty(); emit dirty();
} else { } else {
@ -188,31 +210,19 @@ std::string FileCache::getFilepath(const Key& key) {
return _dirpath + DIR_SEP + key + EXT_SEP + _ext; return _dirpath + DIR_SEP + key + EXT_SEP + _ext;
} }
// This is a non-public function that uses the mutex because it's
// essentially a public function specifically to a File object
void FileCache::addUnusedFile(const FilePointer& file) { void FileCache::addUnusedFile(const FilePointer& file) {
{ Lock lock(_mutex);
Lock lock(_filesMutex); _files[file->getKey()] = file;
_files[file->getKey()] = file; _unusedFiles.insert(file);
} _numUnusedFiles += 1;
_unusedFilesSize += file->getLength();
{
Lock lock(_unusedFilesMutex);
_unusedFiles.insert(file);
_numUnusedFiles += 1;
_unusedFilesSize += file->getLength();
}
clean(); clean();
emit dirty(); emit dirty();
} }
void FileCache::removeUnusedFile(const FilePointer& file) {
Lock lock(_unusedFilesMutex);
if (_unusedFiles.erase(file)) {
_numUnusedFiles -= 1;
_unusedFilesSize -= file->getLength();
}
}
size_t FileCache::getOverbudgetAmount() const { size_t FileCache::getOverbudgetAmount() const {
size_t result = 0; size_t result = 0;
@ -241,20 +251,13 @@ void FileCache::eject(const FilePointer& file) {
const auto& length = file->getLength(); const auto& length = file->getLength();
const auto& key = file->getKey(); const auto& key = file->getKey();
{ if (0 != _files.erase(key)) {
Lock lock(_filesMutex); _numTotalFiles -= 1;
if (0 != _files.erase(key)) { _totalFilesSize -= length;
_numTotalFiles -= 1;
_totalFilesSize -= length;
}
} }
if (0 != _unusedFiles.erase(file)) {
{ _numUnusedFiles -= 1;
Lock unusedLock(_unusedFilesMutex); _unusedFilesSize -= length;
if (0 != _unusedFiles.erase(file)) {
_numUnusedFiles -= 1;
_unusedFilesSize -= length;
}
} }
} }
@ -266,7 +269,6 @@ void FileCache::clean() {
return; return;
} }
Lock unusedLock(_unusedFilesMutex);
using Queue = std::priority_queue<FilePointer, std::vector<FilePointer>, FilePointerComparator>; using Queue = std::priority_queue<FilePointer, std::vector<FilePointer>, FilePointerComparator>;
Queue queue; Queue queue;
for (const auto& file : _unusedFiles) { for (const auto& file : _unusedFiles) {
@ -283,18 +285,19 @@ void FileCache::clean() {
} }
void FileCache::wipe() { void FileCache::wipe() {
Lock unusedFilesLock(_unusedFilesMutex); Lock lock(_mutex);
while (!_unusedFiles.empty()) { while (!_unusedFiles.empty()) {
eject(*_unusedFiles.begin()); eject(*_unusedFiles.begin());
} }
} }
void FileCache::clear() { void FileCache::clear() {
Lock lock(_mutex);
// Eliminate any overbudget files // Eliminate any overbudget files
clean(); clean();
// Mark everything remaining as persisted // Mark everything remaining as persisted while effectively ejecting from the cache
Lock unusedFilesLock(_unusedFilesMutex);
for (auto& file : _unusedFiles) { for (auto& file : _unusedFiles) {
file->_shouldPersist = true; file->_shouldPersist = true;
file->_cache = nullptr; file->_cache = nullptr;
@ -329,4 +332,4 @@ File::~File() {
void File::touch() { void File::touch() {
utime(_filepath.c_str(), nullptr); utime(_filepath.c_str(), nullptr);
_modified = std::max<int64_t>(QFileInfo(_filepath.c_str()).lastRead().toMSecsSinceEpoch(), _modified); _modified = std::max<int64_t>(QFileInfo(_filepath.c_str()).lastRead().toMSecsSinceEpoch(), _modified);
} }

View file

@ -108,7 +108,6 @@ private:
FilePointer addFile(Metadata&& metadata, const std::string& filepath); FilePointer addFile(Metadata&& metadata, const std::string& filepath);
void addUnusedFile(const FilePointer& file); void addUnusedFile(const FilePointer& file);
void removeUnusedFile(const FilePointer& file);
void clean(); void clean();
void clear(); void clear();
// Remove a file from the cache // Remove a file from the cache
@ -125,16 +124,14 @@ private:
std::atomic<size_t> _totalFilesSize { 0 }; std::atomic<size_t> _totalFilesSize { 0 };
std::atomic<size_t> _unusedFilesSize { 0 }; std::atomic<size_t> _unusedFilesSize { 0 };
std::string _ext; const std::string _ext;
std::string _dirname; const std::string _dirname;
std::string _dirpath; const std::string _dirpath;
bool _initialized { false }; bool _initialized { false };
Mutex _mutex;
Map _files; Map _files;
Mutex _filesMutex;
Set _unusedFiles; Set _unusedFiles;
Mutex _unusedFilesMutex;
}; };
class File : public QObject { class File : public QObject {
@ -146,7 +143,7 @@ public:
const Key& getKey() const { return _key; } const Key& getKey() const { return _key; }
const size_t& getLength() const { return _length; } const size_t& getLength() const { return _length; }
std::string getFilepath() const { return _filepath; } const std::string& getFilepath() const { return _filepath; }
virtual ~File(); virtual ~File();
/// overrides should call File::deleter to maintain caching behavior /// overrides should call File::deleter to maintain caching behavior

View file

@ -144,7 +144,9 @@ function onMessage(message) {
isDomainOpen(Settings.getValue("previousSnapshotDomainID"), function (canShare) { isDomainOpen(Settings.getValue("previousSnapshotDomainID"), function (canShare) {
var isGif = fileExtensionMatches(message.data, "gif"); var isGif = fileExtensionMatches(message.data, "gif");
isLoggedIn = Account.isLoggedIn(); isLoggedIn = Account.isLoggedIn();
isUploadingPrintableStill = canShare && Account.isLoggedIn() && !isGif; if (!isGif) {
isUploadingPrintableStill = canShare && Account.isLoggedIn();
}
if (canShare) { if (canShare) {
if (isLoggedIn) { if (isLoggedIn) {
print('Sharing snapshot with audience "for_url":', message.data); print('Sharing snapshot with audience "for_url":', message.data);

View file

@ -103,7 +103,7 @@ function getControllerLocation(controllerHand) {
const STRING_PULL_SOUND_URL = Script.resolvePath('Bow_draw.1.L.wav'); const STRING_PULL_SOUND_URL = Script.resolvePath('Bow_draw.1.L.wav');
const ARROW_HIT_SOUND_URL = Script.resolvePath('Arrow_impact1.L.wav'); const ARROW_HIT_SOUND_URL = Script.resolvePath('Arrow_impact1.L.wav');
const ARROW_MODEL_URL = Script.resolvePath('arrow.fbx'); const ARROW_MODEL_URL = Script.resolvePath('models/arrow.baked.fbx');
const ARROW_DIMENSIONS = { const ARROW_DIMENSIONS = {
x: 0.20, x: 0.20,
y: 0.19, y: 0.19,

View file

@ -37,7 +37,7 @@ var userData = {
var id = Entities.addEntity({ var id = Entities.addEntity({
"position": MyAvatar.position, "position": MyAvatar.position,
"collisionsWillMove": 1, "collisionsWillMove": 1,
"compoundShapeURL": Script.resolvePath("bow_collision_hull.obj"), "compoundShapeURL": Script.resolvePath("models/bow_collision_hull.obj"),
"created": "2016-09-01T23:57:55Z", "created": "2016-09-01T23:57:55Z",
"dimensions": { "dimensions": {
"x": 0.039999999105930328, "x": 0.039999999105930328,
@ -50,7 +50,7 @@ var id = Entities.addEntity({
"y": -9.8, "y": -9.8,
"z": 0 "z": 0
}, },
"modelURL": Script.resolvePath("bow-deadly.fbx"), "modelURL": Script.resolvePath("models/bow-deadly.baked.fbx"),
"name": "Hifi-Bow", "name": "Hifi-Bow",
"rotation": { "rotation": {
"w": 0.9718012809753418, "w": 0.9718012809753418,

View file

@ -114,7 +114,7 @@ SHORTBOW_ENTITIES =
"id": "{04288f77-64df-4323-ac38-9c1960a393a5}", "id": "{04288f77-64df-4323-ac38-9c1960a393a5}",
"lastEdited": 1487893058314990, "lastEdited": 1487893058314990,
"lastEditedBy": "{fce8028a-4bac-43e8-96ff-4c7286ea4ab3}", "lastEditedBy": "{fce8028a-4bac-43e8-96ff-4c7286ea4ab3}",
"modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-button.fbx", "modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-button.baked.fbx",
"name": "SB.StartButton", "name": "SB.StartButton",
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}", "owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
"parentID": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}", "parentID": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}",
@ -758,7 +758,7 @@ SHORTBOW_ENTITIES =
"id": "{d4c8f577-944d-4d50-ac85-e56387c0ef0a}", "id": "{d4c8f577-944d-4d50-ac85-e56387c0ef0a}",
"lastEdited": 1487892440231278, "lastEdited": 1487892440231278,
"lastEditedBy": "{91f193dd-829a-4b33-ab27-e9a26160634a}", "lastEditedBy": "{91f193dd-829a-4b33-ab27-e9a26160634a}",
"modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-platform.fbx", "modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-platform.baked.fbx",
"name": "SB.Platform", "name": "SB.Platform",
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}", "owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
"parentID": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}", "parentID": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}",
@ -794,7 +794,7 @@ SHORTBOW_ENTITIES =
"id": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}", "id": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}",
"lastEdited": 1487892440231832, "lastEdited": 1487892440231832,
"lastEditedBy": "{91f193dd-829a-4b33-ab27-e9a26160634a}", "lastEditedBy": "{91f193dd-829a-4b33-ab27-e9a26160634a}",
"modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-scoreboard.fbx", "modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-scoreboard.baked.fbx",
"name": "SB.Scoreboard", "name": "SB.Scoreboard",
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}", "owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
"queryAACube": { "queryAACube": {

View file

@ -96,7 +96,7 @@
"id": "{04288f77-64df-4323-ac38-9c1960a393a5}", "id": "{04288f77-64df-4323-ac38-9c1960a393a5}",
"lastEdited": 1487893058314990, "lastEdited": 1487893058314990,
"lastEditedBy": "{fce8028a-4bac-43e8-96ff-4c7286ea4ab3}", "lastEditedBy": "{fce8028a-4bac-43e8-96ff-4c7286ea4ab3}",
"modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-button.fbx", "modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-button.baked.fbx",
"name": "SB.StartButton", "name": "SB.StartButton",
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}", "owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
"parentID": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}", "parentID": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}",
@ -740,7 +740,7 @@
"id": "{d4c8f577-944d-4d50-ac85-e56387c0ef0a}", "id": "{d4c8f577-944d-4d50-ac85-e56387c0ef0a}",
"lastEdited": 1487892440231278, "lastEdited": 1487892440231278,
"lastEditedBy": "{91f193dd-829a-4b33-ab27-e9a26160634a}", "lastEditedBy": "{91f193dd-829a-4b33-ab27-e9a26160634a}",
"modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-platform.fbx", "modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-platform.baked.fbx",
"name": "SB.Platform", "name": "SB.Platform",
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}", "owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
"parentID": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}", "parentID": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}",
@ -776,7 +776,7 @@
"id": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}", "id": "{0cd1f1f7-53b9-4c15-bf25-42c0760d16f0}",
"lastEdited": 1487892440231832, "lastEdited": 1487892440231832,
"lastEditedBy": "{91f193dd-829a-4b33-ab27-e9a26160634a}", "lastEditedBy": "{91f193dd-829a-4b33-ab27-e9a26160634a}",
"modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-scoreboard.fbx", "modelURL": "file:///c:/Users/ryanh/dev/hifi/unpublishedScripts/marketplace/shortbow/models/shortbow-scoreboard.baked.fbx",
"name": "SB.Scoreboard", "name": "SB.Scoreboard",
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}", "owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
"queryAACube": { "queryAACube": {

View file

@ -131,7 +131,7 @@ var baseEnemyProperties = {
}, },
"lifetime": 30, "lifetime": 30,
"id": "{ed8f7339-8bbd-4750-968e-c3ceb9d64721}", "id": "{ed8f7339-8bbd-4750-968e-c3ceb9d64721}",
"modelURL": Script.resolvePath("models/Amber.fbx"), "modelURL": Script.resolvePath("models/Amber.baked.fbx"),
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}", "owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
"queryAACube": { "queryAACube": {
"scale": 1.0999215841293335, "scale": 1.0999215841293335,
@ -290,7 +290,7 @@ ShortbowGameManager.prototype = {
"position": props.position, "position": props.position,
"rotation": props.rotation, "rotation": props.rotation,
"collisionsWillMove": 1, "collisionsWillMove": 1,
"compoundShapeURL": Script.resolvePath("bow/bow_collision_hull.obj"), "compoundShapeURL": Script.resolvePath("bow/models/bow_collision_hull.obj"),
"created": "2016-09-01T23:57:55Z", "created": "2016-09-01T23:57:55Z",
"dimensions": { "dimensions": {
"x": 0.039999999105930328, "x": 0.039999999105930328,
@ -303,7 +303,7 @@ ShortbowGameManager.prototype = {
"y": -9.8, "y": -9.8,
"z": 0 "z": 0
}, },
"modelURL": Script.resolvePath("bow/bow-deadly.fbx"), "modelURL": Script.resolvePath("bow/models/bow-deadly.baked.fbx"),
"name": "WG.Hifi-Bow", "name": "WG.Hifi-Bow",
"script": Script.resolvePath("bow/bow.js"), "script": Script.resolvePath("bow/bow.js"),
"shapeType": "compound", "shapeType": "compound",