mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-11 09:06:59 +02:00
Merge pull request #5276 from Atlante45/clear_cache_and_restart
Reload content menu item
This commit is contained in:
commit
6cd584ddd9
21 changed files with 155 additions and 79 deletions
|
@ -53,7 +53,7 @@ AnimationDetails ScriptableAvatar::getAnimationDetails() {
|
|||
|
||||
void ScriptableAvatar::update(float deltatime) {
|
||||
// Run animation
|
||||
if (_animation != NULL && _animation->isValid() && _animation->getFrames().size() > 0) {
|
||||
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0) {
|
||||
QStringList modelJoints = getJointNames();
|
||||
QStringList animationJoints = _animation->getJointNames();
|
||||
|
||||
|
|
|
@ -702,6 +702,14 @@ void Application::cleanupBeforeQuit() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void Application::emptyLocalCache() {
|
||||
QNetworkDiskCache* cache = qobject_cast<QNetworkDiskCache*>(NetworkAccessManager::getInstance().cache());
|
||||
if (cache) {
|
||||
qDebug() << "DiskCacheEditor::clear(): Clearing disk cache.";
|
||||
cache->clear();
|
||||
}
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
EntityTree* tree = _entities.getTree();
|
||||
tree->lockForWrite();
|
||||
|
@ -2407,6 +2415,15 @@ void Application::cameraMenuChanged() {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::reloadResourceCaches() {
|
||||
emptyLocalCache();
|
||||
|
||||
DependencyManager::get<AnimationCache>()->refreshAll();
|
||||
DependencyManager::get<GeometryCache>()->refreshAll();
|
||||
DependencyManager::get<SoundCache>()->refreshAll();
|
||||
DependencyManager::get<TextureCache>()->refreshAll();
|
||||
}
|
||||
|
||||
void Application::rotationModeChanged() {
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||
_myAvatar->setHeadPitch(0);
|
||||
|
|
|
@ -442,6 +442,8 @@ public slots:
|
|||
void domainConnectionDenied(const QString& reason);
|
||||
|
||||
void cameraMenuChanged();
|
||||
|
||||
void reloadResourceCaches();
|
||||
|
||||
private slots:
|
||||
void clearDomainOctreeDetails();
|
||||
|
@ -487,6 +489,8 @@ private:
|
|||
void init();
|
||||
|
||||
void cleanupBeforeQuit();
|
||||
|
||||
void emptyLocalCache();
|
||||
|
||||
void update(float deltaTime);
|
||||
|
||||
|
|
|
@ -256,6 +256,8 @@ Menu::Menu() {
|
|||
avatar, SLOT(updateMotionBehavior()));
|
||||
|
||||
MenuWrapper* viewMenu = addMenu("View");
|
||||
|
||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches()));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu,
|
||||
MenuOption::Fullscreen,
|
||||
|
|
|
@ -229,6 +229,7 @@ namespace MenuOption {
|
|||
const QString Preferences = "Preferences...";
|
||||
const QString Quit = "Quit";
|
||||
const QString ReloadAllScripts = "Reload All Scripts";
|
||||
const QString ReloadContent = "Reload Content (Clears all caches)";
|
||||
const QString RenderBoundingCollisionShapes = "Show Bounding Collision Shapes";
|
||||
const QString RenderFocusIndicator = "Show Eye Focus";
|
||||
const QString RenderHeadCollisionShapes = "Show Head Collision Shapes";
|
||||
|
|
|
@ -636,7 +636,7 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) {
|
|||
_billboardTexture = DependencyManager::get<TextureCache>()->getTexture(
|
||||
uniqueUrl, DEFAULT_TEXTURE, false, _billboard);
|
||||
}
|
||||
if (!_billboardTexture->isLoaded()) {
|
||||
if (!_billboardTexture || !_billboardTexture->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
// rotate about vertical to face the camera
|
||||
|
|
|
@ -28,12 +28,12 @@ BillboardOverlay::BillboardOverlay(const BillboardOverlay* billboardOverlay) :
|
|||
}
|
||||
|
||||
void BillboardOverlay::render(RenderArgs* args) {
|
||||
if (!_isLoaded) {
|
||||
if (!_texture) {
|
||||
_isLoaded = true;
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(_url);
|
||||
}
|
||||
|
||||
if (!_visible || !_texture->isLoaded()) {
|
||||
if (!_visible || !_texture || !_texture->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ void BillboardOverlay::setBillboardURL(const QString& url) {
|
|||
bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) {
|
||||
|
||||
if (_texture) {
|
||||
if (_texture && _texture->isLoaded()) {
|
||||
glm::quat rotation = getRotation();
|
||||
if (_isFacingAvatar) {
|
||||
// rotate about vertical to face the camera
|
||||
|
|
|
@ -38,10 +38,7 @@ QSharedPointer<Resource> AnimationCache::createResource(const QUrl& url, const Q
|
|||
return QSharedPointer<Resource>(new Animation(url), &Resource::allReferencesCleared);
|
||||
}
|
||||
|
||||
Animation::Animation(const QUrl& url) :
|
||||
Resource(url),
|
||||
_isValid(false) {
|
||||
}
|
||||
Animation::Animation(const QUrl& url) : Resource(url) {}
|
||||
|
||||
class AnimationReader : public QRunnable {
|
||||
public:
|
||||
|
@ -97,7 +94,6 @@ QVector<FBXAnimationFrame> Animation::getFrames() const {
|
|||
void Animation::setGeometry(const FBXGeometry& geometry) {
|
||||
_geometry = geometry;
|
||||
finishedLoading(true);
|
||||
_isValid = true;
|
||||
}
|
||||
|
||||
void Animation::downloadFinished(QNetworkReply* reply) {
|
||||
|
|
|
@ -57,8 +57,6 @@ public:
|
|||
Q_INVOKABLE QStringList getJointNames() const;
|
||||
|
||||
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
|
||||
|
||||
bool isValid() const { return _isValid; }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -69,7 +67,6 @@ protected:
|
|||
private:
|
||||
|
||||
FBXGeometry _geometry;
|
||||
bool _isValid;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ AudioInjector* AudioInjector::playSound(const QString& soundUrl, const float vol
|
|||
if (soundCache.isNull()) {
|
||||
return NULL;
|
||||
}
|
||||
SharedSoundPointer sound = soundCache.data()->getSound(QUrl(soundUrl));
|
||||
SharedSoundPointer sound = soundCache->getSound(QUrl(soundUrl));
|
||||
if (sound.isNull() || !sound->isReady()) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -546,7 +546,7 @@ const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(EntityItemP
|
|||
Model* model = modelEntityItem->getModel(this);
|
||||
if (model) {
|
||||
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = model->getCollisionGeometry();
|
||||
if (!collisionNetworkGeometry.isNull()) {
|
||||
if (collisionNetworkGeometry && collisionNetworkGeometry->isLoaded()) {
|
||||
result = &collisionNetworkGeometry->getFBXGeometry();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -401,8 +401,8 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
|
|||
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
|
||||
const QSharedPointer<NetworkGeometry> renderNetworkGeometry = _model->getGeometry();
|
||||
|
||||
if ((! collisionNetworkGeometry.isNull() && collisionNetworkGeometry->isLoaded()) &&
|
||||
(! renderNetworkGeometry.isNull() && renderNetworkGeometry->isLoaded())) {
|
||||
if ((collisionNetworkGeometry && collisionNetworkGeometry->isLoaded()) &&
|
||||
(renderNetworkGeometry && renderNetworkGeometry->isLoaded())) {
|
||||
// we have both URLs AND both geometries AND they are both fully loaded.
|
||||
return true;
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
|
|||
|
||||
// should never fall in here when collision model not fully loaded
|
||||
// hence we assert collisionNetworkGeometry is not NULL
|
||||
assert(!collisionNetworkGeometry.isNull());
|
||||
assert(collisionNetworkGeometry);
|
||||
|
||||
const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry();
|
||||
const QSharedPointer<NetworkGeometry> renderNetworkGeometry = _model->getGeometry();
|
||||
|
|
|
@ -184,7 +184,7 @@ void ModelEntityItem::cleanupLoadedAnimations() {
|
|||
_loadedAnimations.clear();
|
||||
}
|
||||
|
||||
Animation* ModelEntityItem::getAnimation(const QString& url) {
|
||||
AnimationPointer ModelEntityItem::getAnimation(const QString& url) {
|
||||
AnimationPointer animation;
|
||||
|
||||
// if we don't already have this model then create it and initialize it
|
||||
|
@ -194,7 +194,7 @@ Animation* ModelEntityItem::getAnimation(const QString& url) {
|
|||
} else {
|
||||
animation = _loadedAnimations[url];
|
||||
}
|
||||
return animation.data();
|
||||
return animation;
|
||||
}
|
||||
|
||||
void ModelEntityItem::mapJoints(const QStringList& modelJointNames) {
|
||||
|
@ -203,9 +203,8 @@ void ModelEntityItem::mapJoints(const QStringList& modelJointNames) {
|
|||
return;
|
||||
}
|
||||
|
||||
Animation* myAnimation = getAnimation(_animationURL);
|
||||
|
||||
if (!_jointMappingCompleted) {
|
||||
AnimationPointer myAnimation = getAnimation(_animationURL);
|
||||
if (myAnimation && myAnimation->isLoaded()) {
|
||||
QStringList animationJointNames = myAnimation->getJointNames();
|
||||
|
||||
if (modelJointNames.size() > 0 && animationJointNames.size() > 0) {
|
||||
|
@ -220,8 +219,12 @@ void ModelEntityItem::mapJoints(const QStringList& modelJointNames) {
|
|||
|
||||
QVector<glm::quat> ModelEntityItem::getAnimationFrame() {
|
||||
QVector<glm::quat> frameData;
|
||||
if (hasAnimation() && _jointMappingCompleted) {
|
||||
Animation* myAnimation = getAnimation(_animationURL);
|
||||
if (!hasAnimation() || !_jointMappingCompleted) {
|
||||
return frameData;
|
||||
}
|
||||
|
||||
AnimationPointer myAnimation = getAnimation(_animationURL);
|
||||
if (myAnimation && myAnimation->isLoaded()) {
|
||||
QVector<FBXAnimationFrame> frames = myAnimation->getFrames();
|
||||
int frameCount = frames.size();
|
||||
if (frameCount > 0) {
|
||||
|
|
|
@ -141,7 +141,7 @@ protected:
|
|||
bool _jointMappingCompleted;
|
||||
QVector<int> _jointMapping;
|
||||
|
||||
static Animation* getAnimation(const QString& url);
|
||||
static AnimationPointer getAnimation(const QString& url);
|
||||
static QMap<QString, AnimationPointer> _loadedAnimations;
|
||||
static AnimationCache _animationCache;
|
||||
|
||||
|
|
|
@ -34,13 +34,18 @@ ResourceCache::ResourceCache(QObject* parent) :
|
|||
}
|
||||
|
||||
ResourceCache::~ResourceCache() {
|
||||
// the unused resources may themselves reference resources that will be added to the unused
|
||||
// list on destruction, so keep clearing until there are no references left
|
||||
while (!_unusedResources.isEmpty()) {
|
||||
foreach (const QSharedPointer<Resource>& resource, _unusedResources) {
|
||||
resource->setCache(nullptr);
|
||||
clearUnusedResource();
|
||||
}
|
||||
|
||||
void ResourceCache::refreshAll() {
|
||||
// Clear all unused resources so we don't have to reload them
|
||||
clearUnusedResource();
|
||||
|
||||
// Refresh all remaining resources in use
|
||||
foreach (auto resource, _resources) {
|
||||
if (!resource.isNull()) {
|
||||
resource.data()->refresh();
|
||||
}
|
||||
_unusedResources.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +53,8 @@ void ResourceCache::refresh(const QUrl& url) {
|
|||
QSharedPointer<Resource> resource = _resources.value(url);
|
||||
if (!resource.isNull()) {
|
||||
resource->refresh();
|
||||
} else {
|
||||
_resources.remove(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,6 +141,17 @@ void ResourceCache::reserveUnusedResource(qint64 resourceSize) {
|
|||
}
|
||||
}
|
||||
|
||||
void ResourceCache::clearUnusedResource() {
|
||||
// the unused resources may themselves reference resources that will be added to the unused
|
||||
// list on destruction, so keep clearing until there are no references left
|
||||
while (!_unusedResources.isEmpty()) {
|
||||
foreach (const QSharedPointer<Resource>& resource, _unusedResources) {
|
||||
resource->setCache(nullptr);
|
||||
}
|
||||
_unusedResources.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceCache::attemptRequest(Resource* resource) {
|
||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||
if (_requestLimit <= 0) {
|
||||
|
@ -253,19 +271,20 @@ void Resource::refresh() {
|
|||
_replyTimer->deleteLater();
|
||||
_replyTimer = nullptr;
|
||||
}
|
||||
|
||||
init();
|
||||
_request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
|
||||
if (!_startedLoading) {
|
||||
attemptRequest();
|
||||
}
|
||||
ensureLoading();
|
||||
emit onRefresh();
|
||||
}
|
||||
|
||||
void Resource::allReferencesCleared() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "allReferencesCleared");
|
||||
return;
|
||||
}
|
||||
if (_cache) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "allReferencesCleared");
|
||||
return;
|
||||
}
|
||||
|
||||
// create and reinsert new shared pointer
|
||||
QSharedPointer<Resource> self(this, &Resource::allReferencesCleared);
|
||||
setSelf(self);
|
||||
|
@ -312,8 +331,7 @@ void Resource::reinsert() {
|
|||
_cache->_resources.insert(_url, _self);
|
||||
}
|
||||
|
||||
const int REPLY_TIMEOUT_MS = 5000;
|
||||
|
||||
static const int REPLY_TIMEOUT_MS = 5000;
|
||||
void Resource::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
if (!_reply->isFinished()) {
|
||||
_bytesReceived = bytesReceived;
|
||||
|
|
|
@ -51,7 +51,7 @@ static const qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES;
|
|||
class ResourceCacheSharedItems : public Dependency {
|
||||
SINGLETON_DEPENDENCY
|
||||
public:
|
||||
QList<QPointer<Resource> > _pendingRequests;
|
||||
QList<QPointer<Resource>> _pendingRequests;
|
||||
QList<Resource*> _loadingRequests;
|
||||
private:
|
||||
ResourceCacheSharedItems() { }
|
||||
|
@ -78,17 +78,14 @@ public:
|
|||
|
||||
ResourceCache(QObject* parent = NULL);
|
||||
virtual ~ResourceCache();
|
||||
|
||||
|
||||
void refreshAll();
|
||||
void refresh(const QUrl& url);
|
||||
|
||||
public slots:
|
||||
void checkAsynchronousGets();
|
||||
|
||||
protected:
|
||||
qint64 _unusedResourcesMaxSize = DEFAULT_UNUSED_MAX_SIZE;
|
||||
qint64 _unusedResourcesSize = 0;
|
||||
QMap<int, QSharedPointer<Resource> > _unusedResources;
|
||||
|
||||
/// Loads a resource from the specified URL.
|
||||
/// \param fallback a fallback URL to load if the desired one is unavailable
|
||||
/// \param delayLoad if true, don't load the resource immediately; wait until load is first requested
|
||||
|
@ -103,6 +100,7 @@ protected:
|
|||
void addUnusedResource(const QSharedPointer<Resource>& resource);
|
||||
void removeUnusedResource(const QSharedPointer<Resource>& resource);
|
||||
void reserveUnusedResource(qint64 resourceSize);
|
||||
void clearUnusedResource();
|
||||
|
||||
static void attemptRequest(Resource* resource);
|
||||
static void requestCompleted(Resource* resource);
|
||||
|
@ -110,7 +108,7 @@ protected:
|
|||
private:
|
||||
friend class Resource;
|
||||
|
||||
QHash<QUrl, QWeakPointer<Resource> > _resources;
|
||||
QHash<QUrl, QWeakPointer<Resource>> _resources;
|
||||
int _lastLRUKey = 0;
|
||||
|
||||
static int _requestLimit;
|
||||
|
@ -118,7 +116,10 @@ private:
|
|||
void getResourceAsynchronously(const QUrl& url);
|
||||
QReadWriteLock _resourcesToBeGottenLock;
|
||||
QQueue<QUrl> _resourcesToBeGotten;
|
||||
|
||||
|
||||
qint64 _unusedResourcesMaxSize = DEFAULT_UNUSED_MAX_SIZE;
|
||||
qint64 _unusedResourcesSize = 0;
|
||||
QMap<int, QSharedPointer<Resource>> _unusedResources;
|
||||
};
|
||||
|
||||
/// Base class for resources.
|
||||
|
@ -172,12 +173,11 @@ public:
|
|||
const QUrl& getURL() const { return _url; }
|
||||
|
||||
signals:
|
||||
|
||||
/// Fired when the resource has been loaded.
|
||||
void loaded();
|
||||
void onRefresh();
|
||||
|
||||
protected slots:
|
||||
|
||||
void attemptRequest();
|
||||
|
||||
/// Refreshes the resource if the last modified date on the network
|
||||
|
@ -185,7 +185,6 @@ protected slots:
|
|||
void maybeRefresh();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void init();
|
||||
|
||||
/// Called when the download has finished. The recipient should delete the reply when done with it.
|
||||
|
@ -207,14 +206,12 @@ protected:
|
|||
QPointer<ResourceCache> _cache;
|
||||
|
||||
private slots:
|
||||
|
||||
void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void handleReplyError();
|
||||
void handleReplyFinished();
|
||||
void handleReplyTimeout();
|
||||
|
||||
private:
|
||||
|
||||
void setLRUKey(int lruKey) { _lruKey = lruKey; }
|
||||
|
||||
void makeRequest();
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
void AnimationHandle::setURL(const QUrl& url) {
|
||||
if (_url != url) {
|
||||
_animation = DependencyManager::get<AnimationCache>()->getAnimation(_url = url);
|
||||
QObject::connect(_animation.data(), &Resource::onRefresh, this, &AnimationHandle::clearJoints);
|
||||
_jointMappings.clear();
|
||||
}
|
||||
}
|
||||
|
@ -110,11 +111,15 @@ void AnimationHandle::setAnimationDetails(const AnimationDetails& details) {
|
|||
|
||||
|
||||
void AnimationHandle::simulate(float deltaTime) {
|
||||
if (!_animation || !_animation->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_animationLoop.simulate(deltaTime);
|
||||
|
||||
// update the joint mappings if necessary/possible
|
||||
if (_jointMappings.isEmpty()) {
|
||||
if (_model->isActive()) {
|
||||
if (_model && _model->isActive()) {
|
||||
_jointMappings = _model->getGeometry()->getJointMappings(_animation);
|
||||
}
|
||||
if (_jointMappings.isEmpty()) {
|
||||
|
@ -146,6 +151,10 @@ void AnimationHandle::simulate(float deltaTime) {
|
|||
}
|
||||
|
||||
void AnimationHandle::applyFrame(float frameIndex) {
|
||||
if (!_animation || !_animation->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const FBXGeometry& animationGeometry = _animation->getGeometry();
|
||||
int frameCount = animationGeometry.animationFrames.size();
|
||||
const FBXAnimationFrame& floorFrame = animationGeometry.animationFrames.at((int)glm::floor(frameIndex) % frameCount);
|
||||
|
|
|
@ -94,6 +94,8 @@ private:
|
|||
void replaceMatchingPriorities(float newPriority);
|
||||
void restoreJoints();
|
||||
|
||||
void clearJoints() { _jointMappings.clear(); }
|
||||
|
||||
Model* _model;
|
||||
WeakAnimationHandlePointer _self;
|
||||
AnimationPointer _animation;
|
||||
|
|
|
@ -1942,7 +1942,7 @@ QSharedPointer<NetworkGeometry> NetworkGeometry::getLODOrFallback(float distance
|
|||
}
|
||||
}
|
||||
}
|
||||
if (lod->isLoaded()) {
|
||||
if (lod && lod->isLoaded()) {
|
||||
hysteresis = lodDistance;
|
||||
return lod;
|
||||
}
|
||||
|
@ -2061,21 +2061,16 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u
|
|||
|
||||
QSharedPointer<NetworkTexture> matchingTexture = QSharedPointer<NetworkTexture>();
|
||||
if (part.diffuseTextureName == name) {
|
||||
part.diffuseTexture =
|
||||
textureCache->getTexture(url, DEFAULT_TEXTURE,
|
||||
_geometry.meshes[i].isEye, QByteArray());
|
||||
part.diffuseTexture = textureCache->getTexture(url, DEFAULT_TEXTURE, _geometry.meshes[i].isEye);
|
||||
part.diffuseTexture->setLoadPriorities(_loadPriorities);
|
||||
} else if (part.normalTextureName == name) {
|
||||
part.normalTexture = textureCache->getTexture(url, DEFAULT_TEXTURE,
|
||||
false, QByteArray());
|
||||
part.normalTexture = textureCache->getTexture(url);
|
||||
part.normalTexture->setLoadPriorities(_loadPriorities);
|
||||
} else if (part.specularTextureName == name) {
|
||||
part.specularTexture = textureCache->getTexture(url, DEFAULT_TEXTURE,
|
||||
false, QByteArray());
|
||||
part.specularTexture = textureCache->getTexture(url);
|
||||
part.specularTexture->setLoadPriorities(_loadPriorities);
|
||||
} else if (part.emissiveTextureName == name) {
|
||||
part.emissiveTexture = textureCache->getTexture(url, DEFAULT_TEXTURE,
|
||||
false, QByteArray());
|
||||
part.emissiveTexture = textureCache->getTexture(url);
|
||||
part.emissiveTexture->setLoadPriorities(_loadPriorities);
|
||||
}
|
||||
}
|
||||
|
@ -2095,22 +2090,22 @@ QStringList NetworkGeometry::getTextureNames() const {
|
|||
for (int j = 0; j < mesh.parts.size(); j++) {
|
||||
const NetworkMeshPart& part = mesh.parts[j];
|
||||
|
||||
if (!part.diffuseTextureName.isEmpty()) {
|
||||
if (!part.diffuseTextureName.isEmpty() && part.diffuseTexture) {
|
||||
QString textureURL = part.diffuseTexture->getURL().toString();
|
||||
result << part.diffuseTextureName + ":" + textureURL;
|
||||
}
|
||||
|
||||
if (!part.normalTextureName.isEmpty()) {
|
||||
if (!part.normalTextureName.isEmpty() && part.normalTexture) {
|
||||
QString textureURL = part.normalTexture->getURL().toString();
|
||||
result << part.normalTextureName + ":" + textureURL;
|
||||
}
|
||||
|
||||
if (!part.specularTextureName.isEmpty()) {
|
||||
if (!part.specularTextureName.isEmpty() && part.specularTexture) {
|
||||
QString textureURL = part.specularTexture->getURL().toString();
|
||||
result << part.specularTextureName + ":" + textureURL;
|
||||
}
|
||||
|
||||
if (!part.emissiveTextureName.isEmpty()) {
|
||||
if (!part.emissiveTextureName.isEmpty() && part.emissiveTexture) {
|
||||
QString textureURL = part.emissiveTexture->getURL().toString();
|
||||
result << part.emissiveTextureName + ":" + textureURL;
|
||||
}
|
||||
|
|
|
@ -457,7 +457,8 @@ bool Model::updateGeometry() {
|
|||
}
|
||||
deleteGeometry();
|
||||
_dilatedTextures.clear();
|
||||
_geometry = geometry;
|
||||
setGeometry(geometry);
|
||||
|
||||
_meshGroupsKnown = false;
|
||||
_readyWhenAdded = false; // in case any of our users are using scenes
|
||||
invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid
|
||||
|
@ -1142,13 +1143,32 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo
|
|||
onInvalidate();
|
||||
|
||||
// if so instructed, keep the current geometry until the new one is loaded
|
||||
_nextBaseGeometry = _nextGeometry = DependencyManager::get<GeometryCache>()->getGeometry(url, fallback, delayLoad);
|
||||
_nextGeometry = DependencyManager::get<GeometryCache>()->getGeometry(url, fallback, delayLoad);
|
||||
_nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS;
|
||||
if (!retainCurrent || !isActive() || (_nextGeometry && _nextGeometry->isLoaded())) {
|
||||
applyNextGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
void Model::geometryRefreshed() {
|
||||
QObject* sender = QObject::sender();
|
||||
|
||||
if (sender == _geometry) {
|
||||
_readyWhenAdded = false; // reset out render items.
|
||||
_needsReload = true;
|
||||
invalidCalculatedMeshBoxes();
|
||||
|
||||
onInvalidate();
|
||||
|
||||
// if so instructed, keep the current geometry until the new one is loaded
|
||||
_nextGeometry = DependencyManager::get<GeometryCache>()->getGeometry(_url);
|
||||
_nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS;
|
||||
applyNextGeometry();
|
||||
} else {
|
||||
sender->disconnect(this, SLOT(geometryRefreshed()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const QSharedPointer<NetworkGeometry> Model::getCollisionGeometry(bool delayLoad)
|
||||
{
|
||||
|
@ -1156,7 +1176,11 @@ const QSharedPointer<NetworkGeometry> Model::getCollisionGeometry(bool delayLoad
|
|||
_collisionGeometry = DependencyManager::get<GeometryCache>()->getGeometry(_collisionUrl, QUrl(), delayLoad);
|
||||
}
|
||||
|
||||
return _collisionGeometry;
|
||||
if (_collisionGeometry && _collisionGeometry->isLoaded()) {
|
||||
return _collisionGeometry;
|
||||
}
|
||||
|
||||
return QSharedPointer<NetworkGeometry>();
|
||||
}
|
||||
|
||||
void Model::setCollisionModelURL(const QUrl& url) {
|
||||
|
@ -1776,6 +1800,18 @@ void Model::setBlendedVertices(int blendNumber, const QWeakPointer<NetworkGeomet
|
|||
}
|
||||
}
|
||||
|
||||
void Model::setGeometry(const QSharedPointer<NetworkGeometry>& newGeometry) {
|
||||
if (_geometry == newGeometry) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_geometry) {
|
||||
_geometry->disconnect(_geometry.data(), &Resource::onRefresh, this, &Model::geometryRefreshed);
|
||||
}
|
||||
_geometry = newGeometry;
|
||||
QObject::connect(_geometry.data(), &Resource::onRefresh, this, &Model::geometryRefreshed);
|
||||
}
|
||||
|
||||
void Model::applyNextGeometry() {
|
||||
// delete our local geometry and custom textures
|
||||
deleteGeometry();
|
||||
|
@ -1783,13 +1819,12 @@ void Model::applyNextGeometry() {
|
|||
_lodHysteresis = _nextLODHysteresis;
|
||||
|
||||
// we retain a reference to the base geometry so that its reference count doesn't fall to zero
|
||||
_baseGeometry = _nextBaseGeometry;
|
||||
_geometry = _nextGeometry;
|
||||
setGeometry(_nextGeometry);
|
||||
|
||||
_meshGroupsKnown = false;
|
||||
_readyWhenAdded = false; // in case any of our users are using scenes
|
||||
_needsReload = false; // we are loaded now!
|
||||
invalidCalculatedMeshBoxes();
|
||||
_nextBaseGeometry.reset();
|
||||
_nextGeometry.reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -246,6 +246,7 @@ public:
|
|||
|
||||
protected:
|
||||
QSharedPointer<NetworkGeometry> _geometry;
|
||||
void setGeometry(const QSharedPointer<NetworkGeometry>& newGeometry);
|
||||
|
||||
glm::vec3 _scale;
|
||||
glm::vec3 _offset;
|
||||
|
@ -322,6 +323,9 @@ protected:
|
|||
// hook for derived classes to be notified when setUrl invalidates the current model.
|
||||
virtual void onInvalidate() {};
|
||||
|
||||
protected slots:
|
||||
void geometryRefreshed();
|
||||
|
||||
private:
|
||||
|
||||
friend class AnimationHandle;
|
||||
|
@ -331,15 +335,12 @@ private:
|
|||
QVector<JointState> createJointStates(const FBXGeometry& geometry);
|
||||
void initJointTransforms();
|
||||
|
||||
QSharedPointer<NetworkGeometry> _baseGeometry; ///< reference required to prevent collection of base
|
||||
QSharedPointer<NetworkGeometry> _nextBaseGeometry;
|
||||
QSharedPointer<NetworkGeometry> _nextGeometry;
|
||||
float _lodDistance;
|
||||
float _lodHysteresis;
|
||||
float _nextLODHysteresis;
|
||||
|
||||
QSharedPointer<NetworkGeometry> _collisionGeometry;
|
||||
QSharedPointer<NetworkGeometry> _saveNonCollisionGeometry;
|
||||
|
||||
float _pupilDilation;
|
||||
QVector<float> _blendshapeCoefficients;
|
||||
|
@ -525,7 +526,6 @@ private:
|
|||
QMap<render::ItemID, render::PayloadPointer> _renderItems;
|
||||
bool _readyWhenAdded = false;
|
||||
bool _needsReload = true;
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QPointer<Model>)
|
||||
|
|
Loading…
Reference in a new issue