]>
Dogcows Code - chaz/yoink/blob - src/Moof/Core.cc
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
10 **************************************************************************/
13 #include <cstdlib> // exit, srand
14 #include <ctime> // time
19 #include "fastevents.h"
25 #include "ModalDialog.hh"
26 #include "Settings.hh"
47 if (settings
.get("rngseed", randomSeed
)) srand(randomSeed
);
50 Scalar timestep
= 80.0;
51 settings
.get("timestep", timestep
);
52 mTimestep
= 1.0 / timestep
;
54 Scalar framerate
= 40.0;
55 settings
.get("framerate", framerate
);
56 mFramerate
= 1.0 / framerate
;
59 settings
.get("showfps", mShowFps
);
64 * The main loop. This just calls dispatchEvents(), update(), and
65 * draw() over and over again. The timing of the update and draw are
66 * decoupled. The actual frame rate is also calculated here. This
67 * function will return the exit code used to stop the loop.
73 ASSERT(video
&& "cannot run core without a current video context");
75 Scalar totalTime
= 0.0;
76 Scalar ticks
= Timer::getTicks();
78 Scalar nextUpdate
= ticks
;
79 Scalar nextDraw
= ticks
;
80 Scalar nextSecond
= ticks
+ SCALAR(1.0);
85 const Scalar timestep
= mTimestep
;
86 const Scalar framerate
= mFramerate
;
88 const int MAX_FRAMESKIP
= 15;
89 const Scalar inverseTimestep
= SCALAR(1.0) / timestep
;
93 Timer::fireIfExpired(); // 1. fire timers
94 dispatchEvents(); // 2. dispatch events
97 while (nextUpdate
< Timer::getTicks() && i
< MAX_FRAMESKIP
)
99 totalTime
+= timestep
;
100 update(totalTime
, timestep
); // 3. update state
102 nextUpdate
+= timestep
;
106 if (nextDraw
< (ticks
= Timer::getTicks()))
108 draw((ticks
+ timestep
- nextUpdate
) * inverseTimestep
);
109 video
->swap(); // 4. draw state
111 nextDraw
+= framerate
;
114 if (nextSecond
< Timer::getTicks())
119 if (mShowFps
) logInfo
<< mFps
<< " fps" << std::endl
;
121 nextSecond
+= SCALAR(1.0);
125 ticks
= Timer::getTicks(); // 5. yield timeslice
126 if (ticks
< nextUpdate
&& ticks
< nextDraw
) Timer::sleep(0.0);
128 while (!mStack
.empty());
130 mDispatch
.dispatch("engine.stopping");
134 void dispatchEvents()
138 while (FE_PollEvent(&event
) == 1)
143 if (event
.key
.keysym
.sym
== SDLK_ESCAPE
&&
144 (SDL_GetModState() & KMOD_CTRL
) )
147 logWarning("escape forced");
152 case SDL_VIDEORESIZE
:
153 video
->resize(event
.resize
.w
, event
.resize
.h
);
162 void update(Scalar t
, Scalar dt
)
164 for (mStackIt
= mStack
.begin(); mStackIt
!= mStack
.end();
167 (*mStackIt
)->update(t
, dt
);
171 void draw(Scalar alpha
)
173 // FIXME - this will crash if the layer being drawn pops itself
174 std::list
<LayerP
>::reverse_iterator it
;
175 for (it
= mStack
.rbegin(); it
!= mStack
.rend(); ++it
)
181 void handleEvent(const Event
& event
)
183 for (mStackIt
= mStack
.begin(); mStackIt
!= mStack
.end();
186 if ((*mStackIt
)->handleEvent(event
)) break;
191 void push(LayerP layer
)
193 ASSERT(layer
&& "cannot push null layer");
194 mStack
.push_front(layer
);
195 logInfo
<< "stack: " << mStack
.size()
196 << " [pushed " << layer
.get() << "]" << std::endl
;
197 layer
->addedToCore();
203 if (mStack
.begin() == mStackIt
) fixIt
= true;
205 LayerP layer
= mStack
.front();
207 logInfo
<< "stack: " << mStack
.size()
208 << " [popped " << layer
.get() << "]" << std::endl
;
209 layer
->removedFromCore();
211 if (fixIt
) mStackIt
= --mStack
.begin();
216 LayerP
pop(Layer
* layer
)
220 std::list
<LayerP
> layers
;
222 std::list
<LayerP
>::iterator it
;
223 for (it
= mStack
.begin(); it
!= mStack
.end(); ++it
)
225 layers
.push_back(*it
);
227 if (it
== mStackIt
) fixIt
= true;
229 if ((*it
).get() == layer
)
232 mStack
.erase(mStack
.begin(), it
);
234 for (it
= layers
.begin(); it
!= layers
.end(); ++it
)
236 (*it
)->removedFromCore();
237 logInfo
<< "stack: " << mStack
.size()
238 << " [popped " << (*it
).get() << "]"
242 if (fixIt
) mStackIt
= --mStack
.begin();
244 return layers
.back();
254 mStackIt
= mStack
.begin();
255 logInfo("stack: 0 [cleared]");
263 std::list
<LayerP
> mStack
;
264 std::list
<LayerP
>::iterator mStackIt
;
276 mImpl(new Core::Impl
) {}
286 int Core::getFps() const
292 void Core::push(LayerP layer
)
304 LayerP
Core::pop(Layer
* layer
)
307 return mImpl
->pop(layer
);
316 int Core::getSize() const
318 return mImpl
->mStack
.size();
329 Dispatch::Handler
Core::addHandler(const std::string
& event
,
330 const Dispatch::Function
& callback
)
332 return mImpl
->mDispatch
.addHandler(event
, callback
);
335 Dispatch::Handler
Core::addHandler(const std::string
& event
,
336 const Dispatch::Function
& callback
,
337 Dispatch::Handler handler
)
339 return mImpl
->mDispatch
.addHandler(event
, callback
, handler
);
342 void Core::dispatch(const std::string
& event
,
343 const Dispatch::Message
* message
)
345 mImpl
->mDispatch
.dispatch(event
, message
);
353 typedef boost::shared_ptr
<Backend_
> BackendP
;
361 #if defined(_WIN32) || defined(__WIN32__)
362 if (SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_TIMER
) != 0)
364 if (SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_EVENTTHREAD
) != 0)
367 const char* error
= SDL_GetError();
368 gError
.init(Error::SDL_INIT
, error
);
374 SDL_VideoDriverName(name
, sizeof(name
));
375 logInfo
<< "initialized SDL; using video driver `"
376 << name
<< "'" << std::endl
;
381 const char* error
= FE_GetError();
382 gError
.init(Error::FASTEVENTS_INIT
, error
);
386 gError
.init(Error::NONE
);
397 if (gRetainCount
++ == 0)
399 gInstance
= BackendP(new Backend_
);
403 static void release()
405 if (--gRetainCount
== 0)
412 static const Error
& getError()
420 static int gRetainCount
;
421 static BackendP gInstance
;
424 Error
Backend_::gError(Error::UNINITIALIZED
);
425 int Backend_::gRetainCount
= 0;
426 BackendP
Backend_::gInstance
;
439 bool Backend::isInitialized()
441 return getError().code() == Error::NONE
;
444 const Error
& Backend::getError()
446 return Backend_::getError();
This page took 0.056061 seconds and 4 git commands to generate.