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
2413 2413
2414 // Check HMD use (may be technically available without being in use)2414 // Check HMD use (may be technically available without being in use)
2415 bool hasHMD = PluginUtils::isHMDAvailable();2415 bool hasHMD = PluginUtils::isHMDAvailable();
2416 bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd();2416 bool isUsingHMD = _displayPlugin->isHmd();
2417 bool isUsingHMDAndHandControllers = hasHMD && hasHandControllers && isUsingHMD;
2417 2418
2418 Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false };2419 Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false };
2419 Setting::Handle<bool> firstRun{ Settings::firstRun, true };2420 Setting::Handle<bool> firstRun{ Settings::firstRun, true };
2420 2421
2421 bool isTutorialComplete = tutorialComplete.get();2422 bool isTutorialComplete = tutorialComplete.get();
2422 bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete;2423 bool shouldGoToTutorial = isUsingHMDAndHandControllers && hasTutorialContent && !isTutorialComplete;
2423 2424
2424 qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD;2425 qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers;
2425 qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<2426 qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<
2426 ", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;2427 ", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;
2427 2428
@@ -2435,10 +2436,18 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 7 unmodified lines
2435 2436
2436 const QString TUTORIAL_PATH = "/tutorial_begin";2437 const QString TUTORIAL_PATH = "/tutorial_begin";
2437 2438
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
2438 if (shouldGoToTutorial) {2446 if (shouldGoToTutorial) {
2439 if (sandboxIsRunning) {2447 if (sandboxIsRunning) {
2440 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";2448 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
2441 DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);2449 DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
2450 sentTo = SENT_TO_TUTORIAL;
2442 } else {2451 } else {
2443 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";2452 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
2444 if (firstRun.get()) {2453 if (firstRun.get()) {
@@ -2446,8 +2455,10 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 1 unmodified line
2446 }2455 }
2447 if (addressLookupString.isEmpty()) {2456 if (addressLookupString.isEmpty()) {
2448 DependencyManager::get<AddressManager>()->goToEntry();2457 DependencyManager::get<AddressManager>()->goToEntry();
2458 sentTo = SENT_TO_ENTRY;
2449 } else {2459 } else {
2450 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);2460 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
2461 sentTo = SENT_TO_PREVIOUS_LOCATION;
2451 }2462 }
2452 }2463 }
2453 } else {2464 } else {
@@ -2460,23 +2471,40 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 6 unmodified lines
2460 2471
2461 // If this is a first run we short-circuit the address passed in2472 // If this is a first run we short-circuit the address passed in
2462 if (isFirstRun) {2473 if (isFirstRun) {
2463 if (isUsingHMD) {2474 if (isUsingHMDAndHandControllers) {
2464 if (sandboxIsRunning) {2475 if (sandboxIsRunning) {
2465 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";2476 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
2466 DependencyManager::get<AddressManager>()->goToLocalSandbox();2477 DependencyManager::get<AddressManager>()->goToLocalSandbox();
2478 sentTo = SENT_TO_SANDBOX;
2467 } else {2479 } else {
2468 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";2480 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
2469 DependencyManager::get<AddressManager>()->goToEntry();2481 DependencyManager::get<AddressManager>()->goToEntry();
2482 sentTo = SENT_TO_ENTRY;
2470 }2483 }
2471 } else {2484 } else {
2472 DependencyManager::get<AddressManager>()->goToEntry();2485 DependencyManager::get<AddressManager>()->goToEntry();
2486 sentTo = SENT_TO_ENTRY;
2473 }2487 }
2474 } else {2488 } else {
2475 qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);2489 qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
2476 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);2490 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
2491 sentTo = SENT_TO_PREVIOUS_LOCATION;
2477 }2492 }
2478 }2493 }
2479 2494
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
2480 _connectionMonitor.init();2508 _connectionMonitor.init();
2481 2509
2482 // After all of the constructor is completed, then set firstRun to false.2510 // 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
407#endif407#endif
408 408
409 409
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 }
410 416
411 // Developer > Render > LOD Tools417 // Developer > Render > LOD Tools
412 addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, 0,418 addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, 0,
interface/src/Menu.h+1−0
@@ -145,6 +145,7 @@ namespace MenuOption { · 144 unmodified lines
145 const QString Quit = "Quit";145 const QString Quit = "Quit";
146 const QString ReloadAllScripts = "Reload All Scripts";146 const QString ReloadAllScripts = "Reload All Scripts";
147 const QString ReloadContent = "Reload Content (Clears all caches)";147 const QString ReloadContent = "Reload Content (Clears all caches)";
148 const QString RenderClearKtxCache = "Clear KTX Cache (requires restart)";
148 const QString RenderMaxTextureMemory = "Maximum Texture Memory";149 const QString RenderMaxTextureMemory = "Maximum Texture Memory";
149 const QString RenderMaxTextureAutomatic = "Automatic Texture Memory";150 const QString RenderMaxTextureAutomatic = "Automatic Texture Memory";
150 const QString RenderMaxTexture4MB = "4 MB";151 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
681 // and pretend that we own it (we assume we'll recover it soon)681 // and pretend that we own it (we assume we'll recover it soon)
682 682
683 // However, for now, when the server uses a newer time than what we sent, listen to what we're told.683 // 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 }
685 } else if (_simulationOwner.set(newSimOwner)) {687 } else if (_simulationOwner.set(newSimOwner)) {
686 markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);688 markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
687 somethingChanged = true;689 somethingChanged = true;
@@ -1293,27 +1295,15 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c · 605 unmodified lines
1293 properties._accelerationChanged = true;1295 properties._accelerationChanged = true;
1294}1296}
1295 1297
1296void EntityItem::pokeSimulationOwnership() {1298void EntityItem::flagForOwnershipBid(uint8_t priority) {
1297 markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE);1299 markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY);
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
1308void EntityItem::grabSimulationOwnership() {
1309 markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB);
1310 auto nodeList = DependencyManager::get<NodeList>();1300 auto nodeList = DependencyManager::get<NodeList>();
1311 if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {1301 if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
1312 // we already own it1302 // we already own it
1313 _simulationOwner.promotePriority(SCRIPT_GRAB_SIMULATION_PRIORITY);1303 _simulationOwner.promotePriority(priority);
1314 } else {1304 } else {
1315 // we don't own it yet1305 // we don't own it yet
1316 _simulationOwner.setPendingPriority(SCRIPT_GRAB_SIMULATION_PRIORITY, usecTimestampNow());1306 _simulationOwner.setPendingPriority(priority, usecTimestampNow());
1317 }1307 }
1318}1308}
1319 1309
libraries/entities/src/EntityItem.h+2−2
@@ -321,6 +321,7 @@ public: · 320 unmodified lines
321 void updateSimulationOwner(const SimulationOwner& owner);321 void updateSimulationOwner(const SimulationOwner& owner);
322 void clearSimulationOwnership();322 void clearSimulationOwnership();
323 void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp);323 void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp);
324 uint8_t getPendingOwnershipPriority() const { return _simulationOwner.getPendingPriority(); }
324 void rememberHasSimulationOwnershipBid() const;325 void rememberHasSimulationOwnershipBid() const;
325 326
326 QString getMarketplaceID() const;327 QString getMarketplaceID() const;
@@ -394,8 +395,7 @@ public: · 67 unmodified lines
394 395
395 void getAllTerseUpdateProperties(EntityItemProperties& properties) const;396 void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
396 397
397 void pokeSimulationOwnership();398 void flagForOwnershipBid(uint8_t priority);
398 void grabSimulationOwnership();
399 void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; }399 void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; }
400 400
401 QString actionsToDebugString();401 QString actionsToDebugString();
libraries/entities/src/EntityScriptingInterface.cpp+6−4
@@ -230,6 +230,8 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties · 229 unmodified lines
230 }230 }
231 231
232 entity->setLastBroadcast(usecTimestampNow());232 entity->setLastBroadcast(usecTimestampNow());
233 // since we're creating this object we will immediately volunteer to own its simulation
234 entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY);
233 propertiesWithSimID.setLastEdited(entity->getLastEdited());235 propertiesWithSimID.setLastEdited(entity->getLastEdited());
234 } else {236 } else {
235 qCDebug(entities) << "script failed to add new Entity to local Octree";237 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
440 } else {442 } else {
441 // we make a bid for simulation ownership443 // we make a bid for simulation ownership
442 properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY);444 properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY);
443 entity->pokeSimulationOwnership();445 entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY);
444 entity->rememberHasSimulationOwnershipBid();446 entity->rememberHasSimulationOwnershipBid();
445 }447 }
446 }448 }
@@ -1194,7 +1196,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, · 747 unmodified lines
1194 }1196 }
1195 action->setIsMine(true);1197 action->setIsMine(true);
1196 success = entity->addAction(simulation, action);1198 success = entity->addAction(simulation, action);
1197 entity->grabSimulationOwnership();1199 entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY);
1198 return false; // Physics will cause a packet to be sent, so don't send from here.1200 return false; // Physics will cause a packet to be sent, so don't send from here.
1199 });1201 });
1200 if (success) {1202 if (success) {
@@ -1210,7 +1212,7 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid& · 9 unmodified lines
1210 return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) {1212 return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) {
1211 bool success = entity->updateAction(simulation, actionID, arguments);1213 bool success = entity->updateAction(simulation, actionID, arguments);
1212 if (success) {1214 if (success) {
1213 entity->grabSimulationOwnership();1215 entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY);
1214 }1216 }
1215 return success;1217 return success;
1216 });1218 });
@@ -1224,7 +1226,7 @@ bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid& · 7 unmodified lines
1224 success = entity->removeAction(simulation, actionID);1226 success = entity->removeAction(simulation, actionID);
1225 if (success) {1227 if (success) {
1226 // reduce from grab to poke1228 // reduce from grab to poke
1227 entity->pokeSimulationOwnership();1229 entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY);
1228 }1230 }
1229 return false; // Physics will cause a packet to be sent, so don't send from here.1231 return false; // Physics will cause a packet to be sent, so don't send from here.
1230 });1232 });
libraries/entities/src/SimulationFlags.h+1−3
@@ -26,12 +26,10 @@ namespace Simulation { · 25 unmodified lines
26 const uint32_t DIRTY_MATERIAL = 0x00400;26 const uint32_t DIRTY_MATERIAL = 0x00400;
27 const uint32_t DIRTY_PHYSICS_ACTIVATION = 0x0800; // should activate object in physics engine27 const uint32_t DIRTY_PHYSICS_ACTIVATION = 0x0800; // should activate object in physics engine
28 const uint32_t DIRTY_SIMULATOR_ID = 0x1000; // the simulatorID has changed28 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"29 const uint32_t DIRTY_SIMULATION_OWNERSHIP_PRIORITY = 0x2000; // our own bid priority has changed
30 const uint32_t DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB = 0x4000; // bid for simulation ownership at "grab"
31 30
32 const uint32_t DIRTY_TRANSFORM = DIRTY_POSITION | DIRTY_ROTATION;31 const uint32_t DIRTY_TRANSFORM = DIRTY_POSITION | DIRTY_ROTATION;
33 const uint32_t DIRTY_VELOCITIES = DIRTY_LINEAR_VELOCITY | DIRTY_ANGULAR_VELOCITY;32 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;
35};33};
36 34
37#endif // hifi_SimulationFlags_h35#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
26SimulationOwner::SimulationOwner() :26SimulationOwner::SimulationOwner() :
27 _id(),27 _id(),
28 _expiry(0),28 _expiry(0),
29 _pendingTimestamp(0),29 _pendingBidTimestamp(0),
30 _priority(0),30 _priority(0),
31 _pendingPriority(0),31 _pendingBidPriority(0),
32 _pendingState(PENDING_STATE_NOTHING)32 _pendingState(PENDING_STATE_NOTHING)
33{33{
34}34}
@@ -36,9 +36,9 @@ SimulationOwner::SimulationOwner() : · 1 unmodified line
36SimulationOwner::SimulationOwner(const QUuid& id, quint8 priority) :36SimulationOwner::SimulationOwner(const QUuid& id, quint8 priority) :
37 _id(id),37 _id(id),
38 _expiry(0),38 _expiry(0),
39 _pendingTimestamp(0),39 _pendingBidTimestamp(0),
40 _priority(priority),40 _priority(priority),
41 _pendingPriority(0)41 _pendingBidPriority(0)
42{42{
43}43}
44 44
@@ -61,9 +61,9 @@ bool SimulationOwner::fromByteArray(const QByteArray& data) { · 16 unmodified lines
61void SimulationOwner::clear() {61void SimulationOwner::clear() {
62 _id = QUuid();62 _id = QUuid();
63 _expiry = 0;63 _expiry = 0;
64 _pendingTimestamp = 0;64 _pendingBidTimestamp = 0;
65 _priority = 0;65 _priority = 0;
66 _pendingPriority = 0;66 _pendingBidPriority = 0;
67 _pendingState = PENDING_STATE_NOTHING;67 _pendingState = PENDING_STATE_NOTHING;
68}68}
69 69
@@ -102,9 +102,9 @@ bool SimulationOwner::set(const SimulationOwner& owner) { · 32 unmodified lines
102}102}
103 103
104void SimulationOwner::setPendingPriority(quint8 priority, const quint64& timestamp) {104void SimulationOwner::setPendingPriority(quint8 priority, const quint64& timestamp) {
105 _pendingPriority = priority;105 _pendingBidPriority = priority;
106 _pendingTimestamp = timestamp;106 _pendingBidTimestamp = timestamp;
107 _pendingState = (_pendingPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE;107 _pendingState = (_pendingBidPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE;
108}108}
109 109
110void SimulationOwner::updateExpiry() {110void SimulationOwner::updateExpiry() {
@@ -113,11 +113,11 @@ void SimulationOwner::updateExpiry() { · 2 unmodified lines
113}113}
114 114
115bool SimulationOwner::pendingRelease(const quint64& timestamp) {115bool 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;
117}117}
118 118
119bool SimulationOwner::pendingTake(const quint64& timestamp) {119bool 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;
121}121}
122 122
123void SimulationOwner::clearCurrentOwner() {123void SimulationOwner::clearCurrentOwner() {
libraries/entities/src/SimulationOwner.h+3−2
@@ -66,6 +66,7 @@ public: · 65 unmodified lines
66 66
67 bool hasExpired() const { return usecTimestampNow() > _expiry; }67 bool hasExpired() const { return usecTimestampNow() > _expiry; }
68 68
69 uint8_t getPendingPriority() const { return _pendingBidPriority; }
69 bool pendingRelease(const quint64& timestamp); // return true if valid pending RELEASE70 bool pendingRelease(const quint64& timestamp); // return true if valid pending RELEASE
70 bool pendingTake(const quint64& timestamp); // return true if valid pending TAKE71 bool pendingTake(const quint64& timestamp); // return true if valid pending TAKE
71 void clearCurrentOwner();72 void clearCurrentOwner();
@@ -84,9 +85,9 @@ public: · 12 unmodified lines
84private:85private:
85 QUuid _id; // owner86 QUuid _id; // owner
86 quint64 _expiry; // time when ownership can transition at equal priority87 quint64 _expiry; // time when ownership can transition at equal priority
87 quint64 _pendingTimestamp; // time when pending update was set88 quint64 _pendingBidTimestamp; // time when pending bid was set
88 quint8 _priority; // priority of current owner89 quint8 _priority; // priority of current owner
89 quint8 _pendingPriority; // priority of pendingTake90 quint8 _pendingBidPriority; // priority at which we'd like to own it
90 quint8 _pendingState; // NOTHING, TAKE, or RELEASE91 quint8 _pendingState; // NOTHING, TAKE, or RELEASE
91};92};
92 93
libraries/model-networking/src/model-networking/KTXCache.cpp+14−0
@@ -11,14 +11,28 @@ · 10 unmodified lines
11 11
12#include "KTXCache.h"12#include "KTXCache.h"
13 13
14#include <SettingHandle.h>
14#include <ktx/KTX.h>15#include <ktx/KTX.h>
15 16
16using File = cache::File;17using File = cache::File;
17using FilePointer = cache::FilePointer;18using FilePointer = cache::FilePointer;
18 19
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
22const int KTXCache::CURRENT_VERSION = 0x01;
23const int KTXCache::INVALID_VERSION = 0x00;
24const char* KTXCache::SETTING_VERSION_NAME = "hifi.ktx.cache_version";
25
19KTXCache::KTXCache(const std::string& dir, const std::string& ext) :26KTXCache::KTXCache(const std::string& dir, const std::string& ext) :
20 FileCache(dir, ext) {27 FileCache(dir, ext) {
21 initialize();28 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 }
22}36}
23 37
24KTXFilePointer KTXCache::writeFile(const char* data, Metadata&& metadata) {38KTXFilePointer 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
27 Q_OBJECT27 Q_OBJECT
28 28
29public:29public:
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
30 KTXCache(const std::string& dir, const std::string& ext);36 KTXCache(const std::string& dir, const std::string& ext);
31 37
32 KTXFilePointer writeFile(const char* data, Metadata&& metadata);38 KTXFilePointer writeFile(const char* data, Metadata&& metadata);
libraries/networking/src/FileCache.cpp+31−14
@@ -236,6 +236,28 @@ namespace cache { · 235 unmodified lines
236 };236 };
237}237}
238 238
239void 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
239void FileCache::clean() {261void FileCache::clean() {
240 size_t overbudgetAmount = getOverbudgetAmount();262 size_t overbudgetAmount = getOverbudgetAmount();
241 263
@@ -250,28 +272,23 @@ void FileCache::clean() { · 8 unmodified lines
250 for (const auto& file : _unusedFiles) {272 for (const auto& file : _unusedFiles) {
251 queue.push(file);273 queue.push(file);
252 }274 }
275
253 while (!queue.empty() && overbudgetAmount > 0) {276 while (!queue.empty() && overbudgetAmount > 0) {
254 auto file = queue.top();277 auto file = queue.top();
255 queue.pop();278 queue.pop();
279 eject(file);
256 auto length = file->getLength();280 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;
271 overbudgetAmount -= std::min(length, overbudgetAmount);281 overbudgetAmount -= std::min(length, overbudgetAmount);
272 }282 }
273}283}
274 284
285void FileCache::wipe() {
286 Lock unusedFilesLock(_unusedFilesMutex);
287 while (!_unusedFiles.empty()) {
288 eject(*_unusedFiles.begin());
289 }
290}
291
275void FileCache::clear() {292void FileCache::clear() {
276 // Eliminate any overbudget files293 // Eliminate any overbudget files
277 clean();294 clean();
libraries/networking/src/FileCache.h+12−4
@@ -46,6 +46,9 @@ public: · 45 unmodified lines
46 FileCache(const std::string& dirname, const std::string& ext, QObject* parent = nullptr);46 FileCache(const std::string& dirname, const std::string& ext, QObject* parent = nullptr);
47 virtual ~FileCache();47 virtual ~FileCache();
48 48
49 // Remove all unlocked items from the cache
50 void wipe();
51
49 size_t getNumTotalFiles() const { return _numTotalFiles; }52 size_t getNumTotalFiles() const { return _numTotalFiles; }
50 size_t getNumCachedFiles() const { return _numUnusedFiles; }53 size_t getNumCachedFiles() const { return _numUnusedFiles; }
51 size_t getSizeTotalFiles() const { return _totalFilesSize; }54 size_t getSizeTotalFiles() const { return _totalFilesSize; }
@@ -95,6 +98,9 @@ public: · 43 unmodified lines
95private:98private:
96 using Mutex = std::recursive_mutex;99 using Mutex = std::recursive_mutex;
97 using Lock = std::unique_lock<Mutex>;100 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>;
98 104
99 friend class File;105 friend class File;
100 106
@@ -105,6 +111,8 @@ private: · 4 unmodified lines
105 void removeUnusedFile(const FilePointer& file);111 void removeUnusedFile(const FilePointer& file);
106 void clean();112 void clean();
107 void clear();113 void clear();
114 // Remove a file from the cache
115 void eject(const FilePointer& file);
108 116
109 size_t getOverbudgetAmount() const;117 size_t getOverbudgetAmount() const;
110 118
@@ -122,10 +130,10 @@ private: · 11 unmodified lines
122 std::string _dirpath;130 std::string _dirpath;
123 bool _initialized { false };131 bool _initialized { false };
124 132
125 std::unordered_map<Key, std::weak_ptr<File>> _files;133 Map _files;
126 Mutex _filesMutex;134 Mutex _filesMutex;
127 135
128 std::unordered_set<FilePointer> _unusedFiles;136 Set _unusedFiles;
129 Mutex _unusedFilesMutex;137 Mutex _unusedFilesMutex;
130};138};
131 139
@@ -136,8 +144,8 @@ public: · 4 unmodified lines
136 using Key = FileCache::Key;144 using Key = FileCache::Key;
137 using Metadata = FileCache::Metadata;145 using Metadata = FileCache::Metadata;
138 146
139 Key getKey() const { return _key; }147 const Key& getKey() const { return _key; }
140 size_t getLength() const { return _length; }148 const size_t& getLength() const { return _length; }
141 std::string getFilepath() const { return _filepath; }149 std::string getFilepath() const { return _filepath; }
142 150
143 virtual ~File();151 virtual ~File();
libraries/physics/src/EntityMotionState.cpp+20−15
@@ -65,8 +65,7 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer · 64 unmodified lines
65 _lastStep(0),65 _lastStep(0),
66 _loopsWithoutOwner(0),66 _loopsWithoutOwner(0),
67 _accelerationNearlyGravityCount(0),67 _accelerationNearlyGravityCount(0),
68 _numInactiveUpdates(1),68 _numInactiveUpdates(1)
69 _outgoingPriority(0)
70{69{
71 _type = MOTIONSTATE_TYPE_ENTITY;70 _type = MOTIONSTATE_TYPE_ENTITY;
72 assert(_entity);71 assert(_entity);
@@ -75,6 +74,8 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer · 2 unmodified lines
75 // we need the side-effects of EntityMotionState::setShape() so we call it explicitly here74 // we need the side-effects of EntityMotionState::setShape() so we call it explicitly here
76 // rather than pass the legit shape pointer to the ObjectMotionState ctor above.75 // rather than pass the legit shape pointer to the ObjectMotionState ctor above.
77 setShape(shape);76 setShape(shape);
77
78 _outgoingPriority = _entity->getPendingOwnershipPriority();
78}79}
79 80
80EntityMotionState::~EntityMotionState() {81EntityMotionState::~EntityMotionState() {
@@ -84,7 +85,7 @@ EntityMotionState::~EntityMotionState() { · 3 unmodified lines
84 85
85void EntityMotionState::updateServerPhysicsVariables() {86void EntityMotionState::updateServerPhysicsVariables() {
86 assert(entityTreeIsLocked());87 assert(entityTreeIsLocked());
87 if (_entity->getSimulatorID() == Physics::getSessionUUID()) {88 if (isLocallyOwned()) {
88 // don't slam these values if we are the simulation owner89 // don't slam these values if we are the simulation owner
89 return;90 return;
90 }91 }
@@ -136,23 +137,23 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) { · 45 unmodified lines
136 _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;137 _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
137 }138 }
138 _loopsWithoutOwner = 0;139 _loopsWithoutOwner = 0;
139 } else if (_entity->getSimulatorID() == Physics::getSessionUUID()) {140 _numInactiveUpdates = 0;
141 } else if (isLocallyOwned()) {
140 // we just inherited ownership, make sure our desired priority matches what we have142 // we just inherited ownership, make sure our desired priority matches what we have
141 upgradeOutgoingPriority(_entity->getSimulationPriority());143 upgradeOutgoingPriority(_entity->getSimulationPriority());
142 } else {144 } else {
143 _outgoingPriority = 0;145 _outgoingPriority = 0;
144 _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;146 _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
147 _numInactiveUpdates = 0;
145 }148 }
146 }149 }
147 if (flags & Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY) {150 if (flags & Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY) {
148 // The DIRTY_SIMULATOR_OWNERSHIP_PRIORITY bits really mean "we should bid for ownership because151 // The DIRTY_SIMULATOR_OWNERSHIP_PRIORITY bit means one of the following:
149 // a local script has been changing physics properties, or we should adjust our own ownership priority".152 // (1) we own it but may need to change the priority OR...
150 // The desired priority is determined by which bits were set.153 // (2) we don't own it but should bid (because a local script has been changing physics properties)
151 if (flags & Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB) {154 uint8_t newPriority = isLocallyOwned() ? _entity->getSimulationOwner().getPriority() : _entity->getSimulationOwner().getPendingPriority();
152 _outgoingPriority = SCRIPT_GRAB_SIMULATION_PRIORITY;155 _outgoingPriority = glm::max(_outgoingPriority, newPriority);
153 } else {156
154 _outgoingPriority = SCRIPT_POKE_SIMULATION_PRIORITY;
155 }
156 // reset bid expiry so that we bid ASAP157 // reset bid expiry so that we bid ASAP
157 _nextOwnershipBid = 0;158 _nextOwnershipBid = 0;
158 }159 }
@@ -317,7 +318,7 @@ bool EntityMotionState::isCandidateForOwnership() const { · 158 unmodified lines
317 assert(_entity);318 assert(_entity);
318 assert(entityTreeIsLocked());319 assert(entityTreeIsLocked());
319 return _outgoingPriority != 0320 return _outgoingPriority != 0
320 || Physics::getSessionUUID() == _entity->getSimulatorID()321 || isLocallyOwned()
321 || _entity->dynamicDataNeedsTransmit();322 || _entity->dynamicDataNeedsTransmit();
322}323}
323 324
@@ -491,7 +492,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { · 167 unmodified lines
491 return true;492 return true;
492 }493 }
493 494
494 if (_entity->getSimulatorID() != Physics::getSessionUUID()) {495 if (!isLocallyOwned()) {
495 // we don't own the simulation496 // we don't own the simulation
496 497
497 // NOTE: we do not volunteer to own kinematic or static objects498 // NOTE: we do not volunteer to own kinematic or static objects
@@ -599,7 +600,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ · 101 unmodified lines
599 properties.clearSimulationOwner();600 properties.clearSimulationOwner();
600 _outgoingPriority = 0;601 _outgoingPriority = 0;
601 _entity->setPendingOwnershipPriority(_outgoingPriority, now);602 _entity->setPendingOwnershipPriority(_outgoingPriority, now);
602 } else if (Physics::getSessionUUID() != _entity->getSimulatorID()) {603 } else if (!isLocallyOwned()) {
603 // we don't own the simulation for this entity yet, but we're sending a bid for it604 // we don't own the simulation for this entity yet, but we're sending a bid for it
604 quint8 bidPriority = glm::max<uint8_t>(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY);605 quint8 bidPriority = glm::max<uint8_t>(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY);
605 properties.setSimulationOwner(Physics::getSessionUUID(), bidPriority);606 properties.setSimulationOwner(Physics::getSessionUUID(), bidPriority);
@@ -788,6 +789,10 @@ void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma · 182 unmodified lines
788 _entity->computeCollisionGroupAndFinalMask(group, mask);789 _entity->computeCollisionGroupAndFinalMask(group, mask);
789}790}
790 791
792bool EntityMotionState::isLocallyOwned() const {
793 return _entity->getSimulatorID() == Physics::getSessionUUID();
794}
795
791bool EntityMotionState::shouldBeLocallyOwned() const {796bool EntityMotionState::shouldBeLocallyOwned() const {
792 return (_outgoingPriority > VOLUNTEER_SIMULATION_PRIORITY && _outgoingPriority > _entity->getSimulationPriority()) ||797 return (_outgoingPriority > VOLUNTEER_SIMULATION_PRIORITY && _outgoingPriority > _entity->getSimulationPriority()) ||
793 _entity->getSimulatorID() == Physics::getSessionUUID();798 _entity->getSimulatorID() == Physics::getSessionUUID();
libraries/physics/src/EntityMotionState.h+1−0
@@ -79,6 +79,7 @@ public: · 78 unmodified lines
79 79
80 virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;80 virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;
81 81
82 bool isLocallyOwned() const override;
82 bool shouldBeLocallyOwned() const override;83 bool shouldBeLocallyOwned() const override;
83 84
84 friend class PhysicalEntitySimulation;85 friend class PhysicalEntitySimulation;
libraries/physics/src/ObjectMotionState.h+1−0
@@ -146,6 +146,7 @@ public: · 145 unmodified lines
146 void dirtyInternalKinematicChanges() { _hasInternalKinematicChanges = true; }146 void dirtyInternalKinematicChanges() { _hasInternalKinematicChanges = true; }
147 void clearInternalKinematicChanges() { _hasInternalKinematicChanges = false; }147 void clearInternalKinematicChanges() { _hasInternalKinematicChanges = false; }
148 148
149 virtual bool isLocallyOwned() const { return false; }
149 virtual bool shouldBeLocallyOwned() const { return false; }150 virtual bool shouldBeLocallyOwned() const { return false; }
150 151
151 friend class PhysicsEngine;152 friend class PhysicsEngine;
libraries/physics/src/PhysicsEngine.cpp+24−19
@@ -129,6 +129,9 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { · 128 unmodified lines
129 }129 }
130 body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);130 body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
131 body->updateInertiaTensor();131 body->updateInertiaTensor();
132 if (motionState->isLocallyOwned()) {
133 _activeStaticBodies.insert(body);
134 }
132 break;135 break;
133 }136 }
134 }137 }
@@ -174,19 +177,9 @@ void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) { · 39 unmodified lines
174 // frame (because the framerate is faster than our physics simulation rate). When this happens we must scan177 // frame (because the framerate is faster than our physics simulation rate). When this happens we must scan
175 // _activeStaticBodies for objects that were recently deleted so we don't try to access a dangling pointer.178 // _activeStaticBodies for objects that were recently deleted so we don't try to access a dangling pointer.
176 for (auto object : objects) {179 for (auto object : objects) {
177 btRigidBody* body = object->getRigidBody();180 std::set<btRigidBody*>::iterator itr = _activeStaticBodies.find(object->getRigidBody());
178 181 if (itr != _activeStaticBodies.end()) {
179 std::vector<btRigidBody*>::reverse_iterator itr = _activeStaticBodies.rbegin();182 _activeStaticBodies.erase(itr);
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;
190 }183 }
191 }184 }
192 }185 }
@@ -245,14 +238,16 @@ VectorOfMotionStates PhysicsEngine::changeObjects(const VectorOfMotionStates& ob · 52 unmodified lines
245 object->clearIncomingDirtyFlags();238 object->clearIncomingDirtyFlags();
246 }239 }
247 if (object->getMotionType() == MOTION_TYPE_STATIC && object->isActive()) {240 if (object->getMotionType() == MOTION_TYPE_STATIC && object->isActive()) {
248 _activeStaticBodies.push_back(object->getRigidBody());241 _activeStaticBodies.insert(object->getRigidBody());
249 }242 }
250 }243 }
251 // active static bodies have changed (in an Easy way) and need their Aabbs updated244 // active static bodies have changed (in an Easy way) and need their Aabbs updated
252 // but we've configured Bullet to NOT update them automatically (for improved performance)245 // but we've configured Bullet to NOT update them automatically (for improved performance)
253 // so we must do it ourselves246 // so we must do it ourselves
254 for (size_t i = 0; i < _activeStaticBodies.size(); ++i) {247 std::set<btRigidBody*>::const_iterator itr = _activeStaticBodies.begin();
255 _dynamicsWorld->updateSingleAabb(_activeStaticBodies[i]);248 while (itr != _activeStaticBodies.end()) {
249 _dynamicsWorld->updateSingleAabb(*itr);
250 ++itr;
256 }251 }
257 return stillNeedChange;252 return stillNeedChange;
258}253}
@@ -496,13 +491,23 @@ const CollisionEvents& PhysicsEngine::getCollisionEvents() { · 237 unmodified lines
496 491
497const VectorOfMotionStates& PhysicsEngine::getChangedMotionStates() {492const VectorOfMotionStates& PhysicsEngine::getChangedMotionStates() {
498 BT_PROFILE("copyOutgoingChanges");493 BT_PROFILE("copyOutgoingChanges");
494
495 _dynamicsWorld->synchronizeMotionStates();
496
499 // Bullet will not deactivate static objects (it doesn't expect them to be active)497 // Bullet will not deactivate static objects (it doesn't expect them to be active)
500 // so we must deactivate them ourselves498 // so we must deactivate them ourselves
501 for (size_t i = 0; i < _activeStaticBodies.size(); ++i) {499 std::set<btRigidBody*>::const_iterator itr = _activeStaticBodies.begin();
502 _activeStaticBodies[i]->forceActivationState(ISLAND_SLEEPING);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;
503 }508 }
504 _activeStaticBodies.clear();509 _activeStaticBodies.clear();
505 _dynamicsWorld->synchronizeMotionStates();510
506 _hasOutgoingChanges = false;511 _hasOutgoingChanges = false;
507 return _dynamicsWorld->getChangedMotionStates();512 return _dynamicsWorld->getChangedMotionStates();
508}513}
libraries/physics/src/PhysicsEngine.h+2−1
@@ -13,6 +13,7 @@ · 12 unmodified lines
13#define hifi_PhysicsEngine_h13#define hifi_PhysicsEngine_h
14 14
15#include <stdint.h>15#include <stdint.h>
16#include <set>
16#include <vector>17#include <vector>
17 18
18#include <QUuid>19#include <QUuid>
@@ -114,7 +115,7 @@ private: · 95 unmodified lines
114 CollisionEvents _collisionEvents;115 CollisionEvents _collisionEvents;
115 QHash<QUuid, EntityDynamicPointer> _objectDynamics;116 QHash<QUuid, EntityDynamicPointer> _objectDynamics;
116 QHash<btRigidBody*, QSet<QUuid>> _objectDynamicsByBody;117 QHash<btRigidBody*, QSet<QUuid>> _objectDynamicsByBody;
117 std::vector<btRigidBody*> _activeStaticBodies;118 std::set<btRigidBody*> _activeStaticBodies;
118 119
119 glm::vec3 _originOffset;120 glm::vec3 _originOffset;
120 121
libraries/physics/src/ThreadSafeDynamicsWorld.h+2−0
@@ -51,6 +51,8 @@ public: · 50 unmodified lines
51 const VectorOfMotionStates& getChangedMotionStates() const { return _changedMotionStates; }51 const VectorOfMotionStates& getChangedMotionStates() const { return _changedMotionStates; }
52 const VectorOfMotionStates& getDeactivatedMotionStates() const { return _deactivatedStates; }52 const VectorOfMotionStates& getDeactivatedMotionStates() const { return _deactivatedStates; }
53 53
54 void addChangedMotionState(ObjectMotionState* motionState) { _changedMotionStates.push_back(motionState); }
55
54private:56private:
55 // call this instead of non-virtual btDiscreteDynamicsWorld::synchronizeSingleMotionState()57 // call this instead of non-virtual btDiscreteDynamicsWorld::synchronizeSingleMotionState()
56 void synchronizeMotionState(btRigidBody* body);58 void synchronizeMotionState(btRigidBody* body);
tests/networking/src/FileCacheTests.cpp+22−5
@@ -113,18 +113,21 @@ void FileCacheTests::testUnusedFiles() { · 112 unmodified lines
113 QVERIFY(!file.get());113 QVERIFY(!file.get());
114 }114 }
115 115
116 QThread::msleep(1000);
117 // Test files 90 to 99 are present116 // Test files 90 to 99 are present
118 for (int i = 90; i < 100; ++i) {117 for (int i = 90; i < 100; ++i) {
119 std::string key = getFileKey(i);118 std::string key = getFileKey(i);
120 auto file = cache->getFile(key);119 auto file = cache->getFile(key);
121 QVERIFY(file.get());120 QVERIFY(file.get());
122 inUseFiles.push_back(file);121 inUseFiles.push_back(file);
123 // Each access touches the file, so we need to sleep here to ensure that the files are 122
124 // spaced out in numeric order, otherwise later tests can't reliably determine the order 123 if (i == 94) {
125 // for cache ejection124 // Each access touches the file, so we need to sleep here to ensure that the the last 5 files
126 QThread::msleep(1000);125 // have later times for cache ejection priority, otherwise the test runs too fast to reliably
126 // differentiate
127 QThread::msleep(1000);
128 }
127 }129 }
130
128 QCOMPARE(cache->getNumCachedFiles(), (size_t)0);131 QCOMPARE(cache->getNumCachedFiles(), (size_t)0);
129 QCOMPARE(cache->getNumTotalFiles(), (size_t)10);132 QCOMPARE(cache->getNumTotalFiles(), (size_t)10);
130 inUseFiles.clear();133 inUseFiles.clear();
@@ -165,6 +168,20 @@ void FileCacheTests::testFreeSpacePreservation() { · 34 unmodified lines
165 }168 }
166}169}
167 170
171void 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
168void FileCacheTests::cleanupTestCase() {185void FileCacheTests::cleanupTestCase() {
169}186}
170 187
tests/networking/src/FileCacheTests.h+1−0
@@ -20,6 +20,7 @@ private slots: · 19 unmodified lines
20 void testUnusedFiles();20 void testUnusedFiles();
21 void testFreeSpacePreservation();21 void testFreeSpacePreservation();
22 void cleanupTestCase();22 void cleanupTestCase();
23 void testWipe();
23 24
24private:25private:
25 size_t getFreeSpace() const;26 size_t getFreeSpace() const;