1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Created by texi2html 1.64 -->
<!--
Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author)
Karl Berry <karl@freefriends.org>
Olaf Bachmann <obachman@mathematik.uni-kl.de>
and many others.
Maintained by: Olaf Bachmann <obachman@mathematik.uni-kl.de>
Send bugs and suggestions to <texi2html@mathematik.uni-kl.de>
-->
<HTML>
<HEAD>
<TITLE>Crystal Space: Simple Header File</TITLE>
<META NAME="description" CONTENT="Crystal Space: Simple Header File">
<META NAME="keywords" CONTENT="Crystal Space: Simple Header File">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<META NAME="Generator" CONTENT="texi2html 1.64">
</HEAD>
<BODY LANG="" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000">
<A NAME="SEC172"></A>
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_73.html#SEC171"> < </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_75.html#SEC173"> > </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_70.html#SEC158"> << </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_73.html#SEC171"> Up </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_79.html#SEC177"> >> </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="index.html#SEC_Top">Top</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_toc.html#SEC_Contents">Contents</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_285.html#SEC711">Index</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_abt.html#SEC_About"> ? </A>]</TD>
</TR></TABLE>
<HR SIZE=1>
<H3> 5.2.1 Simple Header File </H3>
<!--docid::SEC172::-->
<P>
It is good practice to always put defines and declares in header
files as opposed to source files. In some cases it is even needed. Here
we will show the header file for a simple Crystal Space application.
Although this is not strictly required, we use a class to encapsulate
the application logic. Our `<TT>simple.h</TT>' header looks as follows:
</P><P>
<TABLE><tr><td> </td><td class=example><pre>#ifndef __SIMPLE_H__
#define __SIMPLE_H__
#include <stdarg.h>
struct iEngine;
struct iLoader;
struct iGraphics3D;
struct iKeyboardDriver;
struct iSector;
struct iView;
struct iVirtualClock;
struct iObjectRegistry;
struct iEvent;
class Simple
{
private:
iObjectRegistry* object_reg;
iEngine* engine;
iLoader* loader;
iGraphics3D* g3d;
iKeyboardDriver* kbd;
iVirtualClock* vc;
public:
Simple ();
~Simple ();
bool Initialize (int argc, const char* const argv[]);
void Start ();
};
#endif // __SIMPLE1_H__
</pre></td></tr></table></P><P>
In the <CODE>Simple</CODE> class we keep a number of references to important
objects that we are going to need a lot. That way we don't have to get
them every time when we need them. Other than that we have a constructor
which will do the initialization of these variables, a destructor which
will clean up the application, an initialization function which will
be responsible for the full set up of Crystal Space and our application,
and finally a <CODE>Start()</CODE> function to start the event handler.
</P><P>
In the source file `<TT>simple.cpp</TT>' we place the following:
</P><P>
<TABLE><tr><td> </td><td class=example><pre>#include "cssysdef.h"
#include "cssys/sysfunc.h"
#include "iutil/vfs.h"
#include "csutil/cscolor.h"
#include "cstool/csview.h"
#include "cstool/initapp.h"
#include "simple.h"
#include "iutil/eventq.h"
#include "iutil/event.h"
#include "iutil/objreg.h"
#include "iutil/csinput.h"
#include "iutil/virtclk.h"
#include "iengine/sector.h"
#include "iengine/engine.h"
#include "iengine/camera.h"
#include "iengine/light.h"
#include "iengine/statlght.h"
#include "iengine/texture.h"
#include "iengine/mesh.h"
#include "iengine/movable.h"
#include "iengine/material.h"
#include "imesh/thing/polygon.h"
#include "imesh/thing/thing.h"
#include "imesh/object.h"
#include "ivideo/graph3d.h"
#include "ivideo/graph2d.h"
#include "ivideo/txtmgr.h"
#include "ivideo/texture.h"
#include "ivideo/material.h"
#include "ivideo/fontserv.h"
#include "igraphic/imageio.h"
#include "imap/parser.h"
#include "ivaria/reporter.h"
#include "ivaria/stdrep.h"
#include "csutil/cmdhelp.h"
CS_IMPLEMENT_APPLICATION
// The global pointer to simple
Simple *simple;
Simple::Simple ()
{
engine = NULL;
loader = NULL;
g3d = NULL;
kbd = NULL;
vc = NULL;
}
Simple::~Simple ()
{
if (vc) vc->DecRef ();
if (engine) engine->DecRef ();
if (loader) loader->DecRef();
if (g3d) g3d->DecRef ();
if (kbd) kbd->DecRef ();
csInitializer::DestroyApplication (object_reg);
}
bool Simple::Initialize (int argc, const char* const argv[])
{
object_reg = csInitializer::CreateEnvironment (argc, argv);
if (!object_reg) return false;
if (!csInitializer::RequestPlugins (object_reg,
CS_REQUEST_VFS,
CS_REQUEST_SOFTWARE3D,
CS_REQUEST_ENGINE,
CS_REQUEST_FONTSERVER,
CS_REQUEST_IMAGELOADER,
CS_REQUEST_LEVELLOADER,
CS_REQUEST_REPORTER,
CS_REQUEST_REPORTERLISTENER,
CS_REQUEST_END))
{
csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
"crystalspace.application.simple",
"Can't initialize plugins!");
return false;
}
// Check for commandline help.
if (csCommandLineHelper::CheckHelp (object_reg))
{
csCommandLineHelper::Help (object_reg);
return false;
}
// The virtual clock.
vc = CS_QUERY_REGISTRY (object_reg, iVirtualClock);
if (!vc)
{
csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
"crystalspace.application.simple",
"Can't find the virtual clock!");
return false;
}
// Find the pointer to engine plugin
engine = CS_QUERY_REGISTRY (object_reg, iEngine);
if (!engine)
{
csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
"crystalspace.application.simple",
"No iEngine plugin!");
return false;
}
loader = CS_QUERY_REGISTRY (object_reg, iLoader);
if (!loader)
{
csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
"crystalspace.application.simple",
"No iLoader plugin!");
return false;
}
g3d = CS_QUERY_REGISTRY (object_reg, iGraphics3D);
if (!g3d)
{
csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
"crystalspace.application.simple",
"No iGraphics3D plugin!");
return false;
}
kbd = CS_QUERY_REGISTRY (object_reg, iKeyboardDriver);
if (!kbd)
{
csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
"crystalspace.application.simple",
"No iKeyboardDriver plugin!");
return false;
}
// Open the main system. This will open all the previously
// loaded plug-ins.
if (!csInitializer::OpenApplication (object_reg))
{
csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
"crystalspace.application.simple",
"Error opening system!");
return false;
}
csReport (object_reg, CS_REPORTER_SEVERITY_NOTIFY,
"crystalspace.application.simple",
"Simple Crystal Space Application version 0.1.");
return true;
}
void Simple::Start ()
{
csDefaultRunLoop (object_reg);
}
/*---------------*
* Main function
*---------------*/
int main (int argc, char* argv[])
{
simple = new Simple ();
if (simple->Initialize (argc, argv))
simple->Start ();
delete simple;
return 0;
}
</pre></td></tr></table></P><P>
This is almost the simplest possible application and it is absolutely useless.
Also don't run it on an operating system where you can't kill a running
application because there is no way to stop the application once it has
started running.
</P><P>
Even though this application is useless it already has a lot of features
that are going to be very useful later. Here is a short summary of all
the things and features it already has:
</P><P>
<UL>
<LI>
It will open a window.
<LI>
You can control the size of the window and the video driver used
for that window with commandline options (<CODE>-video</CODE> and <CODE>-mode</CODE>
commandline options).
<LI>
It will give commandline help when you use the <CODE>-help</CODE> commandline
option.
<LI>
It has the following plugins initialized and ready to use: engine, 3D
renderer, canvas, reporter, reporter listener, font server, image loader,
level loader, and VFS.
</UL>
<P>
Before we start making this application more useful lets have a look at what
actually happens here.
</P><P>
Before doing anything at all, after including the necessary header files, we
first need to use a few macros. The CS_IMPLEMENT_APPLICATION macro is
essential for every application using CS. It makes sure that the <CODE>main()</CODE>
routine is correctly linked and called on every platform.
</P><P>
The main routine first creates an instance of our
`<SAMP>Simple</SAMP>' class. We put this instance into a global variable to make
access to it easier. The next step is initialization. The first thing the
<CODE>Initialize()</CODE> function does is to create the environment with
<CODE>csInitializer::CreateEnvironment()</CODE>. This will initialize SCF,
create the object registry, setup commandline reading, and then create a
number of other useful entities (plugin manager, event queue, ...).
</P><P>
Note the usage of the <CODE>csReport()</CODE> function. This is a conveniance
function to send a message (usually an error or notification) to the
reporter plugin. It works a lot like <CODE>printf</CODE> except that you
additionally need to give the severity level and an identifier which can give
someone listening to the reporter an idea of the origin of the message.
</P><P>
<CODE>csInitializer::RequestPlugins()</CODE> will use the config file (which
we are not using in this tutorial), the commandline and the requested
plugins to find out which plugins to load. The commandline has highest
priority, followed by the config file and lastly the requested plugins.
</P><P>
The <CODE>csCommandLineHelper::CheckHelp()</CODE> function will check if the
<CODE>-help</CODE> commandline option is given and if so show the help for
all loaded plugins (every plugin that is loaded in memory is capable of
extending the commandline options).
</P><P>
After that we will query the object registry to find out all the common
objects that we're going to need later and store a reference in our
main class. At destruction time we must then release these references
with <CODE>DecRef()</CODE>.
</P><P>
Finally, when all is done the window is opened with a call to the function
<CODE>csInitializer::OpenApplication()</CODE>. This sends the <CODE>cscmdSystemOpen</CODE>
message to all components that are listening to the event queue. One of the
plugins that does this is the 3D renderer which will then open its window (or
enable graphics on a non-windowing operating system).
</P><P>
This concludes the initialization pass.
</P><P>
In <CODE>Simple::Start()</CODE> we will start the default main loop by
calling <CODE>csDefaultRunLoop()</CODE>. This function will only return when
the application exits (which this example cannot yet do). Basically
this function will start the loop to handle events.
</P><P>
<A NAME="Simple Event Handling"></A>
<HR SIZE=1>
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_73.html#SEC171"> < </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_75.html#SEC173"> > </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_70.html#SEC158"> << </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_73.html#SEC171"> Up </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_79.html#SEC177"> >> </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="index.html#SEC_Top">Top</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_toc.html#SEC_Contents">Contents</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_285.html#SEC711">Index</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_abt.html#SEC_About"> ? </A>]</TD>
</TR></TABLE>
<BR>
<FONT SIZE="-1">
This document was generated
using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
"><I>texi2html</I></A>
</BODY>
</HTML>
|