From d09f70239c435fba20eafd61f84b160d856d7afe Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 09:03:53 -0800 Subject: [PATCH] make entity-tree a global. change how network-requests to load model geometry are triggered --- interface/src/Application.cpp | 73 ++++--- interface/src/Application.h | 3 +- .../src/EntityTreeRenderer.h | 2 +- .../src/RenderableModelEntityItem.cpp | 187 ++++++++++-------- .../src/RenderableModelEntityItem.h | 4 +- libraries/entities/src/EntityItem.h | 2 + libraries/entities/src/EntityTree.cpp | 9 + libraries/entities/src/EntityTree.h | 3 + libraries/entities/src/ModelEntityItem.h | 7 +- libraries/entities/src/ZoneEntityItem.h | 2 +- 10 files changed, 170 insertions(+), 122 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a03cad62a..1b94c913db 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -352,6 +352,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(true, qApp, qApp); return true; } @@ -371,7 +372,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _frameCount(0), _fps(60.0f), _physicsEngine(new PhysicsEngine(Vectors::ZERO)), - _entities(true, this, this), _entityClipboardRenderer(false, this, this), _entityClipboard(new EntityTree()), _lastQueriedTime(usecTimestampNow()), @@ -864,7 +864,7 @@ void Application::cleanupBeforeQuit() { } _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(); @@ -875,7 +875,7 @@ void Application::cleanupBeforeQuit() { // tell the packet receiver we're shutting down, so it can drop packets 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 // first stop all timers directly or by invokeMethod @@ -921,7 +921,7 @@ void Application::emptyLocalCache() { } Application::~Application() { - EntityTreePointer tree = _entities.getTree(); + EntityTreePointer tree = getEntities()->getTree(); tree->setSimulation(NULL); _octreeProcessor.terminate(); @@ -1995,7 +1995,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { event->buttons(), event->modifiers()); - _entities.mouseMoveEvent(&mappedEvent, deviceID); + getEntities()->mouseMoveEvent(&mappedEvent, deviceID); _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 @@ -2021,7 +2021,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { event->buttons(), event->modifiers()); if (!_aboutToQuit) { - _entities.mousePressEvent(&mappedEvent, deviceID); + getEntities()->mousePressEvent(&mappedEvent, deviceID); } _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts @@ -2066,7 +2066,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { event->buttons(), event->modifiers()); if (!_aboutToQuit) { - _entities.mouseReleaseEvent(&mappedEvent, deviceID); + getEntities()->mouseReleaseEvent(&mappedEvent, deviceID); } _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts @@ -2389,7 +2389,7 @@ void Application::calibrateEyeTracker5Points() { bool Application::exportEntities(const QString& filename, const QVector& entityIDs) { QVector entities; - auto entityTree = _entities.getTree(); + auto entityTree = getEntities()->getTree(); auto exportTree = std::make_shared(); exportTree->createRootElement(); @@ -2433,7 +2433,7 @@ bool Application::exportEntities(const QString& filename, const QVector 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) { glm::vec3 root(x, y, z); @@ -2501,7 +2501,7 @@ bool Application::importEntities(const QString& urlOrFilename) { } QVector 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() { @@ -2540,13 +2540,13 @@ void Application::init() { // fire off an immediate domain-server check in now that settings are loaded DependencyManager::get()->sendDomainServerCheckIn(); - _entities.init(); - _entities.setViewFrustum(getViewFrustum()); + getEntities()->init(); + getEntities()->setViewFrustum(getViewFrustum()); ObjectMotionState::setShapeManager(&_shapeManager); _physicsEngine->init(); - EntityTreePointer tree = _entities.getTree(); + EntityTreePointer tree = getEntities()->getTree(); _entitySimulation.init(tree, _physicsEngine, &_entityEditSender); tree->setSimulation(&_entitySimulation); @@ -2554,11 +2554,11 @@ void Application::init() { // connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts connect(&_entitySimulation, &EntitySimulation::entityCollisionWithEntity, - &_entities, &EntityTreeRenderer::entityCollisionWithEntity); + getEntities(), &EntityTreeRenderer::entityCollisionWithEntity); // connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing // of events related clicking, hovering over, and entering entities - _entities.connectSignalsToSlots(entityScriptingInterface.data()); + getEntities()->connectSignalsToSlots(entityScriptingInterface.data()); _entityClipboardRenderer.init(); _entityClipboardRenderer.setViewFrustum(getViewFrustum()); @@ -2907,19 +2907,19 @@ void Application::update(float deltaTime) { _avatarUpdate->synchronousProcess(); - if (true || _physicsEnabled) { + if (_physicsEnabled) { PerformanceTimer perfTimer("physics"); static VectorOfMotionStates motionStates; _entitySimulation.getObjectsToDelete(motionStates); _physicsEngine->deleteObjects(motionStates); - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _entitySimulation.getObjectsToAdd(motionStates); _physicsEngine->addObjects(motionStates); }); - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _entitySimulation.getObjectsToChange(motionStates); VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates); _entitySimulation.setObjectsToChange(stillNeedChange); @@ -2937,12 +2937,12 @@ void Application::update(float deltaTime) { myAvatar->prepareForPhysicsSimulation(); - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _physicsEngine->stepSimulation(); }); if (_physicsEngine->hasOutgoingChanges()) { - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID()); avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges()); }); @@ -2957,9 +2957,9 @@ void Application::update(float deltaTime) { // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk // deadlock.) _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). - _entities.update(); // update the models... + getEntities()->update(); // update the models... } myAvatar->harvestResultsFromPhysicsSimulation(); @@ -3781,7 +3781,7 @@ void Application::clearDomainOctreeDetails() { }); // reset the model renderer - _entities.clear(); + getEntities()->clear(); } void Application::domainChanged(const QString& domainHostname) { @@ -3903,7 +3903,7 @@ bool Application::nearbyEntitiesAreReadyForPhysics() { // 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 // 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) { return false; } @@ -3916,6 +3916,9 @@ bool Application::nearbyEntitiesAreReadyForPhysics() { foreach (EntityItemPointer entity, entities) { 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; } } @@ -3967,11 +3970,21 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer }); }); - if (!_physicsEnabled && nearbyEntitiesAreReadyForPhysics()) { - // These stats packets are sent in between full sends of a scene. - // We keep physics disabled until we've recieved a full scene and everything near the avatar in that - // scene is ready to compute its collision shape. - _physicsEnabled = true; + if (!_physicsEnabled) { + if (nearbyEntitiesAreReadyForPhysics()) { + // These stats packets are sent in between full sends of a scene. + // We keep physics disabled until we've recieved a full scene and everything near the avatar in that + // 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; @@ -4034,7 +4047,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri // we can use the same ones from the application. auto entityScriptingInterface = DependencyManager::get(); entityScriptingInterface->setPacketSender(&_entityEditSender); - entityScriptingInterface->setEntityTree(_entities.getTree()); + entityScriptingInterface->setEntityTree(getEntities()->getTree()); // AvatarManager has some custom types AvatarManager::registerMetaTypes(scriptEngine); diff --git a/interface/src/Application.h b/interface/src/Application.h index 27df7835e6..3d033e3b02 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -136,7 +136,7 @@ public: const ViewFrustum* getDisplayViewFrustum() const; ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } - EntityTreeRenderer* getEntities() { return &_entities; } + EntityTreeRenderer* getEntities() { return DependencyManager::get().data(); } QUndoStack* getUndoStack() { return &_undoStack; } MainWindow* getWindow() { return _window; } EntityTreePointer getEntityClipboard() { return _entityClipboard; } @@ -451,7 +451,6 @@ private: PhysicalEntitySimulation _entitySimulation; PhysicsEnginePointer _physicsEngine; - EntityTreeRenderer _entities; EntityTreeRenderer _entityClipboardRenderer; EntityTreePointer _entityClipboard; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 9980b9d8b6..076fe26d6f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -30,7 +30,7 @@ class ZoneEntityItem; // Generic client side Octree renderer class. -class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService { +class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency { Q_OBJECT public: EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b0f155decf..8b6f5ab967 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -12,12 +12,14 @@ #include #include +#include #include #include #include #include #include +#include #include "EntityTreeRenderer.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().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) { _dimensionsInitialized = true; ModelEntityItem::setDimensions(value); @@ -253,6 +281,60 @@ void RenderableModelEntityItem::render(RenderArgs* args) { remapTextures(); + { + // float alpha = getLocalRenderAlpha(); + + if (!_model || _needsModelReload) { + // TODO: this getModel() appears to be about 3% of model render time. We should optimize + PerformanceTimer perfTimer("getModel"); + EntityTreeRenderer* renderer = static_cast(args->_renderer); + getModel(renderer); + } + + if (_model) { + // handle animations.. + if (hasAnimation()) { + if (!jointsMapped()) { + QStringList modelJointNames = _model->getJointNames(); + mapJoints(modelJointNames); + } + + if (jointsMapped()) { + bool newFrame; + QVector frameDataRotations; + QVector frameDataTranslations; + getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); + assert(frameDataRotations.size() == frameDataTranslations.size()); + if (newFrame) { + for (int i = 0; i < frameDataRotations.size(); i++) { + _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); + } + } + } + } + + bool movingOrAnimating = isMoving() || isAnimatingSomething(); + if ((movingOrAnimating || + _needsInitialSimulation || + _model->getTranslation() != getPosition() || + _model->getRotation() != getRotation() || + _model->getRegistrationPoint() != getRegistrationPoint()) + && _model->isActive() && _dimensionsInitialized) { + _model->setScaleToFit(true, getDimensions()); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + + // make sure to simulate so everything gets set up correctly for rendering + { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + + _needsInitialSimulation = false; + } + } + } } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); gpu::Batch& batch = *args->_batch; @@ -264,7 +346,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { Model* result = NULL; - + if (!renderer) { return result; } @@ -286,7 +368,8 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { // 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. - if (_model && QUrl(getModelURL()) != _model->getURL()) { + if (_model && (QUrl(getModelURL()) != _model->getURL() || + QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) { result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL()); _needsInitialSimulation = true; } else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one @@ -295,6 +378,12 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } else { // we already have the model we want... result = _model; } + + if (_model && _needsInitialSimulation) { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + _needsInitialSimulation = false; } else { // if our desired URL is empty, we may need to delete our existing model if (_model) { _myRenderer->releaseModel(_model); @@ -307,35 +396,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } bool RenderableModelEntityItem::needsToCallUpdate() const { - if (!_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate()) { - return true; - } - - if (!_dimensionsInitialized && _model && _model->isActive()) { - return true; - } - - if (_myRenderer && (!_model || _needsModelReload)) { - return true; - } - - if (_model) { - if (hasAnimation() || jointsMapped()) { - return true; - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - return true; - } - } - - return false; + return !_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate(); } void RenderableModelEntityItem::update(const quint64& now) { @@ -351,56 +412,6 @@ void RenderableModelEntityItem::update(const quint64& now) { Q_ARG(EntityItemProperties, properties)); } - if (_myRenderer && (!_model || _needsModelReload)) { - // TODO: this getModel() appears to be about 3% of model render time. We should optimize - PerformanceTimer perfTimer("getModel"); - getModel(_myRenderer); - } - - if (_model) { - // handle animations.. - if (hasAnimation()) { - if (!jointsMapped()) { - QStringList modelJointNames = _model->getJointNames(); - mapJoints(modelJointNames); - } - - if (jointsMapped()) { - bool newFrame; - QVector frameDataRotations; - QVector frameDataTranslations; - getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); - assert(frameDataRotations.size() == frameDataTranslations.size()); - if (newFrame) { - for (int i = 0; i < frameDataRotations.size(); i++) { - _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); - } - } - } - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - _model->setScaleToFit(true, getDimensions()); - _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); - - // make sure to simulate so everything gets set up correctly for rendering - { - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - } - - _needsInitialSimulation = false; - } - } - ModelEntityItem::update(now); } @@ -427,17 +438,27 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori } void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) { + auto currentCompoundShapeURL = getCompoundShapeURL(); 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() { ShapeType type = getShapeType(); + if (type == SHAPE_TYPE_COMPOUND) { if (!_model) { + EntityTreePointer tree = getTree(); + if (tree) { + QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); + } return false; // hmm... } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 3f3fe11633..45d5f43683 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -29,7 +29,8 @@ public: virtual ~RenderableModelEntityItem(); virtual void setDimensions(const glm::vec3& value) override; - + virtual void setModelURL(const QString& url); + virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -72,6 +73,7 @@ public: virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; void locationChanged(); + virtual void loader() override; private: void remapTextures(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 69d642fad1..a1fc89c5e0 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -382,6 +382,8 @@ public: 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 void loader() {} // called indirectly when urls for geometry are updated + protected: const QByteArray getActionDataInternal() const; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index abad1e5cd1..7688d034d0 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -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(); + } +} diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 064c106b91..e893c69259 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -235,6 +235,9 @@ public: return _deletedEntityItemIDs.contains(id); } +public slots: + void callLoader(EntityItemID entityID); + signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index cbd54f7168..310e741fda 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -74,11 +74,10 @@ public: _color[GREEN_INDEX] = value.green; _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... const AnimationPropertyGroup& getAnimationProperties() const { return _animationProperties; } diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index bf323248c0..19206f8acc 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -57,7 +57,7 @@ public: static bool getDrawZoneBoundaries() { return _drawZoneBoundaries; } static void setDrawZoneBoundaries(bool value) { _drawZoneBoundaries = value; } - virtual bool isReadyToComputeShape() { return false; } + virtual bool isReadyToComputeShape() { return true; } void updateShapeType(ShapeType type) { _shapeType = type; } virtual ShapeType getShapeType() const;