From e2b9bba70c7989449ce3323345df25a6d4079f72 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 4 Feb 2012 17:57:22 -0500 Subject: [PATCH 1/6] ptStatusLog now supports unicode objects and string objects --- .../FeatureLib/pfPython/pyGlueHelpers.h | 4 ++-- .../FeatureLib/pfPython/pyStatusLogGlue.cpp | 24 +++++++++++++------ 2 files changed, 19 insertions(+), 9 deletions(-) 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); From 33dbdce2f113ea63162124d1e5eb13c743537f8a Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 6 Feb 2012 18:49:37 -0500 Subject: [PATCH 2/6] Really fix those bizarre panic links Looks like Cyan never actually stopped simulating, so we simulate through adding objects to the scene and positioning them. This is a bad thing(TM), so now we suspend/resume the simulation on plAgeLoadedMsg. --- Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp index e68d1544..b8d89793 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" @@ -358,6 +359,7 @@ void plSimulationMgr::Init() { gTheInstance->RegisterAs(kSimulationMgr_KEY); gTheInstance->GetKey()->RefObject(); + plgDispatch::Dispatch()->RegisterForExactType(plAgeLoadedMsg::Index(), gTheInstance->GetKey()); } else { @@ -377,6 +379,7 @@ void plSimulationMgr::Shutdown() // 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(); + plgDispatch::Dispatch()->UnRegisterForExactType(plAgeLoadedMsg::Index(), gTheInstance->GetKey()); gTheInstance->UnRegister(); // this will destroy the instance gTheInstance = nil; } @@ -756,6 +759,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); } From 8cbde377efa7e8b4a2159dba28fe107bcb6dbfe0 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 6 Feb 2012 21:17:08 -0500 Subject: [PATCH 3/6] Fix an obvious memory leak. This thing was pissing me off, which made me piss off a lot of other people, which pissed off even more people, so the entire planet got pissed off and nuclear warfare began. So, let's not do stupid crap and piss me off, okay? --- Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp index b8d89793..c4367b3d 100644 --- a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp @@ -358,7 +358,6 @@ void plSimulationMgr::Init() if (gTheInstance->InitSimulation()) { gTheInstance->RegisterAs(kSimulationMgr_KEY); - gTheInstance->GetKey()->RefObject(); plgDispatch::Dispatch()->RegisterForExactType(plAgeLoadedMsg::Index(), gTheInstance->GetKey()); } else @@ -376,11 +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(); plgDispatch::Dispatch()->UnRegisterForExactType(plAgeLoadedMsg::Index(), gTheInstance->GetKey()); - gTheInstance->UnRegister(); // this will destroy the instance + gTheInstance->UnRegisterAs(kSimulationMgr_KEY); // this will destroy the instance gTheInstance = nil; } } From 54b5e4cf249949bac65c83673f72df10c1d1007e Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 6 Feb 2012 21:44:13 -0500 Subject: [PATCH 4/6] Fix Gira basket explosions Tweak the GZ marker detector region fix to only wake up kinematic detector regions... waking up regular dynamic actors before we position them causes bad things to happen. --- Sources/Plasma/PubUtilLib/plPhysX/plPXPhysical.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysical.cpp b/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysical.cpp index 37fb721f..17a95259 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; From d4dabfb047d81a4c6f5714488585799311af59eb Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Thu, 9 Feb 2012 00:21:41 -0500 Subject: [PATCH 5/6] That looks dangerous... PhysX is nicely capable of clamping for us without those nasty hacks, so let's allow PhysX to do it for us. Hopefully, this will keep anything too insane from happening when I disable the framerate limit. --- .../PubUtilLib/plPhysX/plSimulationMgr.cpp | 40 ++++--------------- .../PubUtilLib/plPhysX/plSimulationMgr.h | 17 -------- 2 files changed, 8 insertions(+), 49 deletions(-) diff --git a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp index c4367b3d..a979aae1 100644 --- a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp @@ -390,8 +390,6 @@ plSimulationMgr* plSimulationMgr::GetInstance() plSimulationMgr::plSimulationMgr() : fSuspended(true) - , fMaxDelta(kDefaultMaxDelta) - , fStepSize(kDefaultStepSize) , fLOSDispatch(new plLOSDispatch()) , fSoundMgr(new plPhysicsSoundMgr) , fLog(nil) @@ -450,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); @@ -602,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 @@ -771,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. From 3788ef10a3bef166c9efebdfca90c1d3be5ea036 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Thu, 9 Feb 2012 00:25:33 -0500 Subject: [PATCH 6/6] The eap sucks commit! It turns out that eap (I know it was him... look at those weird comments between the functions) was calling plClient::IDraw for every KeyedObject we loaded in order to update the progress bar. For some reason, some stooge added a framerate limit to the MAIN DRAW LOOP instead of this function. *Sigh*. Either way, the framerate limit is a HACK. We should really be loading resources in another thread. --- Sources/Plasma/Apps/plClient/plClient.cpp | 31 ++++++++++------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/plClient.cpp b/Sources/Plasma/Apps/plClient/plClient.cpp index 6cff6ef1..1b218525 100644 --- a/Sources/Plasma/Apps/plClient/plClient.cpp +++ b/Sources/Plasma/Apps/plClient/plClient.cpp @@ -1290,7 +1290,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; + } } //============================================================================ @@ -1836,22 +1849,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)