]>
Dogcows Code - chaz/yoink/blob - View.cc
e2e84b52fa600850aaadf73452f10302458d32f6
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
18 #include "fastevents.h"
24 #include "ModalDialog.hh"
25 #include "Settings.hh"
34 class RootView
: public View
36 void update(Scalar t
, Scalar dt
)
38 if (children().size() == 0) stop();
42 static RootView gRootView
;
49 Impl(View
* view
, Settings
& settings
, Video
& video
) :
58 if (settings
.get("rngseed", randomSeed
)) srand(randomSeed
);
61 Scalar timestep
= 80.0;
62 settings
.get("timestep", timestep
);
63 mTimestep
= 1.0 / timestep
;
65 Scalar framerate
= 40.0;
66 settings
.get("framerate", framerate
);
67 mFramerate
= 1.0 / framerate
;
70 settings
.get("showfps", mShowFps
);
84 mTimestep
= SCALAR(0.01);
85 mFramerate
= SCALAR(0.02);
91 * The main loop. This just calls dispatchEvents(), update(), and
92 * draw() over and over again. The timing of the update and draw are
93 * decoupled. The actual frame rate is also calculated here. This
94 * function will return the exit code used to stop the loop.
99 ASSERT(mVideo
&& "running without video set");
101 Scalar totalTime
= 0.0;
102 Scalar ticks
= Timer::getTicks();
104 Scalar nextUpdate
= ticks
;
105 Scalar nextDraw
= ticks
;
106 Scalar nextSecond
= ticks
+ SCALAR(1.0);
111 const Scalar timestep
= mTimestep
;
112 const Scalar framerate
= mFramerate
;
114 const int MAX_FRAMESKIP
= 15;
115 const Scalar inverseTimestep
= SCALAR(1.0) / timestep
;
120 Timer::fireIfExpired(); // 1. fire timers
121 dispatchEvents(); // 2. dispatch events
123 if (!mIsRunning
) break;
126 while (nextUpdate
< Timer::getTicks() && i
< MAX_FRAMESKIP
)
128 totalTime
+= timestep
; // 3. update state
129 mView
.update(totalTime
, timestep
);
131 nextUpdate
+= timestep
;
134 if (!mIsRunning
) break;
137 if (nextDraw
< (ticks
= Timer::getTicks()))
140 (ticks
+ timestep
- nextUpdate
) * inverseTimestep
);
141 mVideo
->swap(); // 4. draw state
143 nextDraw
+= framerate
;
146 if (nextSecond
< Timer::getTicks())
151 if (mShowFps
) logInfo
<< mFps
<< " fps" << std::endl
;
153 nextSecond
+= SCALAR(1.0);
157 if (!mIsRunning
) break;
159 ticks
= Timer::getTicks(); // 5. yield timeslice
160 if (ticks
< nextUpdate
&& ticks
< nextDraw
) Timer::sleep(0.0);
170 void dispatchEvents()
174 while (FE_PollEvent(&event
) == 1)
179 if (event
.key
.keysym
.sym
== SDLK_ESCAPE
&&
180 (SDL_GetModState() & KMOD_CTRL
) )
183 logWarning("escape forced");
188 case SDL_VIDEORESIZE
:
189 mVideo
->resize(event
.resize
.w
, event
.resize
.h
);
193 mView
.handleEvent(event
);
197 bool handleEvent(const Event
& event
)
199 std::list
<ViewP
>::iterator it
;
200 for (it
= mChildren
.begin(); it
!= mChildren
.end(); ++it
)
202 if ((*it
)->handleEvent(event
)) return true;
208 void update(Scalar t
, Scalar dt
)
210 std::list
<ViewP
>::iterator it
;
211 for (it
= mChildren
.begin(); it
!= mChildren
.end(); ++it
)
213 (*it
)->update(t
, dt
);
217 void draw(Scalar alpha
)
219 std::list
<ViewP
>::iterator it
;
220 for (it
= mChildren
.begin(); it
!= mChildren
.end(); ++it
)
227 void addChild(ViewP child
)
229 ASSERT(child
&& "adding null view");
230 ASSERT(child
.get() != &mView
&& "adding view to itself");
232 child
->mImpl
->mParent
->removeChild(child
);
233 mChildren
.push_back(child
);
235 child
->mImpl
->mParent
= &mView
;
236 child
->mImpl
->percolateObjects();
238 child
->didAddToView();
241 void percolateObjects()
243 bool recurseAgain
= false;
245 if (mParent
->mImpl
->mVideo
&& mParent
->mImpl
->mVideo
!= mVideo
)
247 mVideo
= mParent
->mImpl
->mVideo
;
251 if (mParent
->mImpl
->mSettings
&&
252 mParent
->mImpl
->mSettings
!= mSettings
)
254 mSettings
= mParent
->mImpl
->mSettings
;
260 std::list
<ViewP
>::iterator it
;
261 for (it
= mChildren
.begin(); it
!= mChildren
.end(); ++it
)
263 (*it
)->mImpl
->percolateObjects();
268 ViewP
removeChild(View
* child
)
270 ASSERT(child
&& "cannot remove null child");
272 std::list
<ViewP
>::iterator it
;
273 for (it
= mChildren
.begin(); it
!= mChildren
.end(); ++it
)
275 if ((*it
).get() == child
)
278 found
->willRemoveFromView();
281 found
->mImpl
->mParent
= &gRootView
;
303 std::list
<ViewP
> mChildren
;
313 View::View(Settings
& settings
, Video
& video
) :
315 mImpl(new View::Impl(this, settings
, video
)) {}
318 mImpl(new View::Impl(this)) {}
321 void View::update(Scalar t
, Scalar dt
)
324 mImpl
->update(t
, dt
);
327 void View::draw(Scalar alpha
) const
333 bool View::handleEvent(const Event
& event
)
336 return mImpl
->handleEvent(event
);
340 void View::addChild(ViewP view
)
343 mImpl
->addChild(view
);
346 ViewP
View::removeChild(View
* view
)
349 return mImpl
->removeChild(view
);
352 ViewP
View::removeChild(ViewP view
)
355 return mImpl
->removeChild(view
.get());
365 View
& View::parent() const
367 return *(mImpl
->mParent
);
370 const std::list
<ViewP
>& View::children() const
372 return mImpl
->mChildren
;
376 Settings
& View::settings() const
378 ASSERT(mImpl
->mSettings
&& "accessing null reference");
380 return *(mImpl
->mSettings
);
383 Video
& View::video() const
385 ASSERT(mImpl
->mVideo
&& "accessing null reference");
387 return *(mImpl
->mVideo
);
400 return mImpl
->stop();
403 bool View::isRunning() const
406 return mImpl
->mIsRunning
;
This page took 0.053807 seconds and 3 git commands to generate.