|
You don't need to use AG_EventLoop_FixedFPS(). Agar allows you to use
a custom event loop, but in practice this is only useful in specialized
applications such as embedded devices, or to overlay Agar GUI elements on
top of an existing SDL or OpenGL application.
If you do need a custom event loop, here is a sample application
which uses a minimal event loop equivalent to AG_EventLoop_FixedFPS().
As you can see, Agar only requires that you:
-
Invoke AG_WidgetDraw() on every visible window (and naturally update
the video region associated with the window).
-
Relay events to AG_ProcessEvent(), so that Agar-GUI can respond to
input device events (and
SDL_VIDEORESIZE). The argument is of
type SDL_Event, but events don't have to come from the SDL.
For example, you could process events from a remote control using
LIRC
and pass a SDL_Event with type = SDL_KEYUP or SDL_KEYDOWN.
-
Update Agar's wheel of time by calling AG_ProcessTimeout(). As an
optimization, you only need to call the function if the list
agTimeoutObjQ is non-empty.
Example 1-1: Basic event loop
(source)
#include <agar/config/have_opengl.h>
#include <agar/core.h>
#include <agar/gui.h>
#include <agar/gui/opengl.h>
static void
MyEventLoop(void)
{
SDL_Event ev;
AG_Window *win;
Uint32 Tr1 = SDL_GetTicks(), Tr2 = 0;
for (;;) {
Tr2 = SDL_GetTicks();
if (Tr2-Tr1 >= agView->rNom) { /* Time to redraw? */
AG_LockVFS(agView);
#ifdef HAVE_OPENGL
if (agView->opengl) {
glClear(GL_COLOR_BUFFER_BIT|
GL_DEPTH_BUFFER_BIT);
}
#endif
/*
* Render the GUI windows and generate a list of
* dirty rectangles.
*/
AG_TAILQ_FOREACH(win, &agView->windows, windows) {
AG_ObjectLock(win);
if (!win->visible) {
AG_ObjectUnlock(win);
continue;
}
AG_WidgetDraw(win);
if (!(win->flags & AG_WINDOW_NOUPDATERECT)) {
AG_QueueVideoUpdate(
AGWIDGET(win)->x, AGWIDGET(win)->y,
AGWIDGET(win)->w, AGWIDGET(win)->h);
}
AG_ObjectUnlock(win);
}
/*
* Update the dirty rectangles. In OpenGL mode,
* we always update the entire display.
*/
if (agView->ndirty > 0) {
#ifdef HAVE_OPENGL
if (agView->opengl) {
SDL_GL_SwapBuffers();
} else
#endif
{
SDL_UpdateRects(agView->v,
agView->ndirty,
agView->dirty);
}
agView->ndirty = 0;
}
AG_UnlockVFS(agView);
/* Recalibrate the effective refresh rate. */
Tr1 = SDL_GetTicks();
agView->rCur = agView->rNom - (Tr1-Tr2);
if (agView->rCur < 1) {
agView->rCur = 1;
}
} else if (SDL_PollEvent(&ev) != 0) {
/* Send all SDL events to Agar-GUI. */
AG_ProcessEvent(&ev);
} else if (AG_TAILQ_FIRST(&agTimeoutObjQ) != NULL) {
/* Advance the timing wheels. */
AG_ProcessTimeout(Tr2);
} else if (agView->rCur > agIdleThresh) {
/* Idle the rest of the time. */
SDL_Delay(agView->rCur - agIdleThresh);
}
}
}
int
main(int argc, char *argv)
{
AG_Window *win;
AG_Table *tbl;
if (AG_InitCore("event1", 0) == -1 ||
AG_InitVideo(320, 240, 32, AG_VIDEO_RESIZABLE) == -1) {
return (1);
}
win = AG_WindowNew(0);
AG_LabelNewStatic(win, 0, "Hello, world!");
AG_WindowShow(win);
MyEventLoop();
return (0);
}
|