History

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

samcake committed 9 years ago

Commit 0a3c1712 parents 8a2837e 142739e21 files · +205 −101Browse files

Unified · Split

21 files
  1. interface/src/Application.cpp +32 −4
  2. interface/src/Menu.cpp +6 −0
  3. interface/src/Menu.h +1 −0
  4. libraries/entities/src/EntityItem.cpp +7 −17
  5. libraries/entities/src/EntityItem.h +2 −2
  6. libraries/entities/src/EntityScriptingInterface.cpp +6 −4
  7. libraries/entities/src/SimulationFlags.h +1 −3
  8. libraries/entities/src/SimulationOwner.cpp +11 −11
  9. libraries/entities/src/SimulationOwner.h +3 −2
  10. libraries/model-networking/src/model-networking/KTXCache.cpp +14 −0
  11. libraries/model-networking/src/model-networking/KTXCache.h +6 −0
  12. libraries/networking/src/FileCache.cpp +31 −14
  13. libraries/networking/src/FileCache.h +12 −4
  14. libraries/physics/src/EntityMotionState.cpp +20 −15
  15. libraries/physics/src/EntityMotionState.h +1 −0
  16. libraries/physics/src/ObjectMotionState.h +1 −0
  17. libraries/physics/src/PhysicsEngine.cpp +24 −19
  18. libraries/physics/src/PhysicsEngine.h +2 −1
  19. libraries/physics/src/ThreadSafeDynamicsWorld.h +2 −0
  20. tests/networking/src/FileCacheTests.cpp +22 −5
  21. tests/networking/src/FileCacheTests.h +1 −0
interface/src/Application.cpp+32−4
@@ -2413,15 +2413,16 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 2412 unmodified lines
24132413
24142414 // Check HMD use (may be technically available without being in use)
24152415 bool hasHMD = PluginUtils::isHMDAvailable();
2416− bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd();
2416+ bool isUsingHMD = _displayPlugin->isHmd();
2417+ bool isUsingHMDAndHandControllers = hasHMD && hasHandControllers && isUsingHMD;
24172418
24182419 Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false };
24192420 Setting::Handle<bool> firstRun{ Settings::firstRun, true };
24202421
24212422 bool isTutorialComplete = tutorialComplete.get();
2422− bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete;
2423+ bool shouldGoToTutorial = isUsingHMDAndHandControllers && hasTutorialContent && !isTutorialComplete;
24232424
2424− qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD;
2425+ qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers;
24252426 qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<
24262427 ", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;
24272428
@@ -2435,10 +2436,18 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 7 unmodified lines
24352436
24362437 const QString TUTORIAL_PATH = "/tutorial_begin";
24372438
2439+ static const QString SENT_TO_TUTORIAL = "tutorial";
2440+ static const QString SENT_TO_PREVIOUS_LOCATION = "previous_location";
2441+ static const QString SENT_TO_ENTRY = "entry";
2442+ static const QString SENT_TO_SANDBOX = "sandbox";
2443+
2444+ QString sentTo;
2445+
24382446 if (shouldGoToTutorial) {
24392447 if (sandboxIsRunning) {
24402448 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
24412449 DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
2450+ sentTo = SENT_TO_TUTORIAL;
24422451 } else {
24432452 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
24442453 if (firstRun.get()) {
@@ -2446,8 +2455,10 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 1 unmodified line
24462455 }
24472456 if (addressLookupString.isEmpty()) {
24482457 DependencyManager::get<AddressManager>()->goToEntry();
2458+ sentTo = SENT_TO_ENTRY;
24492459 } else {
24502460 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
2461+ sentTo = SENT_TO_PREVIOUS_LOCATION;
24512462 }
24522463 }
24532464 } else {
@@ -2460,23 +2471,40 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 6 unmodified lines
24602471
24612472 // If this is a first run we short-circuit the address passed in
24622473 if (isFirstRun) {
2463− if (isUsingHMD) {
2474+ if (isUsingHMDAndHandControllers) {
24642475 if (sandboxIsRunning) {
24652476 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
24662477 DependencyManager::get<AddressManager>()->goToLocalSandbox();
2478+ sentTo = SENT_TO_SANDBOX;
24672479 } else {
24682480 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
24692481 DependencyManager::get<AddressManager>()->goToEntry();
2482+ sentTo = SENT_TO_ENTRY;
24702483 }
24712484 } else {
24722485 DependencyManager::get<AddressManager>()->goToEntry();
2486+ sentTo = SENT_TO_ENTRY;
24732487 }
24742488 } else {
24752489 qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
24762490 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
2491+ sentTo = SENT_TO_PREVIOUS_LOCATION;
24772492 }
24782493 }
24792494
2495+ UserActivityLogger::getInstance().logAction("startup_sent_to", {
2496+ { "sent_to", sentTo },
2497+ { "sandbox_is_running", sandboxIsRunning },
2498+ { "has_hmd", hasHMD },
2499+ { "has_hand_controllers", hasHandControllers },
2500+ { "is_using_hmd", isUsingHMD },
2501+ { "is_using_hmd_and_hand_controllers", isUsingHMDAndHandControllers },
2502+ { "content_version", contentVersion },
2503+ { "is_tutorial_complete", isTutorialComplete },
2504+ { "has_tutorial_content", hasTutorialContent },
2505+ { "should_go_to_tutorial", shouldGoToTutorial }
2506+ });
2507+
24802508 _connectionMonitor.init();
24812509
24822510 // After all of the constructor is completed, then set firstRun to false.
interface/src/Menu.cpp+6−0
@@ -407,6 +407,12 @@ Menu::Menu() { · 406 unmodified lines
407407 #endif
408408
409409
410+ {
411+ auto action = addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderClearKtxCache);
412+ connect(action, &QAction::triggered, []{
413+ Setting::Handle<int>(KTXCache::SETTING_VERSION_NAME, KTXCache::INVALID_VERSION).set(KTXCache::INVALID_VERSION);
414+ });
415+ }
410416
411417 // Developer > Render > LOD Tools
412418 addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, 0,
interface/src/Menu.h+1−0
@@ -145,6 +145,7 @@ namespace MenuOption { · 144 unmodified lines
145145 const QString Quit = "Quit";
146146 const QString ReloadAllScripts = "Reload All Scripts";
147147 const QString ReloadContent = "Reload Content (Clears all caches)";
148+ const QString RenderClearKtxCache = "Clear KTX Cache (requires restart)";
148149 const QString RenderMaxTextureMemory = "Maximum Texture Memory";
149150 const QString RenderMaxTextureAutomatic = "Automatic Texture Memory";
150151 const QString RenderMaxTexture4MB = "4 MB";
libraries/entities/src/EntityItem.cpp+7−17
@@ -681,7 +681,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef · 680 unmodified lines
681681 // and pretend that we own it (we assume we'll recover it soon)
682682
683683 // However, for now, when the server uses a newer time than what we sent, listen to what we're told.
684− if (overwriteLocalData) weOwnSimulation = false;
684+ if (overwriteLocalData) {
685+ weOwnSimulation = false;
686+ }
685687 } else if (_simulationOwner.set(newSimOwner)) {
686688 markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
687689 somethingChanged = true;
@@ -1293,27 +1295,15 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c · 605 unmodified lines
12931295 properties._accelerationChanged = true;
12941296 }
12951297
1296−void EntityItem::pokeSimulationOwnership() {
1297− markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE);
1298− auto nodeList = DependencyManager::get<NodeList>();
1299− if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
1300− // we already own it
1301− _simulationOwner.promotePriority(SCRIPT_POKE_SIMULATION_PRIORITY);
1302− } else {
1303− // we don't own it yet
1304− _simulationOwner.setPendingPriority(SCRIPT_POKE_SIMULATION_PRIORITY, usecTimestampNow());
1305− }
1306−}
1307−
1308−void EntityItem::grabSimulationOwnership() {
1309− markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB);
1298+void EntityItem::flagForOwnershipBid(uint8_t priority) {
1299+ markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY);
13101300 auto nodeList = DependencyManager::get<NodeList>();
13111301 if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
13121302 // we already own it
1313− _simulationOwner.promotePriority(SCRIPT_GRAB_SIMULATION_PRIORITY);
1303+ _simulationOwner.promotePriority(priority);
13141304 } else {
13151305 // we don't own it yet
1316− _simulationOwner.setPendingPriority(SCRIPT_GRAB_SIMULATION_PRIORITY, usecTimestampNow());
1306+ _simulationOwner.setPendingPriority(priority, usecTimestampNow());
13171307 }
13181308 }
13191309
libraries/entities/src/EntityItem.h+2−2
@@ -321,6 +321,7 @@ public: · 320 unmodified lines
321321 void updateSimulationOwner(const SimulationOwner& owner);
322322 void clearSimulationOwnership();
323323 void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp);
324+ uint8_t getPendingOwnershipPriority() const { return _simulationOwner.getPendingPriority(); }
324325 void rememberHasSimulationOwnershipBid() const;
325326
326327 QString getMarketplaceID() const;
@@ -394,8 +395,7 @@ public: · 67 unmodified lines
394395
395396 void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
396397
397− void pokeSimulationOwnership();
398− void grabSimulationOwnership();
398+ void flagForOwnershipBid(uint8_t priority);
399399 void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; }
400400
401401 QString actionsToDebugString();
libraries/entities/src/EntityScriptingInterface.cpp+6−4
@@ -230,6 +230,8 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties · 229 unmodified lines
230230 }
231231
232232 entity->setLastBroadcast(usecTimestampNow());
233+ // since we're creating this object we will immediately volunteer to own its simulation
234+ entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY);
233235 propertiesWithSimID.setLastEdited(entity->getLastEdited());
234236 } else {
235237 qCDebug(entities) << "script failed to add new Entity to local Octree";
@@ -440,7 +442,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& · 204 unmodified lines
440442 } else {
441443 // we make a bid for simulation ownership
442444 properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY);
443− entity->pokeSimulationOwnership();
445+ entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY);
444446 entity->rememberHasSimulationOwnershipBid();
445447 }
446448 }
@@ -1194,7 +1196,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, · 747 unmodified lines
11941196 }
11951197 action->setIsMine(true);
11961198 success = entity->addAction(simulation, action);
1197− entity->grabSimulationOwnership();
1199+ entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY);
11981200 return false; // Physics will cause a packet to be sent, so don't send from here.
11991201 });
12001202 if (success) {
@@ -1210,7 +1212,7 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid& · 9 unmodified lines
12101212 return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) {
12111213 bool success = entity->updateAction(simulation, actionID, arguments);
12121214 if (success) {
1213− entity->grabSimulationOwnership();
1215+ entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY);
12141216 }
12151217 return success;
12161218 });
@@ -1224,7 +1226,7 @@ bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid& · 7 unmodified lines
12241226 success = entity->removeAction(simulation, actionID);
12251227 if (success) {
12261228 // reduce from grab to poke
1227− entity->pokeSimulationOwnership();
1229+ entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY);
12281230 }
12291231 return false; // Physics will cause a packet to be sent, so don't send from here.
12301232 });
libraries/entities/src/SimulationFlags.h+1−3
@@ -26,12 +26,10 @@ namespace Simulation { · 25 unmodified lines
2626 const uint32_t DIRTY_MATERIAL = 0x00400;
2727 const uint32_t DIRTY_PHYSICS_ACTIVATION = 0x0800; // should activate object in physics engine
2828 const uint32_t DIRTY_SIMULATOR_ID = 0x1000; // the simulatorID has changed
29− const uint32_t DIRTY_SIMULATION_OWNERSHIP_FOR_POKE = 0x2000; // bid for simulation ownership at "poke"
30− const uint32_t DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB = 0x4000; // bid for simulation ownership at "grab"
29+ const uint32_t DIRTY_SIMULATION_OWNERSHIP_PRIORITY = 0x2000; // our own bid priority has changed
3130
3231 const uint32_t DIRTY_TRANSFORM = DIRTY_POSITION | DIRTY_ROTATION;
3332 const uint32_t DIRTY_VELOCITIES = DIRTY_LINEAR_VELOCITY | DIRTY_ANGULAR_VELOCITY;
34− const uint32_t DIRTY_SIMULATION_OWNERSHIP_PRIORITY = DIRTY_SIMULATION_OWNERSHIP_FOR_POKE | DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB;
3533 };
3634
3735 #endif // hifi_SimulationFlags_h
libraries/entities/src/SimulationOwner.cpp+11−11
@@ -26,9 +26,9 @@ const int SimulationOwner::NUM_BYTES_ENCODED = NUM_BYTES_RFC4122_UUID + 1; · 25 unmodified lines
2626 SimulationOwner::SimulationOwner() :
2727 _id(),
2828 _expiry(0),
29− _pendingTimestamp(0),
29+ _pendingBidTimestamp(0),
3030 _priority(0),
31− _pendingPriority(0),
31+ _pendingBidPriority(0),
3232 _pendingState(PENDING_STATE_NOTHING)
3333 {
3434 }
@@ -36,9 +36,9 @@ SimulationOwner::SimulationOwner() : · 1 unmodified line
3636 SimulationOwner::SimulationOwner(const QUuid& id, quint8 priority) :
3737 _id(id),
3838 _expiry(0),
39− _pendingTimestamp(0),
39+ _pendingBidTimestamp(0),
4040 _priority(priority),
41− _pendingPriority(0)
41+ _pendingBidPriority(0)
4242 {
4343 }
4444
@@ -61,9 +61,9 @@ bool SimulationOwner::fromByteArray(const QByteArray& data) { · 16 unmodified lines
6161 void SimulationOwner::clear() {
6262 _id = QUuid();
6363 _expiry = 0;
64− _pendingTimestamp = 0;
64+ _pendingBidTimestamp = 0;
6565 _priority = 0;
66− _pendingPriority = 0;
66+ _pendingBidPriority = 0;
6767 _pendingState = PENDING_STATE_NOTHING;
6868 }
6969
@@ -102,9 +102,9 @@ bool SimulationOwner::set(const SimulationOwner& owner) { · 32 unmodified lines
102102 }
103103
104104 void SimulationOwner::setPendingPriority(quint8 priority, const quint64& timestamp) {
105− _pendingPriority = priority;
106− _pendingTimestamp = timestamp;
107− _pendingState = (_pendingPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE;
105+ _pendingBidPriority = priority;
106+ _pendingBidTimestamp = timestamp;
107+ _pendingState = (_pendingBidPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE;
108108 }
109109
110110 void SimulationOwner::updateExpiry() {
@@ -113,11 +113,11 @@ void SimulationOwner::updateExpiry() { · 2 unmodified lines
113113 }
114114
115115 bool SimulationOwner::pendingRelease(const quint64& timestamp) {
116− return _pendingPriority == 0 && _pendingState == PENDING_STATE_RELEASE && _pendingTimestamp >= timestamp;
116+ return _pendingBidPriority == 0 && _pendingState == PENDING_STATE_RELEASE && _pendingBidTimestamp >= timestamp;
117117 }
118118
119119 bool SimulationOwner::pendingTake(const quint64& timestamp) {
120− return _pendingPriority > 0 && _pendingState == PENDING_STATE_TAKE && _pendingTimestamp >= timestamp;
120+ return _pendingBidPriority > 0 && _pendingState == PENDING_STATE_TAKE && _pendingBidTimestamp >= timestamp;
121121 }
122122
123123 void SimulationOwner::clearCurrentOwner() {
libraries/entities/src/SimulationOwner.h+3−2
@@ -66,6 +66,7 @@ public: · 65 unmodified lines
6666
6767 bool hasExpired() const { return usecTimestampNow() > _expiry; }
6868
69+ uint8_t getPendingPriority() const { return _pendingBidPriority; }
6970 bool pendingRelease(const quint64& timestamp); // return true if valid pending RELEASE
7071 bool pendingTake(const quint64& timestamp); // return true if valid pending TAKE
7172 void clearCurrentOwner();
@@ -84,9 +85,9 @@ public: · 12 unmodified lines
8485 private:
8586 QUuid _id; // owner
8687 quint64 _expiry; // time when ownership can transition at equal priority
87− quint64 _pendingTimestamp; // time when pending update was set
88+ quint64 _pendingBidTimestamp; // time when pending bid was set
8889 quint8 _priority; // priority of current owner
89− quint8 _pendingPriority; // priority of pendingTake
90+ quint8 _pendingBidPriority; // priority at which we'd like to own it
9091 quint8 _pendingState; // NOTHING, TAKE, or RELEASE
9192 };
9293
libraries/model-networking/src/model-networking/KTXCache.cpp+14−0
@@ -11,14 +11,28 @@ · 10 unmodified lines
1111
1212 #include "KTXCache.h"
1313
14+#include <SettingHandle.h>
1415 #include <ktx/KTX.h>
1516
1617 using File = cache::File;
1718 using FilePointer = cache::FilePointer;
1819
20+// Whenever a change is made to the serialized format for the KTX cache that isn't backward compatible,
21+// this value should be incremented. This will force the KTX cache to be wiped
22+const int KTXCache::CURRENT_VERSION = 0x01;
23+const int KTXCache::INVALID_VERSION = 0x00;
24+const char* KTXCache::SETTING_VERSION_NAME = "hifi.ktx.cache_version";
25+
1926 KTXCache::KTXCache(const std::string& dir, const std::string& ext) :
2027 FileCache(dir, ext) {
2128 initialize();
29+
30+ Setting::Handle<int> cacheVersionHandle(SETTING_VERSION_NAME, INVALID_VERSION);
31+ auto cacheVersion = cacheVersionHandle.get();
32+ if (cacheVersion != CURRENT_VERSION) {
33+ wipe();
34+ cacheVersionHandle.set(CURRENT_VERSION);
35+ }
2236 }
2337
2438 KTXFilePointer KTXCache::writeFile(const char* data, Metadata&& metadata) {
libraries/model-networking/src/model-networking/KTXCache.h+6−0
@@ -27,6 +27,12 @@ class KTXCache : public cache::FileCache { · 26 unmodified lines
2727 Q_OBJECT
2828
2929 public:
30+ // Whenever a change is made to the serialized format for the KTX cache that isn't backward compatible,
31+ // this value should be incremented. This will force the KTX cache to be wiped
32+ static const int CURRENT_VERSION;
33+ static const int INVALID_VERSION;
34+ static const char* SETTING_VERSION_NAME;
35+
3036 KTXCache(const std::string& dir, const std::string& ext);
3137
3238 KTXFilePointer writeFile(const char* data, Metadata&& metadata);
libraries/networking/src/FileCache.cpp+31−14
@@ -236,6 +236,28 @@ namespace cache { · 235 unmodified lines
236236 };
237237 }
238238
239+void FileCache::eject(const FilePointer& file) {
240+ file->_cache = nullptr;
241+ const auto& length = file->getLength();
242+ const auto& key = file->getKey();
243+
244+ {
245+ Lock lock(_filesMutex);
246+ if (0 != _files.erase(key)) {
247+ _numTotalFiles -= 1;
248+ _totalFilesSize -= length;
249+ }
250+ }
251+
252+ {
253+ Lock unusedLock(_unusedFilesMutex);
254+ if (0 != _unusedFiles.erase(file)) {
255+ _numUnusedFiles -= 1;
256+ _unusedFilesSize -= length;
257+ }
258+ }
259+}
260+
239261 void FileCache::clean() {
240262 size_t overbudgetAmount = getOverbudgetAmount();
241263
@@ -250,28 +272,23 @@ void FileCache::clean() { · 8 unmodified lines
250272 for (const auto& file : _unusedFiles) {
251273 queue.push(file);
252274 }
275+
253276 while (!queue.empty() && overbudgetAmount > 0) {
254277 auto file = queue.top();
255278 queue.pop();
279+ eject(file);
256280 auto length = file->getLength();
257−
258− unusedLock.unlock();
259− {
260− file->_cache = nullptr;
261− Lock lock(_filesMutex);
262− _files.erase(file->getKey());
263− }
264− unusedLock.lock();
265−
266− _unusedFiles.erase(file);
267− _numTotalFiles -= 1;
268− _numUnusedFiles -= 1;
269− _totalFilesSize -= length;
270− _unusedFilesSize -= length;
271281 overbudgetAmount -= std::min(length, overbudgetAmount);
272282 }
273283 }
274284
285+void FileCache::wipe() {
286+ Lock unusedFilesLock(_unusedFilesMutex);
287+ while (!_unusedFiles.empty()) {
288+ eject(*_unusedFiles.begin());
289+ }
290+}
291+
275292 void FileCache::clear() {
276293 // Eliminate any overbudget files
277294 clean();
libraries/networking/src/FileCache.h+12−4
@@ -46,6 +46,9 @@ public: · 45 unmodified lines
4646 FileCache(const std::string& dirname, const std::string& ext, QObject* parent = nullptr);
4747 virtual ~FileCache();
4848
49+ // Remove all unlocked items from the cache
50+ void wipe();
51+
4952 size_t getNumTotalFiles() const { return _numTotalFiles; }
5053 size_t getNumCachedFiles() const { return _numUnusedFiles; }
5154 size_t getSizeTotalFiles() const { return _totalFilesSize; }
@@ -95,6 +98,9 @@ public: · 43 unmodified lines
9598 private:
9699 using Mutex = std::recursive_mutex;
97100 using Lock = std::unique_lock<Mutex>;
101+ using Map = std::unordered_map<Key, std::weak_ptr<File>>;
102+ using Set = std::unordered_set<FilePointer>;
103+ using KeySet = std::unordered_set<Key>;
98104
99105 friend class File;
100106
@@ -105,6 +111,8 @@ private: · 4 unmodified lines
105111 void removeUnusedFile(const FilePointer& file);
106112 void clean();
107113 void clear();
114+ // Remove a file from the cache
115+ void eject(const FilePointer& file);
108116
109117 size_t getOverbudgetAmount() const;
110118
@@ -122,10 +130,10 @@ private: · 11 unmodified lines
122130 std::string _dirpath;
123131 bool _initialized { false };
124132
125− std::unordered_map<Key, std::weak_ptr<File>> _files;
133+ Map _files;
126134 Mutex _filesMutex;
127135
128− std::unordered_set<FilePointer> _unusedFiles;
136+ Set _unusedFiles;
129137 Mutex _unusedFilesMutex;
130138 };
131139
@@ -136,8 +144,8 @@ public: · 4 unmodified lines
136144 using Key = FileCache::Key;
137145 using Metadata = FileCache::Metadata;
138146
139− Key getKey() const { return _key; }
140− size_t getLength() const { return _length; }
147+ const Key& getKey() const { return _key; }
148+ const size_t& getLength() const { return _length; }
141149 std::string getFilepath() const { return _filepath; }
142150
143151 virtual ~File();
libraries/physics/src/EntityMotionState.cpp+20−15
@@ -65,8 +65,7 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer · 64 unmodified lines
6565 _lastStep(0),
6666 _loopsWithoutOwner(0),
6767 _accelerationNearlyGravityCount(0),
68− _numInactiveUpdates(1),
69− _outgoingPriority(0)
68+ _numInactiveUpdates(1)
7069 {
7170 _type = MOTIONSTATE_TYPE_ENTITY;
7271 assert(_entity);
@@ -75,6 +74,8 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer · 2 unmodified lines
7574 // we need the side-effects of EntityMotionState::setShape() so we call it explicitly here
7675 // rather than pass the legit shape pointer to the ObjectMotionState ctor above.
7776 setShape(shape);
77+
78+ _outgoingPriority = _entity->getPendingOwnershipPriority();
7879 }
7980
8081 EntityMotionState::~EntityMotionState() {
@@ -84,7 +85,7 @@ EntityMotionState::~EntityMotionState() { · 3 unmodified lines
8485
8586 void EntityMotionState::updateServerPhysicsVariables() {
8687 assert(entityTreeIsLocked());
87− if (_entity->getSimulatorID() == Physics::getSessionUUID()) {
88+ if (isLocallyOwned()) {
8889 // don't slam these values if we are the simulation owner
8990 return;
9091 }
@@ -136,23 +137,23 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) { · 45 unmodified lines
136137 _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
137138 }
138139 _loopsWithoutOwner = 0;
139− } else if (_entity->getSimulatorID() == Physics::getSessionUUID()) {
140+ _numInactiveUpdates = 0;
141+ } else if (isLocallyOwned()) {
140142 // we just inherited ownership, make sure our desired priority matches what we have
141143 upgradeOutgoingPriority(_entity->getSimulationPriority());
142144 } else {
143145 _outgoingPriority = 0;
144146 _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
147+ _numInactiveUpdates = 0;
145148 }
146149 }
147150 if (flags & Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY) {
148− // The DIRTY_SIMULATOR_OWNERSHIP_PRIORITY bits really mean "we should bid for ownership because
149− // a local script has been changing physics properties, or we should adjust our own ownership priority".
150− // The desired priority is determined by which bits were set.
151− if (flags & Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB) {
152− _outgoingPriority = SCRIPT_GRAB_SIMULATION_PRIORITY;
153− } else {
154− _outgoingPriority = SCRIPT_POKE_SIMULATION_PRIORITY;
155− }
151+ // The DIRTY_SIMULATOR_OWNERSHIP_PRIORITY bit means one of the following:
152+ // (1) we own it but may need to change the priority OR...
153+ // (2) we don't own it but should bid (because a local script has been changing physics properties)
154+ uint8_t newPriority = isLocallyOwned() ? _entity->getSimulationOwner().getPriority() : _entity->getSimulationOwner().getPendingPriority();
155+ _outgoingPriority = glm::max(_outgoingPriority, newPriority);
156+
156157 // reset bid expiry so that we bid ASAP
157158 _nextOwnershipBid = 0;
158159 }
@@ -317,7 +318,7 @@ bool EntityMotionState::isCandidateForOwnership() const { · 158 unmodified lines
317318 assert(_entity);
318319 assert(entityTreeIsLocked());
319320 return _outgoingPriority != 0
320− || Physics::getSessionUUID() == _entity->getSimulatorID()
321+ || isLocallyOwned()
321322 || _entity->dynamicDataNeedsTransmit();
322323 }
323324
@@ -491,7 +492,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { · 167 unmodified lines
491492 return true;
492493 }
493494
494− if (_entity->getSimulatorID() != Physics::getSessionUUID()) {
495+ if (!isLocallyOwned()) {
495496 // we don't own the simulation
496497
497498 // NOTE: we do not volunteer to own kinematic or static objects
@@ -599,7 +600,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ · 101 unmodified lines
599600 properties.clearSimulationOwner();
600601 _outgoingPriority = 0;
601602 _entity->setPendingOwnershipPriority(_outgoingPriority, now);
602− } else if (Physics::getSessionUUID() != _entity->getSimulatorID()) {
603+ } else if (!isLocallyOwned()) {
603604 // we don't own the simulation for this entity yet, but we're sending a bid for it
604605 quint8 bidPriority = glm::max<uint8_t>(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY);
605606 properties.setSimulationOwner(Physics::getSessionUUID(), bidPriority);
@@ -788,6 +789,10 @@ void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma · 182 unmodified lines
788789 _entity->computeCollisionGroupAndFinalMask(group, mask);
789790 }
790791
792+bool EntityMotionState::isLocallyOwned() const {
793+ return _entity->getSimulatorID() == Physics::getSessionUUID();
794+}
795+
791796 bool EntityMotionState::shouldBeLocallyOwned() const {
792797 return (_outgoingPriority > VOLUNTEER_SIMULATION_PRIORITY && _outgoingPriority > _entity->getSimulationPriority()) ||
793798 _entity->getSimulatorID() == Physics::getSessionUUID();
libraries/physics/src/EntityMotionState.h+1−0
@@ -79,6 +79,7 @@ public: · 78 unmodified lines
7979
8080 virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;
8181
82+ bool isLocallyOwned() const override;
8283 bool shouldBeLocallyOwned() const override;
8384
8485 friend class PhysicalEntitySimulation;
libraries/physics/src/ObjectMotionState.h+1−0
@@ -146,6 +146,7 @@ public: · 145 unmodified lines
146146 void dirtyInternalKinematicChanges() { _hasInternalKinematicChanges = true; }
147147 void clearInternalKinematicChanges() { _hasInternalKinematicChanges = false; }
148148
149+ virtual bool isLocallyOwned() const { return false; }
149150 virtual bool shouldBeLocallyOwned() const { return false; }
150151
151152 friend class PhysicsEngine;
libraries/physics/src/PhysicsEngine.cpp+24−19
@@ -129,6 +129,9 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { · 128 unmodified lines
129129 }
130130 body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
131131 body->updateInertiaTensor();
132+ if (motionState->isLocallyOwned()) {
133+ _activeStaticBodies.insert(body);
134+ }
132135 break;
133136 }
134137 }
@@ -174,19 +177,9 @@ void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) { · 39 unmodified lines
174177 // frame (because the framerate is faster than our physics simulation rate). When this happens we must scan
175178 // _activeStaticBodies for objects that were recently deleted so we don't try to access a dangling pointer.
176179 for (auto object : objects) {
177− btRigidBody* body = object->getRigidBody();
178−
179− std::vector<btRigidBody*>::reverse_iterator itr = _activeStaticBodies.rbegin();
180− while (itr != _activeStaticBodies.rend()) {
181− if (body == *itr) {
182− if (*itr != *(_activeStaticBodies.rbegin())) {
183− // swap with rbegin
184− *itr = *(_activeStaticBodies.rbegin());
185− }
186− _activeStaticBodies.pop_back();
187− break;
188− }
189− ++itr;
180+ std::set<btRigidBody*>::iterator itr = _activeStaticBodies.find(object->getRigidBody());
181+ if (itr != _activeStaticBodies.end()) {
182+ _activeStaticBodies.erase(itr);
190183 }
191184 }
192185 }
@@ -245,14 +238,16 @@ VectorOfMotionStates PhysicsEngine::changeObjects(const VectorOfMotionStates& ob · 52 unmodified lines
245238 object->clearIncomingDirtyFlags();
246239 }
247240 if (object->getMotionType() == MOTION_TYPE_STATIC && object->isActive()) {
248− _activeStaticBodies.push_back(object->getRigidBody());
241+ _activeStaticBodies.insert(object->getRigidBody());
249242 }
250243 }
251244 // active static bodies have changed (in an Easy way) and need their Aabbs updated
252245 // but we've configured Bullet to NOT update them automatically (for improved performance)
253246 // so we must do it ourselves
254− for (size_t i = 0; i < _activeStaticBodies.size(); ++i) {
255− _dynamicsWorld->updateSingleAabb(_activeStaticBodies[i]);
247+ std::set<btRigidBody*>::const_iterator itr = _activeStaticBodies.begin();
248+ while (itr != _activeStaticBodies.end()) {
249+ _dynamicsWorld->updateSingleAabb(*itr);
250+ ++itr;
256251 }
257252 return stillNeedChange;
258253 }
@@ -496,13 +491,23 @@ const CollisionEvents& PhysicsEngine::getCollisionEvents() { · 237 unmodified lines
496491
497492 const VectorOfMotionStates& PhysicsEngine::getChangedMotionStates() {
498493 BT_PROFILE("copyOutgoingChanges");
494+
495+ _dynamicsWorld->synchronizeMotionStates();
496+
499497 // Bullet will not deactivate static objects (it doesn't expect them to be active)
500498 // so we must deactivate them ourselves
501− for (size_t i = 0; i < _activeStaticBodies.size(); ++i) {
502− _activeStaticBodies[i]->forceActivationState(ISLAND_SLEEPING);
499+ std::set<btRigidBody*>::const_iterator itr = _activeStaticBodies.begin();
500+ while (itr != _activeStaticBodies.end()) {
501+ btRigidBody* body = *itr;
502+ body->forceActivationState(ISLAND_SLEEPING);
503+ ObjectMotionState* motionState = static_cast<ObjectMotionState*>(body->getUserPointer());
504+ if (motionState) {
505+ _dynamicsWorld->addChangedMotionState(motionState);
506+ }
507+ ++itr;
503508 }
504509 _activeStaticBodies.clear();
505− _dynamicsWorld->synchronizeMotionStates();
510+
506511 _hasOutgoingChanges = false;
507512 return _dynamicsWorld->getChangedMotionStates();
508513 }
libraries/physics/src/PhysicsEngine.h+2−1
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313 #define hifi_PhysicsEngine_h
1414
1515 #include <stdint.h>
16+#include <set>
1617 #include <vector>
1718
1819 #include <QUuid>
@@ -114,7 +115,7 @@ private: · 95 unmodified lines
114115 CollisionEvents _collisionEvents;
115116 QHash<QUuid, EntityDynamicPointer> _objectDynamics;
116117 QHash<btRigidBody*, QSet<QUuid>> _objectDynamicsByBody;
117− std::vector<btRigidBody*> _activeStaticBodies;
118+ std::set<btRigidBody*> _activeStaticBodies;
118119
119120 glm::vec3 _originOffset;
120121
libraries/physics/src/ThreadSafeDynamicsWorld.h+2−0
@@ -51,6 +51,8 @@ public: · 50 unmodified lines
5151 const VectorOfMotionStates& getChangedMotionStates() const { return _changedMotionStates; }
5252 const VectorOfMotionStates& getDeactivatedMotionStates() const { return _deactivatedStates; }
5353
54+ void addChangedMotionState(ObjectMotionState* motionState) { _changedMotionStates.push_back(motionState); }
55+
5456 private:
5557 // call this instead of non-virtual btDiscreteDynamicsWorld::synchronizeSingleMotionState()
5658 void synchronizeMotionState(btRigidBody* body);
tests/networking/src/FileCacheTests.cpp+22−5
@@ -113,18 +113,21 @@ void FileCacheTests::testUnusedFiles() { · 112 unmodified lines
113113 QVERIFY(!file.get());
114114 }
115115
116− QThread::msleep(1000);
117116 // Test files 90 to 99 are present
118117 for (int i = 90; i < 100; ++i) {
119118 std::string key = getFileKey(i);
120119 auto file = cache->getFile(key);
121120 QVERIFY(file.get());
122121 inUseFiles.push_back(file);
123− // Each access touches the file, so we need to sleep here to ensure that the files are
124− // spaced out in numeric order, otherwise later tests can't reliably determine the order
125− // for cache ejection
126− QThread::msleep(1000);
122+
123+ if (i == 94) {
124+ // Each access touches the file, so we need to sleep here to ensure that the the last 5 files
125+ // have later times for cache ejection priority, otherwise the test runs too fast to reliably
126+ // differentiate
127+ QThread::msleep(1000);
128+ }
127129 }
130+
128131 QCOMPARE(cache->getNumCachedFiles(), (size_t)0);
129132 QCOMPARE(cache->getNumTotalFiles(), (size_t)10);
130133 inUseFiles.clear();
@@ -165,6 +168,20 @@ void FileCacheTests::testFreeSpacePreservation() { · 34 unmodified lines
165168 }
166169 }
167170
171+void FileCacheTests::testWipe() {
172+ // Reset the cache
173+ auto cache = makeFileCache(_testDir.path());
174+ QCOMPARE(cache->getNumCachedFiles(), (size_t)5);
175+ QCOMPARE(cache->getNumTotalFiles(), (size_t)5);
176+ cache->wipe();
177+ QCOMPARE(cache->getNumCachedFiles(), (size_t)0);
178+ QCOMPARE(cache->getNumTotalFiles(), (size_t)0);
179+ QVERIFY(getCacheDirectorySize() > 0);
180+ forceDeletes();
181+ QCOMPARE(getCacheDirectorySize(), (size_t)0);
182+}
183+
184+
168185 void FileCacheTests::cleanupTestCase() {
169186 }
170187
tests/networking/src/FileCacheTests.h+1−0
@@ -20,6 +20,7 @@ private slots: · 19 unmodified lines
2020 void testUnusedFiles();
2121 void testFreeSpacePreservation();
2222 void cleanupTestCase();
23+ void testWipe();
2324
2425 private:
2526 size_t getFreeSpace() const;