Merge pull request #6612 from sethalves/no-physics-until-ready

No physics until ready
This commit is contained in:
Howard Stearns 2015-12-10 16:09:49 -08:00
commit 585911fe98
12 changed files with 122 additions and 56 deletions

View file

@ -352,6 +352,7 @@ bool setupEssentials(int& argc, char** argv) {
DependencyManager::set<UserInputMapper>(); DependencyManager::set<UserInputMapper>();
DependencyManager::set<controller::ScriptingInterface, ControllerScriptingInterface>(); DependencyManager::set<controller::ScriptingInterface, ControllerScriptingInterface>();
DependencyManager::set<InterfaceParentFinder>(); DependencyManager::set<InterfaceParentFinder>();
DependencyManager::set<EntityTreeRenderer>(true, qApp, qApp);
return true; return true;
} }
@ -371,7 +372,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
_frameCount(0), _frameCount(0),
_fps(60.0f), _fps(60.0f),
_physicsEngine(new PhysicsEngine(Vectors::ZERO)), _physicsEngine(new PhysicsEngine(Vectors::ZERO)),
_entities(true, this, this),
_entityClipboardRenderer(false, this, this), _entityClipboardRenderer(false, this, this),
_entityClipboard(new EntityTree()), _entityClipboard(new EntityTree()),
_lastQueriedTime(usecTimestampNow()), _lastQueriedTime(usecTimestampNow()),
@ -864,7 +864,7 @@ void Application::cleanupBeforeQuit() {
} }
_keyboardFocusHighlight = nullptr; _keyboardFocusHighlight = nullptr;
_entities.clear(); // this will allow entity scripts to properly shutdown getEntities()->clear(); // this will allow entity scripts to properly shutdown
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
@ -875,7 +875,7 @@ void Application::cleanupBeforeQuit() {
// tell the packet receiver we're shutting down, so it can drop packets // tell the packet receiver we're shutting down, so it can drop packets
nodeList->getPacketReceiver().setShouldDropPackets(true); nodeList->getPacketReceiver().setShouldDropPackets(true);
_entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts
ScriptEngine::stopAllScripts(this); // stop all currently running global scripts ScriptEngine::stopAllScripts(this); // stop all currently running global scripts
// first stop all timers directly or by invokeMethod // first stop all timers directly or by invokeMethod
@ -921,7 +921,7 @@ void Application::emptyLocalCache() {
} }
Application::~Application() { Application::~Application() {
EntityTreePointer tree = _entities.getTree(); EntityTreePointer tree = getEntities()->getTree();
tree->setSimulation(NULL); tree->setSimulation(NULL);
_octreeProcessor.terminate(); _octreeProcessor.terminate();
@ -1976,7 +1976,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
event->buttons(), event->modifiers()); event->buttons(), event->modifiers());
_entities.mouseMoveEvent(&mappedEvent, deviceID); getEntities()->mouseMoveEvent(&mappedEvent, deviceID);
_controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts
// if one of our scripts have asked to capture this event, then stop processing it // if one of our scripts have asked to capture this event, then stop processing it
@ -2002,7 +2002,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
event->buttons(), event->modifiers()); event->buttons(), event->modifiers());
if (!_aboutToQuit) { if (!_aboutToQuit) {
_entities.mousePressEvent(&mappedEvent, deviceID); getEntities()->mousePressEvent(&mappedEvent, deviceID);
} }
_controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
@ -2047,7 +2047,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
event->buttons(), event->modifiers()); event->buttons(), event->modifiers());
if (!_aboutToQuit) { if (!_aboutToQuit) {
_entities.mouseReleaseEvent(&mappedEvent, deviceID); getEntities()->mouseReleaseEvent(&mappedEvent, deviceID);
} }
_controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
@ -2370,7 +2370,7 @@ void Application::calibrateEyeTracker5Points() {
bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) { bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
QVector<EntityItemPointer> entities; QVector<EntityItemPointer> entities;
auto entityTree = _entities.getTree(); auto entityTree = getEntities()->getTree();
auto exportTree = std::make_shared<EntityTree>(); auto exportTree = std::make_shared<EntityTree>();
exportTree->createRootElement(); exportTree->createRootElement();
@ -2414,7 +2414,7 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) { bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) {
QVector<EntityItemPointer> entities; QVector<EntityItemPointer> entities;
_entities.getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities); getEntities()->getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities);
if (entities.size() > 0) { if (entities.size() > 0) {
glm::vec3 root(x, y, z); glm::vec3 root(x, y, z);
@ -2482,7 +2482,7 @@ bool Application::importEntities(const QString& urlOrFilename) {
} }
QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) { QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) {
return _entityClipboard->sendEntities(&_entityEditSender, _entities.getTree(), x, y, z); return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), x, y, z);
} }
void Application::initDisplay() { void Application::initDisplay() {
@ -2521,13 +2521,13 @@ void Application::init() {
// fire off an immediate domain-server check in now that settings are loaded // fire off an immediate domain-server check in now that settings are loaded
DependencyManager::get<NodeList>()->sendDomainServerCheckIn(); DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
_entities.init(); getEntities()->init();
_entities.setViewFrustum(getViewFrustum()); getEntities()->setViewFrustum(getViewFrustum());
ObjectMotionState::setShapeManager(&_shapeManager); ObjectMotionState::setShapeManager(&_shapeManager);
_physicsEngine->init(); _physicsEngine->init();
EntityTreePointer tree = _entities.getTree(); EntityTreePointer tree = getEntities()->getTree();
_entitySimulation.init(tree, _physicsEngine, &_entityEditSender); _entitySimulation.init(tree, _physicsEngine, &_entityEditSender);
tree->setSimulation(&_entitySimulation); tree->setSimulation(&_entitySimulation);
@ -2535,11 +2535,11 @@ void Application::init() {
// connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts // connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts
connect(&_entitySimulation, &EntitySimulation::entityCollisionWithEntity, connect(&_entitySimulation, &EntitySimulation::entityCollisionWithEntity,
&_entities, &EntityTreeRenderer::entityCollisionWithEntity); getEntities(), &EntityTreeRenderer::entityCollisionWithEntity);
// connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing // connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing
// of events related clicking, hovering over, and entering entities // of events related clicking, hovering over, and entering entities
_entities.connectSignalsToSlots(entityScriptingInterface.data()); getEntities()->connectSignalsToSlots(entityScriptingInterface.data());
_entityClipboardRenderer.init(); _entityClipboardRenderer.init();
_entityClipboardRenderer.setViewFrustum(getViewFrustum()); _entityClipboardRenderer.setViewFrustum(getViewFrustum());
@ -2888,19 +2888,19 @@ void Application::update(float deltaTime) {
_avatarUpdate->synchronousProcess(); _avatarUpdate->synchronousProcess();
if (true || _physicsEnabled) { if (_physicsEnabled) {
PerformanceTimer perfTimer("physics"); PerformanceTimer perfTimer("physics");
static VectorOfMotionStates motionStates; static VectorOfMotionStates motionStates;
_entitySimulation.getObjectsToDelete(motionStates); _entitySimulation.getObjectsToDelete(motionStates);
_physicsEngine->deleteObjects(motionStates); _physicsEngine->deleteObjects(motionStates);
_entities.getTree()->withWriteLock([&] { getEntities()->getTree()->withWriteLock([&] {
_entitySimulation.getObjectsToAdd(motionStates); _entitySimulation.getObjectsToAdd(motionStates);
_physicsEngine->addObjects(motionStates); _physicsEngine->addObjects(motionStates);
}); });
_entities.getTree()->withWriteLock([&] { getEntities()->getTree()->withWriteLock([&] {
_entitySimulation.getObjectsToChange(motionStates); _entitySimulation.getObjectsToChange(motionStates);
VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates); VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates);
_entitySimulation.setObjectsToChange(stillNeedChange); _entitySimulation.setObjectsToChange(stillNeedChange);
@ -2918,12 +2918,12 @@ void Application::update(float deltaTime) {
myAvatar->prepareForPhysicsSimulation(); myAvatar->prepareForPhysicsSimulation();
_entities.getTree()->withWriteLock([&] { getEntities()->getTree()->withWriteLock([&] {
_physicsEngine->stepSimulation(); _physicsEngine->stepSimulation();
}); });
if (_physicsEngine->hasOutgoingChanges()) { if (_physicsEngine->hasOutgoingChanges()) {
_entities.getTree()->withWriteLock([&] { getEntities()->getTree()->withWriteLock([&] {
_entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID()); _entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID());
avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges()); avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges());
}); });
@ -2938,9 +2938,9 @@ void Application::update(float deltaTime) {
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
// deadlock.) // deadlock.)
_entitySimulation.handleCollisionEvents(collisionEvents); _entitySimulation.handleCollisionEvents(collisionEvents);
// NOTE: the _entities.update() call below will wait for lock // NOTE: the getEntities()->update() call below will wait for lock
// and will simulate entity motion (the EntityTree has been given an EntitySimulation). // and will simulate entity motion (the EntityTree has been given an EntitySimulation).
_entities.update(); // update the models... getEntities()->update(); // update the models...
} }
myAvatar->harvestResultsFromPhysicsSimulation(); myAvatar->harvestResultsFromPhysicsSimulation();
@ -3764,7 +3764,7 @@ void Application::clearDomainOctreeDetails() {
}); });
// reset the model renderer // reset the model renderer
_entities.clear(); getEntities()->clear();
} }
void Application::domainChanged(const QString& domainHostname) { void Application::domainChanged(const QString& domainHostname) {
@ -3886,7 +3886,7 @@ bool Application::nearbyEntitiesAreReadyForPhysics() {
// Someone logs in close to the table. They receive information about the items on the table before they // Someone logs in close to the table. They receive information about the items on the table before they
// receive information about the table. The items are very close to the avatar's capsule, so they become // receive information about the table. The items are very close to the avatar's capsule, so they become
// activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet. // activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet.
EntityTreePointer entityTree = _entities.getTree(); EntityTreePointer entityTree = getEntities()->getTree();
if (!entityTree) { if (!entityTree) {
return false; return false;
} }
@ -3899,6 +3899,9 @@ bool Application::nearbyEntitiesAreReadyForPhysics() {
foreach (EntityItemPointer entity, entities) { foreach (EntityItemPointer entity, entities) {
if (!entity->isReadyToComputeShape()) { if (!entity->isReadyToComputeShape()) {
static QString repeatedMessage =
LogHandler::getInstance().addRepeatedMessageRegex("Physics disabled until entity loads: .*");
qCDebug(interfaceapp) << "Physics disabled until entity loads: " << entity->getID() << entity->getName();
return false; return false;
} }
} }
@ -3950,11 +3953,21 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer
}); });
}); });
if (!_physicsEnabled && nearbyEntitiesAreReadyForPhysics()) { if (!_physicsEnabled) {
// These stats packets are sent in between full sends of a scene. if (nearbyEntitiesAreReadyForPhysics()) {
// We keep physics disabled until we've recieved a full scene and everything near the avatar in that // These stats packets are sent in between full sends of a scene.
// scene is ready to compute its collision shape. // We keep physics disabled until we've recieved a full scene and everything near the avatar in that
_physicsEnabled = true; // scene is ready to compute its collision shape.
_physicsEnabled = true;
getMyAvatar()->updateMotionBehaviorFromMenu();
} else {
auto characterController = getMyAvatar()->getCharacterController();
if (characterController) {
// if we have a character controller, disable it here so the avatar doesn't get stuck due to
// a non-loading collision hull.
characterController->setEnabled(false);
}
}
} }
return statsMessageLength; return statsMessageLength;
@ -4017,7 +4030,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
// we can use the same ones from the application. // we can use the same ones from the application.
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
entityScriptingInterface->setPacketSender(&_entityEditSender); entityScriptingInterface->setPacketSender(&_entityEditSender);
entityScriptingInterface->setEntityTree(_entities.getTree()); entityScriptingInterface->setEntityTree(getEntities()->getTree());
// AvatarManager has some custom types // AvatarManager has some custom types
AvatarManager::registerMetaTypes(scriptEngine); AvatarManager::registerMetaTypes(scriptEngine);

View file

@ -136,7 +136,7 @@ public:
const ViewFrustum* getDisplayViewFrustum() const; const ViewFrustum* getDisplayViewFrustum() const;
ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; }
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
EntityTreeRenderer* getEntities() { return &_entities; } EntityTreeRenderer* getEntities() { return DependencyManager::get<EntityTreeRenderer>().data(); }
QUndoStack* getUndoStack() { return &_undoStack; } QUndoStack* getUndoStack() { return &_undoStack; }
MainWindow* getWindow() { return _window; } MainWindow* getWindow() { return _window; }
EntityTreePointer getEntityClipboard() { return _entityClipboard; } EntityTreePointer getEntityClipboard() { return _entityClipboard; }
@ -444,7 +444,6 @@ private:
PhysicalEntitySimulation _entitySimulation; PhysicalEntitySimulation _entitySimulation;
PhysicsEnginePointer _physicsEngine; PhysicsEnginePointer _physicsEngine;
EntityTreeRenderer _entities;
EntityTreeRenderer _entityClipboardRenderer; EntityTreeRenderer _entityClipboardRenderer;
EntityTreePointer _entityClipboard; EntityTreePointer _entityClipboard;

View file

@ -95,7 +95,6 @@ int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const {
result = MSECS_PER_SECOND / THROTTLED_FRAMERATE; result = MSECS_PER_SECOND / THROTTLED_FRAMERATE;
} }
qDebug() << "New interval " << result;
return result; return result;
} }
@ -138,7 +137,6 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() {
} }
int newInterval = getDesiredInterval(); int newInterval = getDesiredInterval();
qDebug() << newInterval;
_timer.start(newInterval); _timer.start(newInterval);
} }

View file

@ -30,7 +30,7 @@ class ZoneEntityItem;
// Generic client side Octree renderer class. // Generic client side Octree renderer class.
class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService { class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency {
Q_OBJECT Q_OBJECT
public: public:
EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,

View file

@ -12,12 +12,14 @@
#include <glm/gtx/quaternion.hpp> #include <glm/gtx/quaternion.hpp>
#include <QJsonDocument> #include <QJsonDocument>
#include <QtCore/QThread>
#include <AbstractViewStateInterface.h> #include <AbstractViewStateInterface.h>
#include <DeferredLightingEffect.h> #include <DeferredLightingEffect.h>
#include <Model.h> #include <Model.h>
#include <PerfStat.h> #include <PerfStat.h>
#include <render/Scene.h> #include <render/Scene.h>
#include <DependencyManager.h>
#include "EntityTreeRenderer.h" #include "EntityTreeRenderer.h"
#include "EntitiesRendererLogging.h" #include "EntitiesRendererLogging.h"
@ -44,6 +46,32 @@ RenderableModelEntityItem::~RenderableModelEntityItem() {
} }
} }
void RenderableModelEntityItem::setModelURL(const QString& url) {
auto& currentURL = getParsedModelURL();
ModelEntityItem::setModelURL(url);
if (currentURL != getParsedModelURL() || !_model) {
EntityTreePointer tree = getTree();
if (tree) {
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
}
}
}
void RenderableModelEntityItem::loader() {
_needsModelReload = true;
EntityTreeRenderer* renderer = DependencyManager::get<EntityTreeRenderer>().data();
assert(renderer);
if (!_model || _needsModelReload) {
PerformanceTimer perfTimer("getModel");
getModel(renderer);
}
if (_model) {
_model->setURL(getParsedModelURL());
_model->setCollisionModelURL(QUrl(getCompoundShapeURL()));
}
}
void RenderableModelEntityItem::setDimensions(const glm::vec3& value) { void RenderableModelEntityItem::setDimensions(const glm::vec3& value) {
_dimensionsInitialized = true; _dimensionsInitialized = true;
ModelEntityItem::setDimensions(value); ModelEntityItem::setDimensions(value);
@ -223,7 +251,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
// check if the URL has changed // check if the URL has changed
auto& currentURL = getParsedModelURL(); auto& currentURL = getParsedModelURL();
if (currentURL != _model->getURL()) { if (currentURL != _model->getURL()) {
qDebug().noquote() << "Updating model URL: " << currentURL.toDisplayString(); qCDebug(entitiesrenderer).noquote() << "Updating model URL: " << currentURL.toDisplayString();
_model->setURL(currentURL); _model->setURL(currentURL);
} }
@ -318,7 +346,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
Model* result = NULL; Model* result = NULL;
if (!renderer) { if (!renderer) {
return result; return result;
} }
@ -340,7 +368,8 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
// if we have a previously allocated model, but its URL doesn't match // if we have a previously allocated model, but its URL doesn't match
// then we need to let our renderer update our model for us. // then we need to let our renderer update our model for us.
if (_model && QUrl(getModelURL()) != _model->getURL()) { if (_model && (QUrl(getModelURL()) != _model->getURL() ||
QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) {
result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL()); result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL());
_needsInitialSimulation = true; _needsInitialSimulation = true;
} else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one } else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one
@ -403,23 +432,34 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
} }
void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) { void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
auto currentCompoundShapeURL = getCompoundShapeURL();
ModelEntityItem::setCompoundShapeURL(url); ModelEntityItem::setCompoundShapeURL(url);
if (_model) {
_model->setCollisionModelURL(QUrl(url)); if (getCompoundShapeURL() != currentCompoundShapeURL || !_model) {
EntityTreePointer tree = getTree();
if (tree) {
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
}
} }
} }
bool RenderableModelEntityItem::isReadyToComputeShape() { bool RenderableModelEntityItem::isReadyToComputeShape() {
ShapeType type = getShapeType(); ShapeType type = getShapeType();
if (type == SHAPE_TYPE_COMPOUND) {
if (type == SHAPE_TYPE_COMPOUND) {
if (!_model) { if (!_model) {
EntityTreePointer tree = getTree();
if (tree) {
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
}
return false; // hmm... return false; // hmm...
} }
if (_needsInitialSimulation) { if (_needsInitialSimulation) {
// the _model's offset will be wrong until _needsInitialSimulation is false // the _model's offset will be wrong until _needsInitialSimulation is false
return false; PerformanceTimer perfTimer("_model->simulate");
_model->simulate(0.0f);
_needsInitialSimulation = false;
} }
assert(!_model->getCollisionURL().isEmpty()); assert(!_model->getCollisionURL().isEmpty());

View file

@ -29,7 +29,8 @@ public:
virtual ~RenderableModelEntityItem(); virtual ~RenderableModelEntityItem();
virtual void setDimensions(const glm::vec3& value) override; virtual void setDimensions(const glm::vec3& value) override;
virtual void setModelURL(const QString& url);
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override; virtual bool setProperties(const EntityItemProperties& properties) override;
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
@ -71,6 +72,8 @@ public:
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
virtual void loader() override;
private: private:
void remapTextures(); void remapTextures();

View file

@ -382,6 +382,8 @@ public:
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); } virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); }
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); }
virtual void loader() {} // called indirectly when urls for geometry are updated
protected: protected:
const QByteArray getActionDataInternal() const; const QByteArray getActionDataInternal() const;

View file

@ -1266,3 +1266,12 @@ void EntityTree::trackIncomingEntityLastEdited(quint64 lastEditedTime, int bytes
} }
} }
} }
void EntityTree::callLoader(EntityItemID entityID) {
// this is used to bounce from the networking thread to the main thread
EntityItemPointer entity = findEntityByEntityItemID(entityID);
if (entity) {
entity->loader();
}
}

View file

@ -235,6 +235,9 @@ public:
return _deletedEntityItemIDs.contains(id); return _deletedEntityItemIDs.contains(id);
} }
public slots:
void callLoader(EntityItemID entityID);
signals: signals:
void deletingEntity(const EntityItemID& entityID); void deletingEntity(const EntityItemID& entityID);
void addingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID);

View file

@ -74,11 +74,10 @@ public:
_color[GREEN_INDEX] = value.green; _color[GREEN_INDEX] = value.green;
_color[BLUE_INDEX] = value.blue; _color[BLUE_INDEX] = value.blue;
} }
// model related properties
void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); }
virtual void setCompoundShapeURL(const QString& url);
// model related properties
virtual void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); }
virtual void setCompoundShapeURL(const QString& url);
// Animation related items... // Animation related items...
const AnimationPropertyGroup& getAnimationProperties() const { return _animationProperties; } const AnimationPropertyGroup& getAnimationProperties() const { return _animationProperties; }

View file

@ -57,7 +57,7 @@ public:
static bool getDrawZoneBoundaries() { return _drawZoneBoundaries; } static bool getDrawZoneBoundaries() { return _drawZoneBoundaries; }
static void setDrawZoneBoundaries(bool value) { _drawZoneBoundaries = value; } static void setDrawZoneBoundaries(bool value) { _drawZoneBoundaries = value; }
virtual bool isReadyToComputeShape() { return false; } virtual bool isReadyToComputeShape() { return true; }
void updateShapeType(ShapeType type) { _shapeType = type; } void updateShapeType(ShapeType type) { _shapeType = type; }
virtual ShapeType getShapeType() const; virtual ShapeType getShapeType() const;

View file

@ -319,10 +319,10 @@ void Resource::attemptRequest() {
void Resource::finishedLoading(bool success) { void Resource::finishedLoading(bool success) {
if (success) { if (success) {
qDebug().noquote() << "Finished loading:" << _url.toDisplayString(); qCDebug(networking).noquote() << "Finished loading:" << _url.toDisplayString();
_loaded = true; _loaded = true;
} else { } else {
qDebug().noquote() << "Failed to load:" << _url.toDisplayString(); qCDebug(networking).noquote() << "Failed to load:" << _url.toDisplayString();
_failedToLoad = true; _failedToLoad = true;
} }
_loadPriorities.clear(); _loadPriorities.clear();
@ -339,13 +339,13 @@ void Resource::makeRequest() {
_request = ResourceManager::createResourceRequest(this, _activeUrl); _request = ResourceManager::createResourceRequest(this, _activeUrl);
if (!_request) { if (!_request) {
qDebug().noquote() << "Failed to get request for" << _url.toDisplayString(); qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString();
ResourceCache::requestCompleted(this); ResourceCache::requestCompleted(this);
finishedLoading(false); finishedLoading(false);
return; return;
} }
qDebug().noquote() << "Starting request for:" << _url.toDisplayString(); qCDebug(networking).noquote() << "Starting request for:" << _url.toDisplayString();
connect(_request, &ResourceRequest::progress, this, &Resource::handleDownloadProgress); connect(_request, &ResourceRequest::progress, this, &Resource::handleDownloadProgress);
connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished); connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished);
@ -369,7 +369,7 @@ void Resource::handleReplyFinished() {
if (result == ResourceRequest::Success) { if (result == ResourceRequest::Success) {
_data = _request->getData(); _data = _request->getData();
auto extraInfo = _url == _activeUrl ? "" : QString(", %1").arg(_activeUrl.toDisplayString()); auto extraInfo = _url == _activeUrl ? "" : QString(", %1").arg(_activeUrl.toDisplayString());
qDebug().noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo); qCDebug(networking).noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo);
finishedLoading(true); finishedLoading(true);
emit loaded(_data); emit loaded(_data);
@ -377,7 +377,7 @@ void Resource::handleReplyFinished() {
} else { } else {
switch (result) { switch (result) {
case ResourceRequest::Result::Timeout: { case ResourceRequest::Result::Timeout: {
qDebug() << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal; qCDebug(networking) << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal;
// Fall through to other cases // Fall through to other cases
} }
case ResourceRequest::Result::ServerUnavailable: { case ResourceRequest::Result::ServerUnavailable: {
@ -386,7 +386,7 @@ void Resource::handleReplyFinished() {
const int BASE_DELAY_MS = 1000; const int BASE_DELAY_MS = 1000;
if (_attempts++ < MAX_ATTEMPTS) { if (_attempts++ < MAX_ATTEMPTS) {
auto waitTime = BASE_DELAY_MS * (int)pow(2.0, _attempts); auto waitTime = BASE_DELAY_MS * (int)pow(2.0, _attempts);
qDebug().nospace() << "Retrying to load the asset in " << waitTime qCDebug(networking).nospace() << "Retrying to load the asset in " << waitTime
<< "ms, attempt " << _attempts << " of " << MAX_ATTEMPTS; << "ms, attempt " << _attempts << " of " << MAX_ATTEMPTS;
QTimer::singleShot(waitTime, this, &Resource::attemptRequest); QTimer::singleShot(waitTime, this, &Resource::attemptRequest);
break; break;
@ -394,7 +394,7 @@ void Resource::handleReplyFinished() {
// fall through to final failure // fall through to final failure
} }
default: { default: {
qDebug() << "Error loading " << _url; qCDebug(networking) << "Error loading " << _url;
auto error = (result == ResourceRequest::Timeout) ? QNetworkReply::TimeoutError auto error = (result == ResourceRequest::Timeout) ? QNetworkReply::TimeoutError
: QNetworkReply::UnknownNetworkError; : QNetworkReply::UnknownNetworkError;
emit failed(error); emit failed(error);