diff --git a/Sources/Plasma/Apps/plClient/plClient.cpp b/Sources/Plasma/Apps/plClient/plClient.cpp index a22f3259..ce487eb7 100644 --- a/Sources/Plasma/Apps/plClient/plClient.cpp +++ b/Sources/Plasma/Apps/plClient/plClient.cpp @@ -1292,7 +1292,20 @@ void plClient::IProgressMgrCallbackProc(plOperationProgress * progress) return; fInstance->fMessagePumpProc(); - fInstance->IDraw(); + + // HACK HACK HACK HACK! + // Yes, this is the ORIGINAL, EVIL famerate limit from plClient::IDraw (except I bumped it to 60fps) + // As it so happens, this callback is happening in the main resource loading thread + // Without this NASTY ASS HACK, we draw after loading every KO, which starves the loader. + // At some point, a better solution should be found... Like running the loader in a separate thread. + static float lastDrawTime; + static const float kMaxFrameRate = 1.f/60.f; + float currTime = (float) hsTimer::GetSeconds(); + if ((currTime - lastDrawTime) > kMaxFrameRate) + { + fInstance->IDraw(); + lastDrawTime = currTime; + } } //============================================================================ @@ -1838,22 +1851,6 @@ hsBool plClient::IDrawProgress() { hsBool plClient::IDraw() { - // Limit framerate - static float lastDrawTime; - static const float kMaxFrameRate = 1.f/30.f; - float currTime = (float) hsTimer::GetSeconds(); - if (!fPipeline->IsDebugFlagSet(plPipeDbg::kFlagNVPerfHUD)) - { - // If we're using NVPerfHUD to step through draw calls, - // We're going to have a frame delta of zero. In that - // case we need to draw no matter what, and we don't - // care as much about starving other threads because - // we're presumably just debugging a graphics glitch. - if ((currTime - lastDrawTime) < kMaxFrameRate) - return true; - } - lastDrawTime = currTime; - // If we're shutting down, don't attempt to draw. Doing so // tends to cause a device reload each frame. if (fDone) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.h b/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.h index 26cf4d5f..c9fcd27a 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.h @@ -45,8 +45,8 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include // Useful string functions -char* PyString_AsStringEx(PyObject*); -inline bool PyString_CheckEx(PyObject*); +char* PyString_AsStringEx(PyObject* obj); +bool PyString_CheckEx(PyObject* obj); // A set of macros to take at least some of the tediousness out of creating straight python glue code diff --git a/Sources/Plasma/FeatureLib/pfPython/pyStatusLogGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyStatusLogGlue.cpp index a783048d..eaae3843 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyStatusLogGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyStatusLogGlue.cpp @@ -58,21 +58,31 @@ PYTHON_INIT_DEFINITION(ptStatusLog, args, keywords) PYTHON_METHOD_DEFINITION(ptStatusLog, open, args) { - char* logName; + PyObject* logName; unsigned long numLines, flags; - if (!PyArg_ParseTuple(args, "sll", &logName, &numLines, &flags)) + if (!PyArg_ParseTuple(args, "Oll", &logName, &numLines, &flags)) { PyErr_SetString(PyExc_TypeError, "open expects a string and two unsigned longs"); PYTHON_RETURN_ERROR; } - PYTHON_RETURN_BOOL(self->fThis->Open(logName, numLines, flags)); + if (!PyString_CheckEx(logName)) + { + PyErr_SetString(PyExc_TypeError, "open expects a string and two unsigned longs"); + PYTHON_RETURN_ERROR; + } + PYTHON_RETURN_BOOL(self->fThis->Open(PyString_AsStringEx(logName), numLines, flags)); } PYTHON_METHOD_DEFINITION(ptStatusLog, write, args) { - char* text; + PyObject* text; PyObject* colorObj = NULL; - if (!PyArg_ParseTuple(args, "s|O", &text, &colorObj)) + if (!PyArg_ParseTuple(args, "O|O", &text, &colorObj)) + { + PyErr_SetString(PyExc_TypeError, "write expects a string and an optional ptColor"); + PYTHON_RETURN_ERROR; + } + if (!PyString_CheckEx(text)) { PyErr_SetString(PyExc_TypeError, "write expects a string and an optional ptColor"); PYTHON_RETURN_ERROR; @@ -85,9 +95,9 @@ PYTHON_METHOD_DEFINITION(ptStatusLog, write, args) PYTHON_RETURN_ERROR; } pyColor* color = pyColor::ConvertFrom(colorObj); - PYTHON_RETURN_BOOL(self->fThis->WriteColor(text, *color)); + PYTHON_RETURN_BOOL(self->fThis->WriteColor(PyString_AsStringEx(text), *color)); } - PYTHON_RETURN_BOOL(self->fThis->Write(text)); + PYTHON_RETURN_BOOL(self->fThis->Write(PyString_AsStringEx(text))); } PYTHON_BASIC_METHOD_DEFINITION(ptStatusLog, close, Close); diff --git a/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysical.cpp b/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysical.cpp index 2ca77b15..df4770c3 100644 --- a/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysical.cpp +++ b/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysical.cpp @@ -827,7 +827,12 @@ void plPXPhysical::ApplyHitForce() void plPXPhysical::ISetTransformGlobal(const hsMatrix44& l2w) { hsAssert(fActor->isDynamic(), "Shouldn't move a static actor"); - fActor->wakeUp(); + + // If we wake up normal dynamic actors, they might explode. + // However, kinematics won't update if they are asleep. Thankfully, kinematics don't + // explode, move, or cause spontaneous nuclear warfare. + if (fActor->readBodyFlag(NX_BF_KINEMATIC)) + fActor->wakeUp(); NxMat34 mat; diff --git a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp index 20f13ab8..4af7cdf5 100644 --- a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp @@ -56,6 +56,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pnSceneObject/plCoordinateInterface.h" #include "pnNetCommon/plSDLTypes.h" #include "plMessage/plCollideMsg.h" +#include "plMessage/plAgeLoadedMsg.h" #include "plModifier/plDetectorLog.h" @@ -357,7 +358,7 @@ void plSimulationMgr::Init() if (gTheInstance->InitSimulation()) { gTheInstance->RegisterAs(kSimulationMgr_KEY); - gTheInstance->GetKey()->RefObject(); + plgDispatch::Dispatch()->RegisterForExactType(plAgeLoadedMsg::Index(), gTheInstance->GetKey()); } else { @@ -374,10 +375,8 @@ void plSimulationMgr::Shutdown() hsAssert(gTheInstance, "Simulation manager missing during shutdown."); if (gTheInstance) { - // UnRef to match our Ref in Init(). Unless something strange is - // going on, this should destroy the instance and set gTheInstance to nil. -// gTheInstance->GetKey()->UnRefObject(); - gTheInstance->UnRegister(); // this will destroy the instance + plgDispatch::Dispatch()->UnRegisterForExactType(plAgeLoadedMsg::Index(), gTheInstance->GetKey()); + gTheInstance->UnRegisterAs(kSimulationMgr_KEY); // this will destroy the instance gTheInstance = nil; } } @@ -391,8 +390,6 @@ plSimulationMgr* plSimulationMgr::GetInstance() plSimulationMgr::plSimulationMgr() : fSuspended(true) - , fMaxDelta(kDefaultMaxDelta) - , fStepSize(kDefaultStepSize) , fLOSDispatch(new plLOSDispatch()) , fSoundMgr(new plPhysicsSoundMgr) , fLog(nil) @@ -451,16 +448,20 @@ NxScene* plSimulationMgr::GetScene(plKey world) if (!scene) { - uint32_t maxSteps = (uint32_t)ceil(fMaxDelta / fStepSize); - NxSceneDesc sceneDesc; sceneDesc.gravity.set(0, 0, -32.174049f); sceneDesc.userTriggerReport = &gSensorReport; sceneDesc.userContactReport = &gContactReport; - sceneDesc.maxTimestep = fStepSize; - sceneDesc.maxIter = maxSteps; scene = fSDK->createScene(sceneDesc); + // See "Advancing The Simulation State" in the PhysX SDK Documentation + // This will cause PhysX to only update for our step size. If we call simulate + // faster than that, PhysX will return immediately. If we call it slower than that, + // PhysX will do some extra steps for us (isn't that nice?). + // Anyway, this should be a good way to make us independent of the framerate. + // If not, I blame the usual suspects (Tye, eap, etc...) + scene->setTiming(kDefaultStepSize); + // Most physicals use the default friction and restitution values, so we // make them the default. NxMaterial* mat = scene->getMaterialFromIndex(0); @@ -603,12 +604,6 @@ void plSimulationMgr::Advance(float delSecs) if (fSuspended) return; - if (delSecs > fMaxDelta) - { - if (fExtraProfile) - Log("Step clamped from %f to limit of %f", delSecs, fMaxDelta); - delSecs = fMaxDelta; - } plProfile_IncCount(StepLen, (int)(delSecs*1000)); #ifndef PLASMA_EXTERNAL_RELASE @@ -756,6 +751,13 @@ void plSimulationMgr::ISendUpdates() hsBool plSimulationMgr::MsgReceive(plMessage *msg) { + // Suspend/resume the simulation based on whether or not we're in an age... + if (plAgeLoadedMsg* aMsg = plAgeLoadedMsg::ConvertNoRef(msg)) + { + fSuspended = !aMsg->fLoaded; + return true; + } + return hsKeyedObject::MsgReceive(msg); } @@ -765,26 +767,6 @@ hsBool plSimulationMgr::MsgReceive(plMessage *msg) // ///////////////////////////////////////////////////////////////// -void plSimulationMgr::SetMaxDelta(float maxDelta) -{ - fMaxDelta = maxDelta; -} - -float plSimulationMgr::GetMaxDelta() const -{ - return fMaxDelta; -} - -void plSimulationMgr::SetStepsPerSecond(int stepsPerSecond) -{ - fStepSize = 1.0f / (float)stepsPerSecond; -} - -int plSimulationMgr::GetStepsPerSecond() -{ - return (int)((1.0 / fStepSize) + 0.5f); // round to nearest int -} - int plSimulationMgr::GetMaterialIdx(NxScene* scene, float friction, float restitution) { if (friction == 0.5f && restitution == 0.5f) diff --git a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h index d22fc286..2a75d943 100644 --- a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h +++ b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h @@ -115,20 +115,6 @@ protected: plSimulationMgr(); virtual ~plSimulationMgr(); - // Set the maximum amount of time (in seconds) that the physics will advance - // between frames. If a frame-to-frame delta is bigger than this, we'll - // clamp it to this value. - // WARNING: animation doesn't do this, so if we clamp the time animated - // physicals and the avatar may move at a faster rate than usual. - void SetMaxDelta(float maxDelta); - float GetMaxDelta() const; - - // Set the number of steps per second that physics will advance. - // The more steps per second, the less fallthough and more accurate - // simulation response. - void SetStepsPerSecond(int stepsPerSecond); - int GetStepsPerSecond(); - // Walk through the synchronization requests and send them as appropriate. void IProcessSynchs(); @@ -151,9 +137,6 @@ protected: // but nothing will move. bool fSuspended; - float fMaxDelta; - float fStepSize; - // A utility class to keep track of a request for a physical synchronization. // These requests must pass a certain criteria (see the code for the latest) // before they are actually either sent over the network or rejected.