00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "Clock.h"
00017 #include "Log.h"
00018
00019
00020
00021
00022 #define DEFAULT_OBSERVER_NAME "__no_name__"
00023
00024
00025 namespace nrEngine{
00026
00027
00028 ScriptFunctionDec(scriptResetClock, Clock)
00029 {
00030
00031 if (args.size() < 1)
00032 {
00033 return ScriptResult(std::string("resetClock([timeToReset = 0, [reset_all_timers = 1]]) - Not valid parameter count!"));
00034 }
00035
00036 if (param.size() == 0)
00037 {
00038 return ScriptResult(std::string("resetClock() was not properly registered before. Clock was not passed!"));
00039 }
00040
00041
00042 Clock* clock = nrEngine::ScriptEngine::parameter_cast<Clock* >(param[0]);
00043 if (clock == NULL)
00044 {
00045 return ScriptResult(std::string("resetClock() was not properly registered before. Clock was not passed!"));
00046 }
00047
00048
00049 bool shouldResetTimers = true;
00050 float64 timeToReset = 0;
00051 if (args.size() > 1) timeToReset = boost::lexical_cast<float64>(args[1]);
00052 if (args.size() > 2) shouldResetTimers = boost::lexical_cast<bool>(args[2]);
00053
00054
00055 clock->reset(timeToReset, shouldResetTimers);
00056
00057 return ScriptResult();
00058 }
00059
00060
00061 Clock::Clock() : ITask(){
00062
00063 setTaskName("SystemClock");
00064 currentTime = 0;
00065 frameTime = 0;
00066 frameNumber = 0;
00067
00068 sourceStartValue = 0;
00069 sourceLastValue = 0;
00070 sourceLastRealValue = 0;
00071
00072 useFixRate = false;
00073 fixFrameRate = 0;
00074 useMaxRate = false;
00075 maxFrameRate = 0;
00076 lastCurrentTime = 0;
00077
00078
00079 setFrameWindow (7);
00080 frameTime = _getFilteredFrameDuration();
00081
00082 timeSource.reset();
00083 realTimeSource.reset(new TimeSource());
00084
00085
00086 nextSyncTime = 0;
00087 syncInterval = 0;
00088
00089 }
00090
00091
00092 Clock::~Clock(){
00093 stopTask();
00094 }
00095
00096
00097 void Clock::reset(float64 resetToTime, bool resetAllObservers)
00098 {
00099
00100 if (resetAllObservers)
00101 {
00102 NR_Log(Log::LOG_ENGINE, "Clock: Reset time observers");
00103 ObserverList::iterator it = observers.begin();
00104 for (; it != observers.end(); it++) (*it)->resetObserver(resetToTime);
00105 }
00106
00107
00108 lastCurrentTime = resetToTime;
00109 currentTime = resetToTime;
00110 frameTime = frameDefaultTime;
00111
00112 realFrameTime = frameDefaultTime;
00113 nextSyncTime = lastCurrentTime + static_cast<float64>(syncInterval) / 1000.0;
00114
00115
00116 setTimeSource(timeSource);
00117 if (timeSource != NULL) timeSource->reset(resetToTime);
00118
00119
00120 setFrameWindow(frameFilteringWindow, frameDefaultTime);
00121
00122 NR_Log(Log::LOG_ENGINE, "Clock: Reset clock to %f", resetToTime);
00123 }
00124
00125
00126 void Clock::setTimeSource(SharedPtr<TimeSource> timeSource)
00127 {
00128 this->timeSource = timeSource;
00129
00130 if (timeSource != NULL){
00131 sourceStartValue = timeSource->getTime();
00132 sourceLastValue = sourceStartValue;
00133 }
00134 }
00135
00136
00137 void Clock::setSyncInterval(uint32 milliseconds)
00138 {
00139 this->syncInterval = milliseconds;
00140 }
00141
00142
00143 bool Clock::isAnySourceBounded(){
00144 return (timeSource != NULL);
00145 }
00146
00147
00148 SharedPtr<Timer> Clock::createTimer(){
00149
00150
00151 SharedPtr<ITimeObserver> timer(new Timer(*this));
00152
00153
00154 int32 id = addObserver(timer);
00155
00156 if (id == 0){
00157 NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "Clock::createTimer(): Can not add timer to the observer list");
00158 }
00159
00160
00161 timer->_observerID = id;
00162 NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Clock::createTimer(): New timer created (id=%d)", id);
00163
00164
00165 return ::boost::dynamic_pointer_cast<Timer, ITimeObserver>(timer);
00166
00167 }
00168
00169
00170 Result Clock::onStartTask()
00171 {
00172
00173 std::vector<nrEngine::ScriptParam> param;
00174 param.push_back(this);
00175 Engine::sScriptEngine()->add("resetClock", scriptResetClock, param);
00176
00177 return OK;
00178 }
00179
00180
00181 Result Clock::stopTask()
00182 {
00183
00184 timeSource.reset();
00185
00186 for (uint32 i=0; i < observers.size(); i++){
00187 observers[i].reset();
00188 }
00189 observers.clear();
00190
00191 Engine::sScriptEngine()->del("resetClock");
00192
00193 return OK;
00194 }
00195
00196
00197 Result Clock::updateTask(){
00198
00199
00200 if (timeSource == NULL) return CLOCK_NO_TIME_SOURCE;
00201
00202 timeSource->notifyNextFrame();
00203
00204
00205 float64 exactFrameDuration = _getExactFrameDuration();
00206 _addToFrameHistory(exactFrameDuration);
00207
00208
00209 frameTime = _getFilteredFrameDuration();
00210 frameNumber ++;
00211
00212
00213 do {
00214 currentTime = timeSource->getTime();
00215
00216
00217 ObserverList::iterator it;
00218 for (it = observers.begin(); it != observers.end(); ++it){
00219 (*it)->notifyTimeObserver();
00220 }
00221
00222
00223 if (syncInterval > 0 && nextSyncTime < currentTime)
00224 {
00225 timeSource->sync();
00226 nextSyncTime = currentTime + static_cast<float64>(syncInterval) / 1000.0;
00227 }
00228
00229 } while (useMaxRate && (currentTime - lastCurrentTime) < invMaxFrameRate);
00230
00231
00232 lastCurrentTime = currentTime;
00233
00234
00235 return OK;
00236 }
00237
00238
00239 float64 Clock::getTime() const{
00240 return currentTime;
00241 }
00242
00243
00244 float32 Clock::getFrameInterval() const{
00245 return (float32)frameTime;
00246 }
00247
00248
00249 float32 Clock::getRealFrameInterval() const
00250 {
00251 return (float32)realFrameTime;
00252 }
00253
00254
00255 float32 Clock::getRealFrameRate() const
00256 {
00257 return 1.0f / getRealFrameInterval();
00258 }
00259
00260
00261 int32 Clock::getFrameNumber() const{
00262 return frameNumber;
00263 }
00264
00265
00266 float32 Clock::getFrameRate() const{
00267 return 1.0f / getFrameInterval();
00268 }
00269
00270
00271 int32 Clock::addObserver(SharedPtr<ITimeObserver> timeObserver){
00272
00273 int32 id = 0;
00274
00275 if (timeObserver != NULL){
00276 observers.push_back (timeObserver);
00277 id = observers.size();
00278 observerIDList[std::string(DEFAULT_OBSERVER_NAME) + ::boost::lexical_cast< std::string >(id)] = id;
00279 observers[observers.size()-1]->_observerID = id;
00280 }
00281
00282 return id;
00283 }
00284
00285
00286 Result Clock::removeObserver(int32 observerID){
00287
00288 int32 id = observerID - 1;
00289 if (id <= 0 || id+1 >= static_cast<int32>(observers.size())
00290 || observerIDList.find(std::string(DEFAULT_OBSERVER_NAME) +
00291 ::boost::lexical_cast< std::string >(observerID)) == observerIDList.end()){
00292 return CLOCK_OBSERVER_NOT_FOUND;
00293 }
00294
00295
00296 observers.erase(observers.begin() + id);
00297
00298
00299 observerIDList.erase(observerIDList.find( std::string(DEFAULT_OBSERVER_NAME) +
00300 ::boost::lexical_cast< std::string >(observerID) ));
00301
00302
00303 return OK;
00304 }
00305
00306
00307 Result Clock::addObserver(const std::string& obsName,SharedPtr<ITimeObserver> timeObserver)
00308 {
00309
00310
00311 if (observerIDList[obsName]){
00312 return CLOCK_OBSERVER_ALREADY_ADDED;
00313 }
00314
00315
00316 if (timeObserver != NULL && obsName.length() > 0){
00317 observers.push_back (timeObserver);
00318 observerIDList[obsName] = observers.size();
00319 observers[observers.size()-1]->_observerID = observers.size();
00320 }
00321
00322 return OK;
00323
00324 }
00325
00326
00327 Result Clock::removeObserver(const std::string& obsName){
00328
00329 if (observerIDList[obsName]){
00330 int32 id = observerIDList[obsName] - 1;
00331 observers.erase(observers.begin() + id);
00332 }else{
00333 return CLOCK_OBSERVER_NOT_FOUND;
00334 }
00335
00336 return OK;
00337 }
00338
00339
00340 void Clock::setFrameWindow(int32 frameCount, float32 defaultFrameTime){
00341
00342 frameFilteringWindow = frameCount > 1 ? frameCount : 1;
00343 frameDefaultTime = defaultFrameTime;
00344 frameDurationHistory.clear ();
00345 frameDurationHistory.push_back(frameDefaultTime);
00346 }
00347
00348
00349 void Clock::setFixFrameRate(bool setFixRate, float32 fixFrameRate){
00350 useFixRate = setFixRate;
00351 this->fixFrameRate = fixFrameRate;
00352 }
00353
00354
00355 void Clock::setMaxFrameRate(bool set, float32 maxFPS)
00356 {
00357 useMaxRate = set;
00358 this->maxFrameRate = maxFPS;
00359 invMaxFrameRate = 1.0 / (float64)(maxFPS);
00360 }
00361
00362
00363 float64 Clock::_getExactFrameDuration (){
00364
00365
00366 float64 sourceTime = timeSource->getTime();
00367 float64 sourceRealTime = realTimeSource->getTime();
00368
00369 realFrameTime = sourceRealTime - sourceLastRealValue;
00370
00371 sourceLastValue = sourceTime;
00372 sourceLastRealValue = sourceRealTime;
00373
00374
00375
00376
00377
00378
00379
00380 if (useFixRate || timeSource == NULL){
00381 return 1.0f / (fixFrameRate);
00382 }
00383
00384 return realFrameTime;
00385 }
00386
00387
00388 void Clock::_addToFrameHistory (float64 exactFrameDuration){
00389 frameDurationHistory.push_back (exactFrameDuration);
00390 if (frameDurationHistory.size () > (uint32) frameFilteringWindow)
00391 frameDurationHistory.pop_front ();
00392 }
00393
00394
00395 float64 Clock::_getFilteredFrameDuration () const{
00396
00397 if (useFixRate){
00398 return 1.0f/(fixFrameRate);
00399 }
00400
00401 float64 totalFrameTime = 0;
00402
00403 std::deque<float64>::const_iterator it;
00404 for (it=frameDurationHistory.begin();it != frameDurationHistory.end(); ++it){
00405 totalFrameTime += *it;
00406 }
00407
00408 return totalFrameTime/static_cast<float64>(frameDurationHistory.size());
00409 }
00410
00411 };
00412
00413 #undef DEFAULT_OBSERVER_NAME