From c0ada0ef9608d73b9bc9468756a9541a597e558b Mon Sep 17 00:00:00 2001
From: Arnaud Degroote <arnaud.degroote@laas.fr>
Date: Mon, 25 Nov 2013 13:57:28 +0100
Subject: [PATCH 2/3] Add a time_scale float to control how the time elapses
 in the BGE

---
 source/gameengine/Ketsji/KX_KetsjiEngine.cpp |   26 ++++++++++++++++++++++----
 source/gameengine/Ketsji/KX_KetsjiEngine.h   |   12 ++++++++++++
 source/gameengine/Ketsji/KX_PythonInit.cpp   |   18 ++++++++++++++++++
 3 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 0e9e2cd..8af83d2 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -138,6 +138,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
 	m_clockTime(0.f),
 	m_previousClockTime(0.f),
 	m_previousAnimTime(0.f),
+	m_timescale(1.f),
+	m_previousRealTime(0.f),
 
 
 	m_exitcode(KX_EXIT_REQUEST_NO_REQUEST),
@@ -401,6 +403,7 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo)
 	m_clockTime = m_kxsystem->GetTimeInSeconds();
 	m_frameTime = m_kxsystem->GetTimeInSeconds();
 	m_previousClockTime = m_kxsystem->GetTimeInSeconds();
+	m_previousRealTime = m_kxsystem->GetTimeInSeconds();
 
 	m_firstframe = true;
 	m_bInitialized = true;
@@ -544,7 +547,7 @@ void KX_KetsjiEngine::EndFrame()
 
 bool KX_KetsjiEngine::NextFrame()
 {
-	double timestep = 1.0/m_ticrate;
+	double timestep = (1.0 / m_ticrate) * m_timescale;
 	double framestep = timestep;
 	//	static hidden::Clock sClock;
 
@@ -557,9 +560,13 @@ bool KX_KetsjiEngine::NextFrame()
 		m_clockTime += timestep;
 	}
 	else {
+		double current_time = m_kxsystem->GetTimeInSeconds();
+		double dt = current_time - m_previousRealTime;
+		m_previousRealTime = current_time;
 		// m_clockTime += dt;
-		m_clockTime = m_kxsystem->GetTimeInSeconds();
+		m_clockTime += dt * m_timescale;
 	}
+
 	
 	double deltatime = m_clockTime - m_frameTime;
 	if (deltatime<0.f)
@@ -571,14 +578,15 @@ bool KX_KetsjiEngine::NextFrame()
 
 
 	// Compute the number of logic frames to do each update (fixed tic bricks)
-	int frames =int(deltatime*m_ticrate+1e-6);
+	int frames =int(deltatime*m_ticrate*m_timescale+1e-6);
 //	if (frames>1)
 //		printf("****************************************");
 //	printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames);
 	
 //	if (!frames)
 //		PIL_sleep_ms(1);
-	
+//
+
 	KX_SceneList::iterator sceneit;
 	
 	if (frames>m_maxPhysicsFrame)
@@ -1834,6 +1842,16 @@ void KX_KetsjiEngine::SetTicRate(double ticrate)
 	m_ticrate = ticrate;
 }
 
+double KX_KetsjiEngine::GetTimeScale() const
+{
+	return m_timescale;
+}
+
+void KX_KetsjiEngine::SetTimeScale(double timescale)
+{
+	m_timescale = timescale;
+}
+
 int KX_KetsjiEngine::GetMaxLogicFrame()
 {
 	return m_maxLogicFrame;
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index e7fb250..d3f43c7 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -112,6 +112,8 @@ private:
 	double				m_previousClockTime;//previous clock time
 	double				m_previousAnimTime; //the last time animations were updated
 	double				m_remainingTime;
+	double				m_timescale;
+	double				m_previousRealTime;
 
 	static int				m_maxLogicFrame;	/* maximum number of consecutive logic frame */
 	static int				m_maxPhysicsFrame;	/* maximum number of consecutive physics frame */
@@ -351,6 +353,16 @@ public:
 	 */
 	static double GetAverageFrameRate();
 
+	/**
+	 * Gets the time scale modifier 
+	 */
+	double GetTimeScale() const;
+
+	/**
+	 * Sets the time scale modifier
+	 */
+	void SetTimeScale(double);
+
 	static void SetExitKey(short key);
 
 	static short GetExitKey();
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index f8b3eb0..e748df8 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -521,6 +521,22 @@ static PyObject* gPyGetRealTime(PyObject *)
 	return PyFloat_FromDouble(gp_KetsjiEngine->GetRealTime());
 }
 
+static PyObject* gPyGetTimeScale(PyObject *)
+{
+	return PyFloat_FromDouble(gp_KetsjiEngine->GetTimeScale());
+}
+
+static PyObject* gPySetTimeScale(PyObject *, PyObject *args)
+{
+	double time_scale;
+
+	if (!PyArg_ParseTuple(args, "d:setTimeScale", &time_scale))
+			return NULL;
+
+	gp_KetsjiEngine->SetTimeScale(time_scale);
+	Py_RETURN_NONE;
+}
+
 static PyObject *gPyGetBlendFileList(PyObject *, PyObject *args)
 {
 	char cpath[sizeof(gp_GamePythonPath)];
@@ -880,6 +896,8 @@ static struct PyMethodDef game_methods[] = {
 	{"getFrameTime", (PyCFunction) gPyGetFrameTime, METH_NOARGS, (const char *)"Get the BGE last frametime"},
 	{"getRealTime", (PyCFunction) gPyGetRealTime, METH_NOARGS, (const char *)"Get the real time"},
 	{"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, (const char *)"Gets the estimated average frame rate"},
+	{"getTimeScale", (PyCFunction) gPyGetTimeScale, METH_NOARGS, (const char *)"Get the time modifier parameter"},
+	{"setTimeScale", (PyCFunction) gPySetTimeScale, METH_VARARGS, (const char *)"Set the time modifier parameter"},
 	{"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, (const char *)"Gets a list of blend files in the same directory as the current blend file"},
 	{"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, (const char *)"Prints GL Extension Info"},
 	{"PrintMemInfo", (PyCFunction)pyPrintStats, METH_NOARGS, (const char *)"Print engine statistics"},
-- 
1.7.10.4

