Integration

This section will explain step by step the requirements to integrate Reveal into your application.

> > > > > > If Reveal is already integrated in your application, please proceed to the tutorial instead.

I assume you already downloaded the library package (sources, compiled libraries for most platforms, executables, documentation), otherwise get it from the framework package server.

I suggest you start out with just compiling for one platform. If you are ready to use the RealComm library, I suggest trying it on the XBox first (but PS2 and GC work as well). If you want to use Win32 only then do a PC version first. If you don't want to use either RealComm or Win32 but you want to write your own support routines, I suggest using Win32 or RealComm first to get some feel for things.

1. Add the Reveal include path to your include-folder search-path.
   For example, if your directory tree looks like this:
   d:\project\lib\reveal\
   d:\project\lib\reveal\docs\
   d:\project\lib\reveal\source\
   d:\project\lib\reveal\include\
   d:\project\lib\reveal\include\reveal
   etc.
   then the include-folder you add should be d:\project\lib\reveal\include or some relative path. It is important to realize that you should not point directly to the path where all the header files are located (include/reveal in this case).

The way you need to include Reveal include files is by specifying the Reveal header folder in front of it. As an example, try to include the following somewhere in your code:

#include "reveal/tweaker.h"

Try to compile this and make sure it can find the include file.
- Link in the platform- and build-specific library
  Reveal comes with pre-build libraries for the major platforms (PC, GC, PS2, XBox). You'll probably want to use those. If not, the full source is include so it shoulnd't be too hard to build your own libraries. Just look at the existing project- and make-files for more information.
  Anyway, make sure your library path contains the reveal/lib/platform folder, and link in the requested version of the library. Currently, we support the following versions:

  Filename | Purpose
  lib/pc-vc7/reveald.lib | Debug version of the reveal lib for PC
  lib/pc-vc7/revealz.lib | Release version of the reveal lib for PC
  lib/xbox/reveald.lib | Debug version of the reveal lib for XBox
  lib/xbox/revealz.lib | Release version of the reveal lib for XBox
  lib/ps2-sn/reveald.lib | Debug version of the reveal lib for Playstation 2
  lib/ps2-sn/revealz.lib | Release version of the reveal lib for Playstation 2
  lib/ngc/reveald.lib | Debug version of the reveal lib Nintendo GameCube
  lib/ngc/revealz.lib | Release version of the reveal lib Nintendo GameCube
  lib/{platform}/stub_reveal(d|z).lib
  Stub version of the reveal libs for all platforms in both release and debug form.

  Just link in whatever library you need.
  The stub libraries provide stubs that get optimized away in Release mode. That way you won't have to wrap all your exposure code in #ifdef debug statements. So, for the release version of the game you'lll probably want to link in the stub-release version, and for the debug version of the game you'll link in the regular release
  version of the library. This way, it's also easy to enable Reveal in the release version of the game, by simply changing the library you link in (and adding a define to your project).
- Give Reveal some memory to use
  Reveal abstracts it's memory consumption so people can use their own allocation schemes.
  It is important to notice that Reveal allocations happen a lot (a minimum of two per control that's added, and more depending on the depth of the tree), and that they are all really small allocations (most of them smaller than 200 bytes, some of them even as small as 4 bytes). Therefore, if you have a custom small object allocator (something like Andrei Alexandrescu describes in his Modern C++ Design book, or perhaps a future SportsCore one) that is optimized for a relatively large number of small allocations, make sure you use that instead of a global general purpose allocation scheme.
  To abstract the Reveal memory mechanism, I had several options, each with advantages and drawbacks. These were the following:
  1. Let the client pass an amount of memory to Reveal at initialization time, and Reveal uses that internally using its own small object allocator. The drawback of this approach is twofold. One, it enforces the client to have a unique point of instantiation (POI). Right now the POI can be anywhere because the tweaker constructor takes no parameters, and allocates no memory. This greatly simplies using a global variable or the singleton approach, as we can do a lazy initialization. Would we use this approach, that is no longer possible. The second drawback is that Reveal has no custom memory allocator at the moment, and without introducing a new dependency or writing one myself, this can't be fixed.
  2. Use a COM based approach where you have an abstract base class (an interface) that supplies two methods, alloc and free. The user supplies an implementation of this interface and passes it to the tweaker. The problem with this approach is that we either need to know the POI, or pass the allocator everytime we do something.
  3. Use a template based approach, where the allocator becomes a policy parameter (see Modern C++ Design). The problem with this approach is that all code has to be in headers (not practical), and that all concrete classes have to become templatized.
  4. Use two free functions, alloc and free, that are declared somewhere, but not implemented. Then, force the client to implement these, so the linker will find them during the linking phase.
  This last approach is the approach Reveal is using. Thus in order to be able to use Reveal, you have to implement two functions in the Reveal::Memory namespace. If you don't do this, you will end up with linker errors. Just copy paste the following code, and put it somewhere in a .cpp file of your game (the file where the other Reveal integration code is going as well for example).

  namespace Reveal { namespace Memory { void* RevealMalloc( size_t size ) { return malloc( size ); }
  void RevealFree( void* ptr ) { free( ptr ); }
  }
  }

  Ofcourse, you don't have to use malloc and free there. You can, and should, use your own memory scheme there. Just make sure the functions are called exactly that, and defined in the Reveal::Memory namespace. If you want, you can check and #include "reveal/custom_memory.h" to see the signatures.
- Give the Reveal GUI a renderer to use
  To reduce dependencies, Reveal does not rely on any specific renderer implementation. Instead, you will have to supply your own renderer. No worries though, since this is really easy to do. All you need are four functions, and I would be surprised if your game does not already have them. They are a line, text , bar and triangle function. All in screenspace. You can of course always use two triangles to draw a rectangle. For this tutorial, I will assume your application supports the following four calls:

  void MyDrawLine( int x1, int y1, int x2, int y2, Reveal::uint32_t color ); void MyDrawBar( int x1, int y1, int x2, int y2, Reveal::uint32_t color ); void MyDrawText( int x1, int y1, const char* text, Reveal::uint32_t color ); void MyDrawTriangle( int x1, int y1, int x2, int y2, int x3, int y3, Reveal::uint32_t color );

  See? You don't even need texturing or whatever. I even assume that your debug font will have a reasonable size, but I don't care what it looks like, or anything else. I don't think any application should have problems supporting something like the above four functions.
  Anyway, we still need a way to give these four functions to Reveal. That's where the Reveal::Renderer class comes in. Using the above functions, you need to write the following code:

  #include "reveal/renderer.h" class MyRendererImpl : public Reveal::Renderer { private: virtual void DoLine( int x1, int y1, int x2, int y2, Reveal::uint32_t color ) const
  {
  MyDrawLine( x1, y1, x2, y2, color );
  }
  virtual void DoBar( int x1, int y1, int width, int height, Reveal::uint32_t color ) const
  {
  MyDrawBar( x1, y1, width, height, color );
  }

  virtual void DoString( int x1, int y1, const char* str, Reveal::uint32_t color ) const
  {
  MyDrawText( x1, y1, str, color );
  }

  virtual void DoTriangle( int x1, int y1, int x2, int y2, int x3, int y3, Reveal::uint32_t color ) const
  {
  MyDrawTriangle( x1, y1, x2, y2, x3, y3, color );
  }

  virtual int DoGetScreenOriginX() const { return /* X of top left corner of the screen */; }
  virtual int DoGetScreenOriginY() const { return /* Y of top left corner of the screen */; }
  virtual int DoGetScreenWidth() const { return /* width of screen */; }
  virtual int DoGetScreenHeight() const { return /* height of screen */; }
  };

  Ok, allow me to explain this. First of all, that private is not a typo. The Reveal::Renderer base class has public base methods that do some stuff, and then forward their call to the virtual implementations in the derived class. Therefore, they are private. Later, we are going to give the Reveal system an instance of the above class (your implementation) and Reveal will thus use your functions to do the drawing.
  What about those four functions at the bottom; DoGetScreenOriginX(), DoGetScreenOriginY(), DoGetScreenWidth() and DoGetScreenHeight()? Those are for dealing with the different resolutions, and television overscans. You should implement these, returning the safe region on your particular platform. For example, the top left visible pixel on a television using the XBox, is somewhere at (25, 35). Thus, DoGetScreenOriginX() would return 25, and DoGetScreenOriginY() would return 35. Also, the width and height are probably smaller since there is some underscan at the bottom and right of the screen.
  I'll comment on how you actually use the renderer after I talk about input.
- Given the Reveal system some input
  The input system is seperated from the outside world much in the same way as the renderer. There is baseclass Reveal::InputState for which you need to provide an implementation. Luckily though, I already provide two implementations, one for PC Win32 platforms and one using Real 5 (for consoles). Let's take a look at how you would use one, and then take a look at what it would take to implement your own system.

  Note for Mudlark integrators: You will have to implement your own input state. Please see the Mudlark integration documentation for more information.
  The Win32 input implementation for PC's
  This is the easiest implementation available. Just include the following:

  #include "reveal/win32_pc_input_state_impl.h"

  And create an instance as follows:

  Reveal::Win32PcInputStateImpl inputState( HWND ); // Where HWND is the application window handle;

  And that's it. I'll come back on how you use this instance.
  Implementing my own input state
  I suggest you skip this section if you choose to use the Win32 or Real 5 implementations for the input. Just come back once you want to implement your own input state.
  Implementing your own input system works much like you did for the renderer. You derive from Reveal::InputState and implement a few pure virtuals. Here's an example, with empty implementations.

  class MyInputStateImpl : public InputState { private: virtual void DoUpdate() { /* this is your chance to actually update the state of your mouse and button; */ } virtual int DoMouseRelX() const { /* relative horizontal mouse movement in between the last two calls to DoUpdate */ }
  virtual int DoMouseRelY() const { /* relative vertical mouse movement in between the last two calls to DoUpdate */ }
  virtual Reveal::uint32_t DoDown() const { /* bitwise combination of all buttons that are currently down */ }
  };

  Later, we will see that we need to call the base-method InputState::Update() every frame. This will then call the virtual DoUpdate() that you implemented. In here, you should take the chance to get the current button state, and mouse movement since the previous call.
  The DoMouseRelX() and DoMouseRelY() methods should return the relative horizontal and vertical mouse movement. The DoDown() method should return information on buttons that are down. The Reveal::InputState base class uses this information to know what buttons went from up to down (pressed), or down to up (released) in between the last two calls to Reveal::InputState::Update().
  The return value of your DoDown() implementation should be a bitwise combination of the flags defined in Reveal::InputState. For example, if the left key and the left mouse button are currently down, then you would return Reveal::InputState::CONFIRM | Reveal::InputState::LEFT (where | is the C++ bitwise OR operator).
  A good idea for a possible Reveal::InputState implementation would be to implement it using your specific console-pad. If you combine that with the RealComm implementation, people can use both the keyboard and mouse and the console-pad as well. This is what FIFA does for example. It takes the analog sticks for relative mouse input, and maps the buttons to the other keyboard controls. If you do take the analog sticks for mouse input, I recommend putting the mouse on the right analog stick. You should also implement a dead-zone for the analog stick, as it is never exactly zeroed out.
  Another thing you could do, which again is something that FIFA and EA-UK are doing as well, is use the mouse support on the PS2. There is a Logitech mouse library for the PS2 that allows you to plug a mouse directly into the front of your PS2. It's extremely useful. Starting with the April 2004 XDK, the Xbox will have direct mouse support as well, there is a chance that we will drop the RealComm implementation then, because we won't need it anymore.
  If you need more information for providing your own implementation for the Reveal::InputState class you can take a look at the Reveal::Real5InputStateImpl and Reveal::Win32PcInputStateImpl classes for an idea how I did it. Even better, mail me (jsuter@ea.com) for the implementation that we use in Fifa. You won't be able to copy paste it directly, but it will be a valuable learning tool.
- Creating, enabling and updating the tweaker
  Now that we have a implementation of both Reveal::Renderer and Reveal::InputState, we are ready to use the tweaker. Make an instance of the tweaker, preferably global (so other parts of the code can reach it, and thus expose their variables), and update it every frame, as follows:

  #include "reveal/tweaker.h" // Global variable, or member of something that exists for a long time. Reveal::Tweaker tweaker; // Enable Reveal, (normally you would do this when you press the magic button to enable Reveal) tweaker.SetEnable( true );
  // Every frame
  {
  tweaker.Handle( inputState );
  tweaker.Render( renderer );
  }

  The Reveal::Tweaker constructor takes no parameters, and does nothing complicated. Also, it has no post-main dependencies. Therefore, you can safely make it a global variable somewhere. If you hate global variables, you can use the provided singleton in the reveal/singleton.h header file, as follows:

  #include "reveal/singleton.h" // Normally you would do this when you press the magic button to enable Reveal. Reveal::Singleton::Instance().SetEnable( true ); // Every frame {
  Reveal::Singleton::Instance().Handle( inputState );
  Reveal::Singleton::Instance().Render( renderer );
  }

  In the above code, inputState and renderer are instance of your implementations for Reveal::InputState and Reveal::Renderer. If your renderer has no state, but only forwards the calls to your application calls, you can choose to construct it inline every frame if you want. The inputState has state, so it needs to persist. You can make it static if you want, or do whatever. Just pass the renderer and the inputState to the tweaker every frame, using the Reveal::Tweaker::Handle and Reveal::Tweaker::Render calls.
  If don't want to make the global, and don't like the singleton, you can #include "reveal/reveal.h" as a last resort. This will pull in all namespaces, include all includes, and gives you a global variable called gTweaker. This is not a good programming practive, but it's quick, easy and dirty. Warning, if you don't use this method, than do not #include "reveal/reveal.h".
- Defining REVEAL in your project
  In order to use Reveal, you have to define REVEAL globally in your project. That is, merely defining it in one file isn't enough, it needs to be defined whereever you actually use Reveal. The reason for this is that you can then undefine REVEAL and link with the stub_ libraries to remove Reveal from your application completely. This means you won't have to wrap all exposure code in between #ifdef DEBUG statements.
  So remember, to use Reveal, define REVEAL and link in the non-stub version of the library.
- Trying it out
  Find a function (or write one) that takes a bool, and returns nothing. Preferably something that has some interesting effect depending on the boolean value. For example:

  void foo( bool v ) { printf( "hello world" ); }

  Now, somewhere in your initialization code, do the following:

  tweaker.AddCheckBoxControl( "misc/whatever/some", "enable", &foo );

  Where tweaker is your tweaker instance, global, static or singleton.
  Compile, link and run your application, and see what happens. Make sure you get some input, and move the mouse (or controller) to the top or bottom of the screen. You should see the menu appear, and you should have a menu structure as in "start / misc / whatever / some" with in it a checkbox control called "enable". If you click it, the foo() function should be called.
- Expose your game, hook in the pause button, use the auxillary buttons, etc. etc. etc.
  That's it. You've succesfully integrated Reveal into your application. You are now ready to expose anything in your game. Just continue to the tutorial for more information on that.