[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## C.1 Release Notes from 0.98 to 1.00

Written by Eric Sunshine, sunshine@sunshineco.com and Frank Richter, res@crystalspace3d.org, with contributions from Adam D. Bradley artdodge@cs.bu.edu and others.

This section documents the major changes between versions 0.98 and 1.00 of Crystal Space.

### New Event System

The event system has undergone a major rewrite, and most client applications will need to make changes in order to adapt to the new architecture.

#### Event Names

The old system of 32 static event "types" has been replaced with an extensible tree-structured event naming layer. This system allows event names to be drilled down to arbitrary levels of specificity while simultaneously allowing event subscribers to express interest in general categories or precise event varieties.

For an example: under the old system, any motion of any joystick would produce a ``csevJoystickMove'` event, and all subscribers to the corresponding ``CSMASK_JoystickMove'` mask would receive all such events. Under the new system, each joystick is individually named, so event consumers can listen only to particular devices, or to particular flavors of events. For example, the fourth joystick can produce the event ``crystalspace.input.joystick.3.button.down'`; an event handler may wish to subscribe to ``crystalspace.input.joystick.3.button.down'` to only receive down events from that joystick, to ``crystalspace.input.joystick.3.button'` to receive all button events from that joystick, to ``crystalspace.input.joystick.3'` to receive all events (buttons and moves) from that joystick, to ``crystalspace.input.joystick'` to receive all events from all joysticks, and so on.

This also means that the concept of Command Codes has been obsoleted. Rather than describing particular command events with a combination of the ``csevCommand'` event type and a command-event-specific command code property, each of the old command codes now has its own event name. For example, ``cscmdQuit'` is now ``crystalspace.application.quit'`, and the ``cscmdPreProcess'`/``cscmdProcess'`/``cscmdPostProcess'`/ ``cscmdFinalProcess'` series will be replaced with a single ``csevFrame'` event (see below).

Event names are translated into an efficient internal representation, the ``csEventID'`, using a singleton event name registry object (``csEventNameRegistry'`, implementing the ``iEventNameRegistry'` interface) which can always be retrieved using the `csEventNameRegistry::GetRegistry(iObjectRegistry*)` method. The actual name translation is performed by the `GetID()` method, which takes string or ``csString'` arguments and returns ``csEventID'`s. These ``csEventID'`s are then used in calls to subscribe to event queues and in comparisons to determine the type of an event. Many common event types' ``csEventID'`s can be accessed using macros defined in ``include/csutil/eventnames.h'`, e.g., ``crystalspace.application.quit'` is ``csevQuit()'`, which must be called upon either an ``iObjectRegistry'` pointer or a ``iEventNameRegistry'` reference. Since referencing an event ID via one of these macros will consume several cycles, performance-sensitive code should cache the results; see, for example, the ``CS_DECLARE_EVENT_SHORTCUTS'` and ``CS_INITIALIZE_EVENT_SHORTCUTS()'` macros in ``include/csutil/eventnames.h'`.

The most intrusive change needed to handle the new event names is in the event demultiplexing you do in event handlers. For example, code that used to look like this:

     static bool DemoEventHandler (iEvent& ev)
     {
       if (ev.Type == csevBroadcast
        && csCommandEventHelper::GetCode(&ev) == cscmdProcess)
       {
           ...
       }
       else if (ev.Type == csevBroadcast
        && csCommandEventHelper::GetCode(&ev) == cscmdFinalProcess)
       {
           ...
       }
       else ...
     }

should be re-written as:

     static bool DemoEventHandler (iEvent& ev)
     {
       if (ev.Name == csevProcess (object_reg))
       {
           ...
       }
       else if (ev.Name == csevFinalProcess (object_reg))
       {
           ...
       }
       else ...
     }

More interestingly, you can also catch entire event hierarchies with a single test:

     if (name_reg->IsKindOf(ev.Name, csevKeyboardEvent (name_reg)))
     {
         HandleKeyboardEvent(ev)
     }

#### Event Scheduling

The more interesting change to the event system is the introduction of a schedulable event subscription system. In the old system, event handlers subscribed to event types on a first-come, first-served basis. This begot an increasing number of event types to represent different points in the frame processing chain that a client might want to hook onto: PreProcess, Process, PostProcess, and FinalProcess. What was really needed was a generic mechanism for representing the order in which handlers of particular events should be invoked, regardless of the order in which they are initialized or in which their respective plugins are loaded.

The new event scheduler takes advantage of properties exposed by a new, enriched `iEventHandler` interface to do exactly this. Under the new system, for each event name that an event handler subscribes to, it may also specify essentially arbitrary happens-before and happens-after relationships with other event handlers, both abstractly ('I want to handle all input events before any instance of the ``crystalspace.aws'` handler') and specifically ('I want to handle the mouse event only after the ``crystalspace.cel'` event handler').

Specifically, the new functions that all `iEventHandler` implementations must provide are:

- `const char *GenericName()` Returns a simple text name common to all instances of this event handler.
- `csHandlerID GenericID()` A csHandlerID is a lightweight way to manage generic handler names. Under almost all circumstances, the implementation of this method simply returns `csHandlerRegistry::GetID(this->GenericName())`.
- `const csHandlerID[] GenericPrec(csEventID)` Returns an array (terminated by `CS_EVENTLIST_END`) of ``csHandlerID'`s of generic event handlers which, for the event name identified by the argument, should always handle events with that name before instances of the current handler.
- `const csHandlerID[] GenericSucc(csEventID)` Returns an array (terminated by `CS_EVENTLIST_END`) of ``csHandlerID'`s of generic event handlers which, for the event name identified by the argument, should always handle events with that name after instances of the current handler.
- `const csHandlerID[] InstancePrec(csEventID)` Returns an array (terminated by `CS_EVENTLIST_END`) of ``csHandlerID'`s of both generic event handlers and event handler instances which, for the event name identified by the argument, should always handle event with that name before this particular instance of the event handler.
- `const csHandlerID[] InstanceSucc(csEventID)` Returns an array (terminated by `CS_EVENTLIST_END`) of ``csHandlerID'`s of both generic event handlers and event handler instances which, for the event name identified by the argument, should always handle event with that name after this particular instance of the event handler.

In many simple cases, you will want to use default implementations of these functions provided by the `CS_EVENTHANDLER_NAMES()` and `CS_EVENTHANDLER_NIL_CONSTRAINTS` macros, like so:

     struct eiEventHandler : public iEventHandler
     {
       SCF_DECLARE_EMBEDDED_IBASE (csWrapperClass);
       virtual bool HandleEvent (iEvent &Event)
       {
         return scfParent->HandleEvent (Event);
       }
       CS_EVENTHANDLER_NAMES("crystalspace.module.name")
       CS_EVENTHANDLER_NIL_CONSTRAINTS
     }

As a convention, most csEventHandlers will implement a static method, `const char *StaticHandlerName()`, which can be retrieved and converted without instantiating the handler. This name string can then be converted into a ``csHandlerID'` by calling `csHandlerRegistry::GetID(myHandlerClass::StaticHandlerName())`. The ``csHandlerID'` of an instance of an event handler class can be retrieved by passing a pointer to that class to `csHandlerRegistry::GetID()`, e.g., `csHandlerRegistry::GetID(new myHandlerClass)`.

#### Event Subscription

The event scheduling system is invoked by calling the `csEventQueue::RegisterListener()` or `csEventQueue::Subscribe()` methods (or, if you are inheriting from `csBaseEventHandler`, `csBaseEventHandler::RegisterQueue`). For each of these, the arguments of interest to use are the `csEventID` and `csEventID[]` parameters. (Note that the ``RegisterListener'` form with no ``csEventID'` argument does not subscribe the listener to anything, and must be followed by a call to `Subscribe()` if you ever want the handler to receive any events.) For each `csEventID` (arrays are terminated by `CS_EVENTLIST_END`), these functions will subscribe the event handler to that event name as well as all of its children. Note, however, that it will only retrieve from the event handler the ordering lists (the Prec and Succ methods) for the event name to which it is explicitly subscribed; if you wish to have one set of ordering constraints for both ``crystalspace.input.keyboard'` and ``crystalspace.input.mouse'` but a different set for ``crystalspace.input.joystick'`, you SHOULD NOT simply subscribe to ``crystalspace.input'` and have the Prec/Succ functions return different values for each of ``.keyboard'`, ``.mouse'`, and ``.joystick'`; rather, you should subscribe to each of those three event names individually. This restriction helps us avoid the introduction of subtly contradictory or circular ordering rules.

Also note that you should use the `Subscribe()` and `Unsubscribe()` methods to add and remove events from the set an event handler wishes to receive. Note that you should only `Unsubscribe()` from the particular events to which you have `Subscribe()`d; the behavior is undefined if you (e.g.) subscribe to ``crystalspace.input'` and subsequently unsubscribe from ``crystalspace.input.joystick'`.

#### Other porting Issues

Since the ``csBaseEventHandler'` object's operation is now linked with having a functional event name registry, any derived class must be sure to call the ``Initialize(iObjectRegistry*)'` method before calling any of the ``RegisterQueue(...)'` methods.

#### The `csevFrame` Transition

At present, a lot of code depends upon subscription to the PreProcess, Process, PostProcess, and FinalProcess events. We intend to remove these events shortly; in their place, all event handlers interested in being called per-frame should subscribe to the ``csevFrame'` event and specify appropriate ordering constraints. (If a handler needs to be called several times per frame, then it should create several embedded event handlers each with its own ordering constraints.) Unfortunately, there aren't any really good ways to make this change-over gracefully, so expect for a zero day to be announced in the near future when Pre/Process/Post/Final will all go away. In the meantime, the ``csevPreProcess'`, ``csevProcess'`, ``csevPostProcess'`, and ``csevFinalProcess'` events are each dispatched by a handler of the ``csevFrame'` event.

#### A Few Common Idioms to Change

If you use `csBaseEventHandler` you should add this line after `RequestPlugins()`:

      csBaseEventHandler::Initialize(GetObjectRegistry());

The call to `RegisterQueue()` should be changed too:

      if (!RegisterQueue(object_reg, csevAllEvents(object_reg)))
        return ReportError("Failed to set up event handler!");

To quit the application you should now use:

      q->GetEventOutlet ()->Broadcast (csevQuit (object_reg));

Handling a broadcast event can be done like this (note that this will be removed in the near future):

      if (event.Name == csevProcess (object_reg))

Handling a keyboard event can be done like this:

      if (event.Name == csevKeyboardDown (object_reg))

### `csArray<>` Index and Size Type Change

`csArray<>` has been changed to use ``size_t'` instead of ``int'` for array sizes and indices. Probably, the most significant semantic difference of this change is that ``size_t'` is usually unsigned as opposed to ``int'` which is signed.

Read this paragraph carefully. In actual code, this change may result in nothing more than simple-looking compiler warnings. However, it may have caused semantics to change subtly.

This has the greatest impact in the areas discussed below.

#### Iterating Over `csArray<>` Contents

For this purpose, usually, ``int'` typed variables were used for keeping track of the index of the current item of an array iteration. Fixing forward iteration over a `csArray<>` to instead use ``size_t'` is simple:

    csArray<...> a;
    for (int i = 0, n = a.Length(); i < n; i++)
    {
      ...
    }

Is changed to:

    ...
    for (size_t i = 0, n = a.Length(); i < n; i++)
    ...

Backward iteration is a bit more problematic. As mentioned before, ``size_t'` typically is unsigned, so you do not have negative values. This can be a problem in constructs like:

    csArray<...> a;
    for (int i = a.Length() - 1; i >= 0; i--)
    {
      ...
    }

If the ``int'` is changed simply to a ``size_t'`, this `for`-loop misbehaves unexpectedly. When ``i'` becomes 0, the body of the loop is executed correctly. However, decrementing ``i'` will not cause ``i'` to have a negative value--after all, ``size_t'` is unsigned. Instead, decrementing will make ``i'` wrap around from 0 to 0xffffffff (on 32-bit machines). Clearly, this is greater than 0, effectively causing an infinite loop. The same thing also happens when ``a'` has no items (i.e. ``a.Length() == 0'`). Here the -1 in the initialization of ``i'` causes wrap-around.

Possible solutions include:

- Use an `int`-typed counter variable and cast the array length to ``int'`. This is not entirely elegant, but it does the job in most cases.
- Re-write the loop to deal properly with the unsigned nature of ``size_t'`:

      csArray<...> a;
      for (size_t i = a.Length(); i-- > 0;)
      {
        ...
      }

  This code does the same as the ``int'` version above, iterating from ``a.Length() - 1'` to 0, inclusively. It also correctly works in the case ``a.Length() == 0'`. The "trick" is to place the modification of ``i'` as a post-decrement in the loop condition. This way, as soon as ``i'` becomes 0, the loop is terminated. The post-decrement ensures that ``i'` has the expected value in the loop body.

#### Searching

Functions like `csArray<>::FindSortedKey()` and `csArray<>::Find()` used to return -1 to signify that an item was not found. This is still the case, but with a twist. Now, ``(size_t)-1'` is returned. For convenience, a constant, ``csArrayItemNotFound'`, has been added, which has this exact value. It can be used in comparisons to make it clear what is actually being checked.

Apropros comparisons: Recall that ``size_t'` is unsigned, so checking whether an index returned by ``FindSortedKey()'` or ``Find()'` is actually a valid index by testing with ``>= 0'` no longer works since ``(size_t)-1'` is always `>= 0`. Replace such checks with tests of equality against ``csArrayItemNotFound'`:

    csArray<...> a;
    int index = a.Find (...);
    if (index >= 0)
    {
      /* Item found */
      ...
    }
    else
    {
      /* Item not found */
      ...
    }

Must be replaced with:

    csArray<...> a;
    size_t index = a.Find (...);
    if (index != csArrayItemNotFound)
    {
      /* Item found */
      ...
    }
    else
    {
      /* Item not found */
      ...
    }

### Texture and Material Preparation

Texture and material preparation is now fully automatic. It is no longer necessary to prepare a texture or a material before you can use it. It is sufficient simply to register the texture or material. This means that the following functions have been removed (and you can just remove invocations of them from your applications if you used them):

- `iMaterialHandle::Prepare()`
- `iTextureHandle::Prepare()`
- `iTextureManager::PrepareMaterials()`
- `iTextureManager::PrepareTextures()`

### Material Registration

Registering an ``iMaterialWrapper'` with the texture manager is no longer necessary; any such calls can be removed.

### Input Definitions

The file ``csutil/inpnames.h'` has been renamed to ``inputdef.h'`, and the following functions have been removed:

- `csTypeOfInputDef()`
- `csParseKeyDef()`
- `csGetKeyDesc()`
- `csParseMouseDef()`
- `csGetMouseDesc()`
- `csParseJoystickDef()`
- `csGetJoystickDesc()`

These functions allowed you to convert a string such as ``Ctrl`+A`, ``JoystickX'` or ``Alt+Mouse1'` into values describing input events and vice versa.

The way to do this is now, however, is to use ``csInputDefinition'`, which resides in ``csutil/inputdef.h'`. The preferred way to convert a string to a definition is to construct a ``csInputDefinition'` from a ``char const*'`; and the preferred way to convert a definition back to a string (perhaps constructed some other way) is via `csInputDefinition::ToString()`.

There are also static helper methods in ``csInputDefinition'` which accept arguments in a similar way to the old functions. These are convenience methods which perform the work of instantiating the object for you:

- `csInputDefinition::ParseKey()`
- `csInputDefinition::GetKeyString()`
- `csInputDefinition::ParseOther()`
- `csInputDefinition::GetOtherString()`

### Pollution Reduction

In order to avoid polluting the top-level system include directory, the Crystal Space header tree is now installed (via ``make install'` or ``jam install'`) in a subdirectory named ``crystalspace'`, rather than being installed directly in the top-level system directory. For example, assuming the default installation location, the Crystal Space headers are now installed in ``/usr/local/include/crystalspace'`. Previously, they would have been deposited directly into ``/usr/local/include'`. The ``cs-config'` utility script properly returns the new header location in response to the ``--includedir'`, ``--cflags'`, and ``--cxxflags'` options, so this relocation should be mostly transparent to external projects.

The following global header files have been renamed in order to avoid possible conflict with headers installed by other packages.

- `platform.h` => `csplatform.h`
- `qint.h` => `csqint.h`
- `qsqrt.h` => `csqsqrt.h`
- `volatile.h` => `csconfig.h`

The following symbols have been renamed in order to avoid pollution of the global namespace.

- `BadBraces` => `csrxBadBraces`
- `BadPattern` => `csrxBadPattern`
- `BadRepetition` => `csrxBadRepetition`
- `big_endian_float()` => `csBigEndianFloat()`
- `big_endian_long()` => `csBigEndianLong()`
- `big_endian_longlong()` => `csBigEndianLongLong()`
- `big_endian_short()` => `csBigEndianShort()`
- `COMP_BC` => `CS_COMPILER_BCC`
- `COMP_GCC` => `CS_COMPILER_GCC`
- `COMP_VC` => `CS_COMPILER_MSVC`
- `convert_endian()` => `csConvertEndian()`
- `DO_MMX` => `CS_HAVE_MMX`
- `DO_NASM` => `CS_HAVE_NASM`
- `double2longlong()` => `csDoubleToLongLong()`
- `ErrBraces` => `csrxErrBraces`
- `ErrBrackets` => `csrxErrBrackets`
- `ErrCharType` => `csrxErrCharType`
- `ErrCollate` => `csrxErrCollate`
- `ErrEscape` => `csrxErrEscape`
- `ErrParentheses` => `csrxErrParentheses`
- `ErrRange` => `csrxErrRange`
- `ErrSpace` => `csrxErrSpace`
- `ErrSubReg` => `csrxErrSubReg`
- `ErrUnknown` => `csrxErrUnknown`
- `float2long()` => `csFloatToLong()`
- `float2short()` => `csFloatToShort()`
- `get_le_float16()` => `csGetLittleEndianFloat16()`
- `get_le_float32()` => `csGetLittleEndianFloat32()`
- `get_le_long()` => `csGetLittleEndianLong()`
- `get_le_short()` => `csGetLittleEndianShort()`
- `IgnoreCase` => `csrxIgnoreCase`
- `little_endian_float()` => `csLittleEndianFloat()`
- `little_endian_long()` => `csLittleEndianLong()`
- `little_endian_longlong()` => `csLittleEndianLongLong()`
- `little_endian_short()` => `csLittleEndianShort()`
- `long2float()` => `csLongToFloat()`
- `longlong2double()` => `csLongLongToDouble()`
- `MemEntry` => `csMemTrackerEntry`
- `MemoryMapFile()` => `csMemoryMapFile()`
- `MemoryMapWindow()` => `csMemoryMapWindow()`
- `MemTrackerInfo` => `csMemTrackerInfo`
- `MemTrackerModule` => `csMemTrackerModule`
- `MemTrackerRegistry` => `csMemTrackerRegistry`
- `MKDIR()` => `CS_MKDIR()`
- `mmioInfo` => `csMemMapInfo`
- `__NEED_GENERIC_ISDIR` => `CS_USE_CUSTOM_ISDIR`
- `__NEED_OPENDIR_PROTOTYPE` => `CS_WIN32_USE_CUSTOM_OPENDIR`
- `NewLine` => `csrxNewLine`
- `NoError` => `csrxNoError`
- `NoMatch` => `csrxNoMatch`
- `NotBOL` => `csrxNotBOL`
- `NotEOL` => `csrxNotEOL`
- `OS_DOS` => `CS_PLATFORM_DOS`
- `OS_MACOSX` => `CS_PLATFORM_MACOSX`
- `OS_UNIX` => `CS_PLATFORM_UNIX`
- `OS_WIN32` => `CS_PLATFORM_WIN32`
- `PATH_DELIMITER` => `CS_PATH_DELIMITER`
- `PATH_SEPARATOR` => `CS_PATH_SEPARATOR`
- `PROC_arch` => `CS_PROCESSOR_arch` (where ``arch'` is ``X86'`, ``M68K'`, etc.)
- `ProcEventHandler()` => `csProcTexEventHandler`
- `QInt()` => `csQint()`
- `QInt16()` => `csQfixed16()`
- `QInt24()` => `csQfixed24()`
- `QInt8()` => `csQfixed8()`
- `qisqrt()` => `csQisqrt()`
- `QRound()` => `csQround()`
- `qsqrt()` => `csQsqrt()`
- `RegisterMemoryTrackerModule()` => `mtiRegisterModule()`
- `set_le_float16()` => `csSetLittleEndianFloat16()`
- `set_le_float32()` => `csSetLittleEndianFloat32()`
- `set_le_long()` => `csSetLittleEndianLong()`
- `set_le_short()` => `csSetLittleEndianShort()`
- `short2float()` => `csShortToFloat()`
- `TEMP_DIR` => `CS_TEMP_DIR`
- `TEMP_FILE` => `CS_TEMP_FILE`
- `UnMemoryMapFile()` => `csUnMemoryMapFile()`
- `WIN32_VOLATILE` => `CS_WIN32_CSCONFIG`

### ``cssysdef.h'` Changes

The ``CS_SYSDEF_PROVIDE_FACILITY'` macros, which clients would `#define` before including ``cssysdef.h'` in order to alter the behavior of ``cssysdef.h'`, have been removed. Retirement of these macros eliminates the polymorphic behavior of ``cssysdef.h'`, thus helping to pave the way toward eventually pre-compiling Crystal Space's headers in order to reduce overall compilation time. In addition to removing these macros from your code, the following table explains what else (if anything) needs to be done to account for the removal.

`CS_SYSDEF_PROVIDE_ACCESS`

  No additional changes.

`CS_SYSDEF_PROVIDE_ALLOCA`

  Use the ``CS_ALLOC_STACK_ARRAY()'` macro, rather than `alloca()`.

`CS_SYSDEF_PROVIDE_CASE`

  No additional changes.

`CS_SYSDEF_PROVIDE_DIR`

  No additional changes.

`CS_SYSDEF_PROVIDE_EXPAND_PATH`

  No additional changes.

`CS_SYSDEF_PROVIDE_GETCWD`

  No additional changes.

`CS_SYSDEF_PROVIDE_GETOPT`

  Include ``csutil/getopt.h'`.

`CS_SYSDEF_PROVIDE_MKDIR`

  Use the ``CS_MKDIR(path)'` macro to create the directory, rather than the obsolete ``MKDIR()'` macro.

`CS_SYSDEF_PROVIDE_PATH`

  No additional changes.

`CS_SYSDEF_PROVIDE_SELECT`

  No additional changes.

`CS_SYSDEF_PROVIDE_SOCKETS`

  Include ``csutil/sockets.h'`.

`CS_SYSDEF_PROVIDE_SOFTWARE2D`

  No additional changes.

`CS_SYSDEF_PROVIDE_TEMP`

  Use the ``CS_TEMP_DIR'` and ``CS_TEMP_FILE'` macros, rather than the obsolete ``TEMP_DIR'` and ``TEMP_FILE'` macros.

`CS_SYSDEF_PROVIDE_UNLINK`

  No additional changes.

`CS_SYSDEF_VFS_PROVIDE_CHECK_VAR`

  No additional changes.

The age-old restriction that ``cssysdef.h'` could be included only by source files (``.cpp'`) has been lifted. This restriction was an unfortunate side-effect of the polymorphic behavior of ``cssysdef.h'` in the presence of various ``CS_SYSDEF_PROVIDE_FACILITY'` macros. It is now safe, even recommended, to include ``cssysdef.h'` in header files (``.h'`). Doing so helps to make header files more self-contained, thus reducing the burden of clients of those headers.

### Library Consolidation

In order to simplify end-user documentation and client usage, the Crystal Space link libraries ``csutil'`, ``csgeom'`, ``csgfx'`, and ``cstool'` have been merged into a single master library named ``crystalspace'` (i.e. ``libcrystalspace.a'` or ``crystalspace.lib'`).

The tools ``cs-config'` and ``jamtemplate'` (see section Creating an External Crystal Space Application), documentation, and all other client-oriented utilities have been updated appropriately to reflect this change. If you had installed Crystal Space previously, you should manually removed the now obsolete installed libraries from the installation location (typically, ``${prefix}/lib'`).

Developers of Crystal Space itself should note that the sources and headers continue to reside in their separate ``csutil'`, ``csgeom'`, etc., directories; and (importantly) the modules themselves remain conceptually distinct. This will not change. The consolidation of the physical link library was an end-user convenience.

### Convenience Classes and Libraries

Crystal Space now publishes several convenience classes and libraries which eliminate much of the drudgery associated with implementing SCF interfaces in certain types of common plugin modules. For example, the ``csGraphics2D'` class implements the ``iGraphics2D'` interface and provides much of the functionality common to most canvases. Likewise, the ``csGraphics3D'` class implements the ``iGraphics3D'` interface and provides much functionality common to renderers. You are not required to utilize these implementations when authoring your own plugins, but they are available for your convenience.

Most of these newly published facilities are bundled in the consolidated master ``crystalspace'` library, but a few are provided in separate libraries because they rely upon external resources which may not be present on all platforms or in all installations. The convenience libraries are:

`crystalspace`

  Canvas, image loader, particle system, renderer, shader, sound loader, and sound renderer support, in addition to the normal Crystal Space classes and utilities.

`crystalspace_directx`

  DirectX support.

`crystalspace_macosx`

  MacOS/X canvas support.

`crystalspace_opengl`

  OpenGL support.

`crystalspace_python`

  Python support.

`crystalspace_windows`

  Windows support.

For a complete list of available convenience classes, consult the header files in the subdirectories of ``CS/include/csplugincommon'`.

### Convenience Headers

For convenience, several top-level master header files have been added to the project. These should simplify client usage by allowing users to choose the level of granularity which suits them best. The list of new header files follows.

`crystalspace.h`

  Nearly all public headers in entire Crystal Space SDK.

`csgeom.h`

  Content of ``CS/include/csgeom'`.

`csgfx.h`

  Content of ``CS/include/csgfx'`.

`csplugincommon.h`

  Content of ``CS/include/csplugincommon'`.

`cstool.h`

  Content of ``CS/include/cstool'`.

`csutil.h`

  Content of ``CS/include/csutil'`.

`iaws.h`

  Content of ``CS/include/iaws'`.

`iengine.h`

  Content of ``CS/include/iengine'`.

`igeom.h`

  Content of ``CS/include/igeom'`.

`igraphic.h`

  Content of ``CS/include/igraphic'`.

`imap.h`

  Content of ``CS/include/imap'`.

`imesh.h`

  Content of ``CS/include/imesh'`.

`inetwork.h`

  Content of ``CS/include/inetwork'`.

`isound.h`

  Content of ``CS/include/isound'`.

`itexture.h`

  Content of ``CS/include/itexture'`.

`iutil.h`

  Content of ``CS/include/iutil'`.

`ivaria.h`

  Content of ``CS/include/ivaria'`.

`ivideo.h`

  Content of ``CS/include/ivideo'`.

Users new to the SDK will probably want to include ``crystalspace.h'` since it is simplest; whereas more advanced users may want to include ``csutil.h'`, ``cstool.h'`, etc.; and power users can continue to include only the individual headers required by a particular piece of code.

As a corollary, the old ``CS/include/css.h'` header, which included many, though not all Crystal Space header files, has been removed. If you require this type functionality from a header, then include the new ``crystalspace.h'` instead.

Be aware that there is a very small set of public headers not included in any of the master headers. These are omitted from the master headers because they reference external resources which might not be known or available to all clients of the master headers. Clients requiring these special-case headers will need to include them manually, on an as-needed basis, and arrange that the build system has sufficient knowledge about the external resources to satisfy the dependencies at build time. The list of headers which are excluded from the master headers follows.

`csplugincommon/directx/*.h`

  DirectX-specific.

`csplugincommon/macosx/*.h`

  MacOS/X-specific.

`csplugincommon/opengl/*.h`

  OpenGL-specific.

`csplugincommon/win32/*.h`

  Windows-specific.

`csutil/archive.h`

  Requires zlib indirectly via ``csutil/zip.h'`.

`csutil/getopt.h`

  Conflicts with platform-supplied ``<getopt.h>'`.

`csutil/zip.h`

  Requires zlib; http://www.gzip.org/zlib/

`inetwork/vosapi.h`

  Requires VOS; http://www.interreality.org/

`ivaria/ode.h`

  Requires ODE; http://www.ode.org/

`ivideo/wxwin.h`

  Requires wxWidgets; http://www.wxwidgets.org/

As an example, if you need access to the ``iWxWindow'` interface, then you must include ``ivideo/wxwin.h'` manually; it will not be included as part of ``crystalspace.h'` or ``ivideo.h'`. Furthermore, you will need to let the build system know where it can find the wxWidgets resources (headers and libraries). Typically, this is done by adding a wxWidgets check to your project's ``configure'` script; emitting the results of the check to your ``Jamconfig'` file with the `CS_EMIT_BUILD_RESULT()` Autoconf macro; and finally utilizing the result of that check in your project's ``Jamfile'` by invoking the Jam rule ``ExternalLibs'`. For MSVC project files, the location of the wxWidgets resources will have to be added as additional include directories and additional library directories, in the project settings or globally, to ensure that MSVC will be able to find them.

### Procedural Texture Relocation

Implementations of the standard procedural textures (dots, fire, plasma, etc.) now reside directly in the ``stdpt'` plugin (``CS/plugins/proctex/standard'`), rather than in the ``cstool'` module. Consequently, the following previously public headers are no longer available:

- `cstool/prdots.h`
- `cstool/prfire.h`
- `cstool/prplasma.h`
- `cstool/prsky.h`
- `cstool/prwater.h`

Likewise, procedural textures can no longer be allocated directly (for instance, via ``new csProcFire'`). Instead, you must now use the plugin system to create such textures. For example:

    csRef<iPluginManager> plugin_mgr(
      scfQueryInterface<iPluginManager> (object_reg));
    csRef<iTextureType> type (csQueryPluginClass<iTextureType> (plugin_mgr,
      "crystalspace.texture.type.fire"));
    if (!type)
    {
      type = csLoadPlugin<iTextureType> (plugin_mgr,
        "crystalspace.texture.type.fire");
    }
    csRef<iTextureFactory> fireFact = type->NewFactory();
    csRef<iTextureWrapper> tex = fireFact->Generate();
    csRef<iFireTexture> fire = scfQueryInterface<iFireTexture> (tex);

Various procedural textures may or may not implement their own custom SCF interfaces beyond the normal interfaces implemented by all procedural textures. In the example above, the "fire" texture implements the specialized ``iFireTexture'`.

### Mouse Corrections

Mouse buttons and axes used to be enumerated basis 1 (first mouse button was 1, Y axis was 2, etc). In keeping with good C/C++/Java/etc coding style, they are now basis-0 (first mouse button is 0, Y axis is 1, etc).

### Joystick Corrections

The implementation of ``iJoystickDriver'` has been fixed to treat joystick numbers consistently. Previously, on account of buggy implementation, some parts of the driver considered joystick numbers 0-based, while other parts considered them 1-based. It now uniformly treats joystick numbers as 0-based. This is consistent with button numbers for joysticks and mice, which are also basis-0.

### `iGraphics2D` Alpha Color Support

``iGraphics2D'` now supports an alpha channel. `iGraphics2D::FindRGB()` accepts an optional alpha value (0 being completely transparent, and 255 being fully opaque) which defaults to 255. All canvases will then blend the pixels appropriately if the color depth is 15 bpp or higher. Furthermore, as `iGraphics2D::Write()` also handles alpha in both foreground and background colors, it is recommended for transparent backgrounds, instead of using ``-1'` as the color value, to obtain a color value from `FindRGB()` that has the same R, G, B components as the foreground color, but an alpha component of 0.

### ``csutil/garray.h'` Deprecated

The ``csutil/garray.h'` file, containing the class `csDirtyAccessArray<>`, has been deprecated in favor of the more sensible file name ``csutil/dirtyaccessarray.h'`. No functional changes have been made to the class.

### `csList<>::Iterator` Normalization

The behavior of `csList<>::Iterator` has been normalized so that it functions identically to all other iterators in Crystal Space. In the past, a newly created `csList<>::Iterator` already pointed at the first element in the container. This differed from all other iterator implementations, in which the first element, like all other elements, is accessed by an invocation of `Next()`.

Old code which accessed the elements of a `csList<>::Iterator` required a non-standard idiom, such as:

    csList<sometype> list = ...;
    csList<sometype>::Iterator it(list);
    if (it.HasCurrent())
    {
      do_something(*it);         // First value.
      while (it.HasNext())
      {
        do_something(it.Next()); // Remaining values.
      }
    }

Or, the slightly less complicated, though still somewhat convoluted:

    csList<sometype>::Iterator it(list);
    while (it.HasCurrent())
    {
      do_something(*it);
      it.Next();
    }

Following normalization, `csList<>::Iterator` now works like all other iterators throughout the toolkit. In particular, for forward iteration, all elements can be accessed via the standard `HasNext()` / `Next()` idiom:

    csList<sometype>::Iterator it(list);
    while (it.HasNext())
    {
      do_something(it.Next());
    }

Likewise, for backward iteration, the `HasPrevious()` / `Previous()` idiom works in the obvious and expected inverse fashion.

Finally, `csList<>::Iterator::Next()` and `Previous()` now return references to contained elements, rather than pointers. This makes the interface of `csList<>::Iterator` internally consistent, as well as consistent with other iterators throughout the toolkit, in which these methods return references.

### `iDocument` Changes

The `iDocument::Parse()` method now accepts an optional argument indicating whether or not extraneous whitespace in ``CS_NODE_TEXT'` nodes should be condensed. Most implementations of ``iDocument'` will attempt to respect this option if possible. For implementations where it does not make sense, the option will be ignored.

Previously, XML-based implementations of the ``iDocument'` interface condensed whitespace in ``CS_NODE_TEXT'` nodes at `Parse()` time. This is no longer the case. Whitespace is now preserved by default. If the new behavior is unsuitable for your case, use the new argument to `iDocument::Parse()` to indicate that whitespace should be condensed. This change was made in order to conform to the latest XML specification which states that XML scanners must preserve whitespace by default. Consult the following documents for more information regarding this issue.

http://www.w3.org/TR/REC-xml/#sec-white-space
http://www.xml.com/axml/notes/AllWSAlways.html

### Naming Normalization

The following SCF class names have been normalized in order to be consistent with the names of all other available "null" and "multiplexer" plugins:

- `crystalspace.mesh.object.nullmesh` => `crystalspace.mesh.object.null`
- `crystalspace.graphics2d.null2d` => `crystalspace.graphics2d.null`
- `crystalspace.documentsystem.multiplex` => `crystalspace.documentsystem.multiplexer`
- `crystalspace.graphic.image.io.multiplex` => `crystalspace.graphic.image.io.multiplexer`

For API consistency and uniformity between container classes, the following methods have been renamed:

- `csArray<>::Length()` => `csArray<>::GetSize()`
- `csArray<>::SetLength()` => `csArray<>::SetSize()`
- `csHash<>::DeleteAll()` => `csHash<>::Empty()`
- `csHash<>::In()` => `csHash<>::Contains()`
- `csHash<>::PutFirst()` => `csHash<>::PutUnique()`
- `csList<>::FetchPrev()` => `csList<>::FetchPrevious()`
- `csList<>::HasPrev()` => `csList<>::HasPrevious()`
- `csSet<>::DeleteAll()` => `csSet<>::Empty()`
- `csSet<>::In()` => `csSet<>::Contains()`
- `csString::Clear()` => `csString::Empty()`
- `csString::FindReplace()` => `csString::ReplaceAll()`
- `csString::FindStr()` => `csString::Find()`
- `csString::Reclaim()` => `csString::ShrinkBestFit()`
- `iString::FindReplace()` => `iString::ReplaceAll()`
- `iString::FindStr()` => `iString::Find()`
- `iStringArray::DeleteAll()` => `iStringArray::Empty()`
- `iStringSet::Clear()` => `iStringSet::Empty()`

In most cases, the old names listed above are still recognized for backward compatibility, but they are deprecated, so you probably ought to convert to the new API at some point. The API of most of the container classes also has been expanded, so you may want to study the API reference manual to learn about newly available functionality.

Likewise, the following global functions have been renamed:

- `csFindReplace()` => `csReplaceAll()`

For consistency with like-named methods in other SCF interfaces, the following ``iImage'` methods have been renamed:

- `GetKeycolor()` => `GetKeyColor()`
- `HasKeycolor()` => `HasKeyColor()`

Various methods in ``csIntersect3'` have been renamed in order to improve consistency and clarity. In addition, some arguments have been reversed order so that, for example, a method named `SegmentTriangle()` will receive first the segment argument followed by the triangle argument.

- `AxisPlane()` => `SegmentAxisPlane()`
- `IntersectPolygon()` => `PlanePolygon()` (plane version)
- `IntersectPolygon()` => `SegmentPolygon()` (segment version)
- `IntersectSegment()` => `SegmentFrustum()`
- `IntersectTriangle()` => `SegmentTriangle()`
- `Plane()` => `SegmentPlane()`
- `Planes()` => `SegmentPlanes()` (segment version)
- `Planes()` => `ThreePlanes()` (three planes version)
- `XFrustum()` => `SegmentXFrustum()`
- `XPlane()` => `SegmentXPlane()`
- `YFrustum()` => `SegmentYFrustum()`
- `YPlane()` => `SegmentYPlane()`
- `Z0Plane()` => `SegmentZ0Plane()`
- `ZPlane()` => `SegmentZPlane()`

In addition to that the function `csMath3::FindIntersection()` has been removed and is replaced with a new `csIntersect3::TriangleTriangle()` routine which is faster and more correct.

The same improvements have been made to `csIntersect2`:

- `IntersectPolygon()` => `PlanePolygon()` (plane version)
- `Lines()` => `LineLine()` (plane version)
- `Plane()` => `SegmentPlane()`
- `PlaneNoTest()` => `SegmentPlaneNoTest()`
- `Planes()` => `PlanePlane()`
- `Segments()` => `SegmentSegment()` (plane version)

The following configuration control macros (most of which are emitted to ``csconfig.h'` by the Crystal Space ``configure'` script) have been renamed in order to improve internal naming consistency, and to conform more closely to naming scheme used by Autoconf.

- `CS_HAS_CAL3D` => `CS_HAVE_CAL3D`
- `CS_HAS_CMATH_H` => `CS_HAVE_CMATH_H`
- `CS_HAS_GLHANDLEARB_T` => `CS_HAVE_GLHANDLEARB_T`
- `CS_HAS_INT64_C` => `CS_HAVE_INT64_C`
- `CS_HAS_INTMAX_T` => `CS_HAVE_INTMAX_T`
- `CS_HAS_INTPTR_T` => `CS_HAVE_INTPTR_T`
- `CS_HAS_INTTYPES_H` => `CS_HAVE_INTTYPES_H`
- `CS_HAS_MACHINE_SOUNDCARD_H` => `CS_HAVE_MACHINE_SOUNDCARD_H`
- `CS_HAS_MEMORY_MAPPED_IO` => `CS_HAVE_MEMORY_MAPPED_IO`
- `CS_HAS_POSIX_MMAP` => `CS_HAVE_POSIX_MMAP`
- `CS_HAS_REGEX` => `CS_HAVE_REGEX`
- `CS_HAS_SOUNDCARD_H` => `CS_HAVE_SOUNDCARD_H`
- `CS_HAS_STDINT_H` => `CS_HAVE_STDINT_H`
- `CS_HAS_SYS_PARAM_H` => `CS_HAVE_SYS_PARAM_H`
- `CS_HAS_SYS_SOUNDCARD_H` => `CS_HAVE_SYS_SOUNDCARD_H`
- `CS_HAS_WCHAR_H` => `CS_HAVE_WCHAR_H`
- `CS_RTLD_NOW_AVAILABLE` => `CS_HAVE_RTLD_NOW`

Likewise, the same normalization has been applied to the ``CS_USE_FAKE_feature'` macros published by the ``configure'` script, and the boolean sense of these control macros has been reversed to account for the name change.

- `CS_USE_FAKE_EXPLICIT_KEYWORD` => `CS_HAVE_CXX_KEYWORD_EXPLICIT`
- `CS_USE_FAKE_MATH_H_FLOAT_FUNCS` => `CS_HAVE_MATH_H_FLOAT_FUNCS`
- `CS_USE_FAKE_SOCKLEN_TYPE` => `CS_HAVE_SOCKLEN_T`
- `CS_USE_FAKE_TYPENAME_KEYWORD` => `CS_HAVE_CXX_KEYWORD_TYPENAME`
- `CS_USE_FAKE_WCHAR_TYPE` => `CS_HAVE_WCHAR_T`
- `CS_USE_FAKE_WCSLEN` => `CS_HAVE_WCSLEN`

For consistency with like-named macros (such as ``CS_PROCESSOR_NAME'` and ``CS_PROCESSOR_arch'`), the following control macros have been renamed:

- `CS_PROCSIZE` => `CS_PROCESSOR_SIZE`

The `csOrdering<>` template has been renamed to the more general `csComparator<>` to reflect the fact that this template can perform both ordering and equality comparisons.

### Default `csHash<>` (and `csHashReversible<>`) Table Size

The default hash table size and grow rate has been reduced from 257 and 64 to 23 and 5, respectively, to have hashes use less memory. If a hash is expected to contain a large quantity of elements, those two parameters can be tweaked upon construction of a `csHash<>` or `csHashReversible<>`. Consult the Public API Documentation of `csHash<>` for more information.

### `iTextureManager::FreeImages()` Removal

`iTextureManager::FreeImages()` has been removed. It was used to release the ``iImage'` objects associated with textures with the purpose of freeing up memory. This happens automatically now; the images associated with a texture are released by the renderer as soon as the image data is converted into the internal texture format (that is, uploaded to the graphics hardware).

### Java Bindings

The Java bindings for Crystal Space have been fully integrated into the project and are now well-supported. It is now possible to write Crystal Space program entirely in Java. See section Java Bindings.

The Crystal Space Java classes now reside in a package named ``org.crystalspace3d'` in order to reflect Crystal Space's new official domain name "crystalspace3d.org". This replaces the older package name ``com.crystalspace'`, which itself replaced the much older name ``net.sourceforge.crystal'`.

### VFS Changes

At initialization time, VFS now merges all ``vfs.cfg'` files located during its start-up scan. Previously, VFS stopped scanning at the first discovered ``vfs.cfg'`, and loaded only that file. During the start-up scan, it searches for a file named ``vfs.cfg'` in the application resource directory (`csGetResourceDir()`), then in the directory containing the application (`csGetAppDir()`), and finally in the Crystal Space installation directory (`csGetConfigPath()`). The full set of directories mounted by VFS following the initial configuration file scan is the union of the entries in all of the discovered ``vfs.cfg'` files. If there are conflicting entries, then mounts and variable assignments specified in configuration files discovered earlier in the scan take precedence over those discovered later.

### `iEvent` Changes

#### Property Bags

The `iEvent::Find()` method was renamed to `Retrieve()` and exhibits different return value semantics. Rather than returning a mere boolean result, it now returns one of the ``csEventError'` enumeration constants. Of particular note, in the case of success, `csEventErrNone` is returned, which has a value of 0. This success value could be misinterpreted as "false" by the unwary when fixing code to deal with this semantic change. Conditionals which test if retrieval of an attribute succeeded must be changed to take this new semantic into account. For instance, code such as the following:

    iEvent* ev = ...;
    if (ev->Find(...))
    {
      ...
    }

must be changed to perform an explicit test on the return value of `Retrieve()`, rather than relying upon default boolean semantics:

    if (ev->Retrieve(...) == csEventErrNone)
    {
      ...
    }

#### Mouse, Joystick, and Command event properties

The ``union'` containing the ``Mouse'`, ``Joystick'`, and ``Command'` structures has been removed; all event attributes are now stored and accessed using the `Add()` and `Retrieve()` mechanisms. To ease access to event data, use the static methods of the ``csMouseEventHelper'`, ``csJoystickEventHelper'`, and ``csCommandEventHelper'` classes. For example, code such as the following:

    iEvent* ev = ...;
    let X = ev->Mouse.X;

should be changed to:

    iEvent* ev = ...;
    let X = csMouseEventHelper::GetX(ev);

See the API documentation for details.

#### Multiple mice

There is now support for handling input from more than one mouse. You can retrieve the identity (basis 0) of the mouse producing a mouse event with `csMouseEventHelper::GetNumber()`.

#### Joystick and Mouse axes

Joysticks can now have up to ``CS_MAX_JOYSTICK_AXES'` axes, and mice can have up to ``CS_MAX_MOUSE_AXES'`. Their values should be accessed using the `csJoystickEventHelper::GetAxis()` and `csMouseEventHelper::GetAxis()` functions, respectively, where both devices and axes are enumerated basis 0. Each helper class also has `GetX()` and `GetY()` methods available; for joystick events, these are deprecated.

### Old Renderer Architecture Removal

The old rendering architecture along with the old renderer plugins have been removed. Additionally, a few plugins, applications, classes, and methods have been deprecated because they are not applicable to the new rendering architecture. The results of the old renderer removal are summarized below.

#### Removed Plugins

The following plugin modules have been removed:

- `terrfunc` (`crystalspace.mesh.object.terrfunc`)
- Old `gl3d` (``plugins/video/renderer/opengl'`)
- Old `soft3d` (``plugins/video/renderer/software'`)
- Old `null3d` (``plugins/video/renderer/null'`)

#### Removed Application

The ``perftest'` application has been removed, since it is no longer has any purpose. For the future the ``csbench'` application should be extended to provide more information.

#### Removed and Renamed Files

The following files were removed:

- `include/ivideo/vbufmgr.h`

The following files in ``data/shader'` were renamed:

- `or_lighting.xml` => `std_lighting.xml`
- `or_lighting_detail.xml` => `std_lighting_detail.xml`
- `or_lighting_detail_add.xml` => `std_lighting_detail_add.xml`
- `or_lighting_detail_alpha.xml` => `std_lighting_detail_alpha.xml`
- `or_lighting_portal.xml` => `std_lighting_portal.xml`

#### Removed Methods and Classes

The following methods have been removed from the ``iGraphics3D'` interface:

- `ClearCache()`
- `CloseFogObject()`
- `DrawFogPolygon()`
- `DrawPolygonDebug()`
- `DrawPolygonFX()`
- `DrawPolygonMesh()`
- `DrawTriangleMesh()`
- `DumpCache()`
- `GetVertexBufferManager()`
- `GetZBuffAt()`
- `OpenFogObject()`

From ``iRenderView'`, the following fog-related methods have been removed. Fog is now calculated within the renderer.

- `CalculateFogMesh()`
- `CalculateFogPolygon()`

From ``iMeshObject'` and ``iParticle'`, the following rendering-related methods have been removed:

- `Draw()`
- `DrawTest()`

From ``iParticleState'`, the following methods have been removed. Use the methods with the same name from ``iMeshObject'` instead.

- `SetColor()`
- `GetColor()`
- `SetMaterialWrapper()`
- `GetMaterialWrapper()`

Apart from these methods, the following classes and structures have been removed or have become private, and are no longer available to client code:

- `G3DFogInfo`
- `G3DPolygonDFP`
- `G3DPolygonDPFX`
- `G3DPolygonDPF`
- `G3DPolygonDP`
- `G3DPolygonMesh`
- `G3DTriangleMesh`

Some methods from ``iSprite3DState'` have been removed that basically provided functionality which was also already available through ``iMeshObject'`:

- `SetBaseColor()`. Use `SetColor()` from ``iMeshObject'`.
- `GetBaseColor()`. Use `GetColor()` from ``iMeshObject'`.

Likewise, the `GetFactory()` method has been removed from ``iThingState'`. Equivalent functionality can be achieved by using `GetFactory()` from ``iMeshObject'` and querying the returned object for the ``iThingFactoryState'` interface. Example:

      csRef<iThingFactoryState> thing_fact_state =
      	scfQueryInterface<iThingFactoryState> (mesh->GetMeshObject ()
    	->GetFactory ());

### Query Macros

The macro `CS_QUERY_REGISTRY_PLUGIN()` has been added to ``iutil/plugin.h'`. This is a convenience macro which embodies the common idiom of first querying the object-registry for an object implementing some interface, and then asking the plugin manager to load a plugin supplying the desired object if it was not found in the object-registry. It also registers the object with the object-registry if the plugin manager loads it successfully.

### Random Number Generator Changes

The global function `csFastRandFloat()` has been retired. In its stead is the new instantiable class ``csRandomFloatGen'`, which is modeled after the ``csRandomGen'` class. Unlike the old `csFastRandFloat()` function which was shared by all clients, instances of ``csRandomFloatGen'` can be controlled and seeded individually, thus making it far more flexible and useful. (Note that the more general-purpose ``csRandomGen'` class is also able to vend floating point numbers.)

### ``iImage'` Changes

The ``iImage'` interface has been reduced to a level where it merely serves as a container for pixel data; however, the image editing functionality was only relocated, not removed.

Forbidding direct manipulation of an ``iImage'`'s pixel data has the following consequences:

- The `Clone()` function was removed. The ``csImageMemory'` class provides a constructor that copies the pixel data from another ``iImage'` object, providing a functionality equal to `Clone()`.
- To edit the pixel data of an image, create a clone of an image (e.g. a ``csImageMemory'` as mentioned above) and manipulate the data in the newly cerated instance.
- If the image data is needed in another format, as the `SetFormat()` call has been removed from the interface.
- The image editing functionality found in methods such as `Rescale()`, `Sharpen()` was moved into the ``csImageManipulate'` class.
- The `CopyXXX()` method that copied an image into another are now provided by ``csImageMemory'`.

As a side-effect of these changes, the ``csImageFile'` and ``csImageMemory'` were merged and the former removed.

### ``iMaterialList'` Change

The function `iMaterialList::NewMaterial()` now needs an additional name parameter. It is not recommended to change the name later.

### `iObjectModel` Change

The function `iObjectModel::GetObjectBoundingBox()` only has one parameter now. The optional ``type'` parameter has been removed as it was not implemented anywhere. In addition to that the constants `CS_BBOX_NORMAL`, `CS_BBOX_ACCURATE`, and `CS_BBOX_MAX` are also removed.

### `iImageIO::Load()` Parameter Change

`iImageIO::Load()` now requires the image source data in an ``iDataBuffer'` object, instead of separate ``buffer'` and ``size'` parameters.

### ``iLight'` Changes

The ``iLight'` and its implementation (``csLight'`) have been extended to also handle spot- and directional-lights. Note that the accual computation of lighting does not yet support these, however the engine can now store and handle the required data.

There have also been two smaller changes to the interface to make it more coherent. The influence radius have been renamed cut-off distance, and thus the methods `GetInfluenceRadius()` and `SetInfluenceRadius()` have been renamed accordingly to `GetCutoffDistance()` and `SetCutoffDistance()`, respectively. Also, `SetAttenuation()` has been renamed to `SetAttenuationMode()` in order to avoid confusion with other similary named methods. For the `CS_ATTN_LINEAR` attenuation type the specification has changed slightly. As a default, the distance where light goes out is same as the cut-off distance, but this can be changed by altering the first attenuation constant. See comments in ``CS/include/iengine/light.h'` for exact details of the different attenuation modes.

### `CS_DECLARE_OBJECT_ITERATOR()` Removal

The ``iObject'` iterator creation macro `CS_DECLARE_OBJECT_ITERATOR()` has been replaced by the templated class `csTypedObjectIterator<>`. Given existing code, such as:

    iObject* parent = ...;
    CS_DECLARE_OBJECT_ITERATOR(MyFooIter, iFoo);
    MyFooIter iter(parent);
    while (iter.HasNext())
    {
      iFoo* foo = iter.Next();
      ...
    }

Revise the code by instantiating the new template class:

    typedef csTypedObjectIterator<iFoo> MyFooIter;
    MyFooIter iter(parent);
    while (iter.HasNext())
    {

Or, even simpler without the ``typedef'`:

    csTypedObjectIterator<iFoo> iter(parent);
    while (iter.HasNext())
    {

### Reference Count Automation

For consistency with the bulk of the Crystal Space API, and in order to simplify reference-count management, the following methods have been changed to return `csRef<>` rather than raw pointers of which the client had to dispose manually via `DecRef()`.

- `iEmitFactoryState::CreateBox()`
- `iEmitFactoryState::CreateCone()`
- `iEmitFactoryState::CreateCylinder()`
- `iEmitFactoryState::CreateCylinderTangent()`
- `iEmitFactoryState::CreateFixed()`
- `iEmitFactoryState::CreateLine()`
- `iEmitFactoryState::CreateMix()`
- `iEmitFactoryState::CreateSphere()`
- `iEmitFactoryState::CreateSphereTangent()`
- `iHazeHullCreation::CreateBox()`
- `iHazeHullCreation::CreateCone()`

### Render Buffer Changes

The ``iRenderBuffer'` interface was made renderer-independant. Consequently, creation was moved out of ``iGraphics3D'` and into ``csRenderBuffer'` in the ``csgfx'` module (see ``csgfx/renderbuffer.h'`). The semantics of the parameters have changed too: notably, instead of specifying the byte size of a buffer, the element count is specified. The same change has been made to `CopyToBuffer()` (which has been renamed to `CopyInto()` to enforce human correction of the arguments).

More serious changes involve the publication of render buffers by renderers. Previously meshes provided render buffers via name, and these were mapped using name <-> OpenGL name mapping. But most meshes only provided a few standard-named buffers (such as, ``vertices'`, ``texcoords'`, etc.), and the mapping itself took some time (5%+ per frame). This has been reworked.

Now, meshes can provide a set of 16 buffers in a fixed structure. Meshes can provide ``index'`, ``position'` (vertices), ``normal'`, ``color'`, ``color_lighting'` (pre-lit colors), ``texcoord0'`, ``texcoord1'`, ``texcoord2'`, ``texcoord3'`, ``texcoord_lightmap'`, ``generic0'`, ``generic1'`, ``generic2'`, ``generic3'`, ``tangent'` and ``binormal'` buffers. At the very least, meshes should provide ``index'`, ``position'`, and if possible ``texcoordn'`. The old system with custom named buffers is also supported.

Both kinds of buffers can be mapped, and the destinations for both kinds of buffers are the same (listed here): ``position'`, ``normal'`, ``color'`, ``primary color'` (alias for ``color'`), ``secondary color'`, ``texture coordinate n'` (where 0 <= n < texture units; ``texture coordinate'` is alias for n = 0), and ``attribute n'` (where 0 <= n < 16). Note that you can not map buffers of different kinds (the ``normal'` and the custom buffers) to same destination; the result is undefined).

The normal buffers are named ``position'`, ``normal'`, ``color'`, ``primary color'`, ``lit color'`, ``texture coordinate n'` (where 0 <= n < 3), ``texture coordinate lightmap'`, ``generic n'` (where 0 <= n < 3), ``binormal'`, and ``tangent'`. These appear in the ``source="..."'` tag within the XML shader description.

Mapping of custom buffers is accomplished as so:

    <buffer
      customsource="custombuffername"
      destination="texture coordinate 1"
    />

And, mapping of a normal buffer is done this way:

    <buffer
      source="tangent"
      destination="texture coordinate 2"
    />

As a convenience, three buffers are mapped automatically by default (as long as the mesh provides them). They are:

- ``position'` => ``position'`
- ``color'` => ``primary color'`
- ``texture coordinate 0'` => ``texture coordinate 0'`

### String Changes

The class hierarchy of ``csString'` has changed. Most functionality is now provided by the new superclass ``csStringBase'`. From this, `csStringFast<>` is subclassed, and ``csString'` descends from `csStringFast<>`. `csStringFast<>` is a templated class featuring an internal character buffer which is used instead of dynamically heap-allocated memory when the string length is sufficently short (as controlled by the class template argument). This generalization can make ``csStringFast<>'` (and its subclass ``csString'`) much faster when used as automatic (stack-allocated) variables, even when declared inside ``for{}'`-loops, since slow heap-allocation often can be avoided.

For simplification purposes, several methods have been removed from ``csString'` and ``iString'` (when present):

- Static `PadFoo()` methods. The same functionality can be achieved with the remaining instance `PadFoo()` methods.
- `AsPadFoo()` instance methods. The same functionality can be achieved with the remaining instance `PadFoo()` methods.
- Static integer and float `Format()` methods. The same functionality can be achieved by utilizing the remaining `Replace()` or `Format()` methods.
- `SetGrowsExponentially()` and `GetGrowsExponentially()`. The same functionality is provided by `SetGrowsBy(0)` and `GetGrowsBy()`.

### RAPID Collision Detection Plugin Removal

The RAPID collision detection plugin has been removed. In addition to being slower than the OPCODE plugin and consuming more memory, its license prevented its use in commercial applications. You should instead now use the OPCODE plugin.

### 64-Bit Portability Changes

Some changes have been made to the Crystal Space API in order to better support 64-bit hardware, which is now becoming common. Additional changes to improve 64-bit support have also been made internally, but the internal changes essentially are transparent to external clients.

The most significant change to the API involves methods and classes dealing with data opaquely. Historically, opaque data has been handled using ``void*'`, and programmers would cast numbers, booleans, and pointers to ``void*'` when it was necessary to deal with the data in an opaque fashion. This technique, however, is not portable to 64-bit platforms. For this reason, the new standard type ``intptr_t'` was introduced. This type is guaranteed to be large enough to store any integral numeric or pointer value regardless of the machine's word size.

Crystal Space now uniformly uses ``intptr_t'`, rather than ``void*'`, when dealing with opaque data. Upgrading your code to reflect this change is usually quite simple. Where your code presently declares a variable or casts a value to ``void*'`, change it to ``intptr_t'`. Likewise, ``void**'` becomes ``intptr_t*'`. For example:

    iGraphics2D canvas = ...;
    iEventOutlet* outlet = ...;
    outlet->Broadcast(cscmdCanvasExposed, (void*)canvas);

Becomes:

    outlet->Broadcast(cscmdCanvasExposed, (intptr_t)canvas);

The event system is impacted by this change. Specifically, the following methods and data members now deal with ``intptr_t'` rather than ``void*'` for the opaque "info" member of `csevCommand`-type events.

- `csEvent::csEvent()`
- `csEventCommandData::Info`
- `iEventOutlet::Broadcast()`
- `iEventOutlet::ImmediateBroadcast()`

The AWS plugin (Alternate Windowing System) and its interfaces have been been updated for 64-bit platform conformance. Specifically, the following methods now deal with ``intptr_t'` rather than ``void*'` for all of AWS's opaque data needs.

- `iAwsComponent::GetProperty()`
- `iAwsComponent::SetProperty()`
- `iAwsParmList::AddOpaque()`
- `iAwsParmList::GetOpaque()`
- `iAwsSink::RegisterTrigger()`
- `iAwsSinkManager::CreateSink()`

AWS callback functions (triggers) are likewise impacted. You need to change the declaration of your triggers to use ``intptr_t'` rather than ``void*'`. For example:

    void MyTrigger(void* sink, iAwsSource* source);

Becomes:

    void MyTrigger(intptr_t sink, iAwsSource* source);

Since converting client AWS code to the new API can be rather onerous on account of the amount of repetitious manual labor involved, the old ``void*'` API is still present in AWS, though heavily deprecated. In the interests of 64-bit portability, the old API will be removed at some point in the future. You are encouraged, therefore, to convert your code to the new API. As an aid to clients in upgrading their code to the new API, one of two control macros can be defined which will help to isolate code which needs to be updated. Defining ``AWS_OBSOLETE_VOIDP'` (via ``#define'` before including ``iaws/aws.h'`) removes from the API all methods dealing with ``void*'`, thus invocations of any such methods will result in compilation errors. Alternately, defining ``AWS_DEPRECATE_VOIDP'`, will cause invocations of methods dealing with ``void*'` to generate compilation warnings, assuming that the compiler supports such deprecation warnings. (Presently, only modern version of the GNU compiler are so configured.)

### Cg Matrix Bindings

Previously, the semantics of a Cg vertex program matrix parameter were determined through the variable name; e.g. a name of ``ModelViewProj'` bound the combined model view and projection matrix to the variable. This is still supported but deprecated. Crystal Space now requires Cg 1.3 which allows the matrix semantics specification in a way similar to other semantics specification. For example:

    uniform float4x4 ModelViewProj

Becomes:

    uniform float4x4 ModelViewProj : state.matrix.mvp

Check the ``data/shaders/'` directory for further examples. For more detailed information, consult the Cg and ``ARB_vertex_program'` documentations.

### CSWS Removal

The long-deprecated Crystal Space Windowing System (CSWS) was removed. Instead use AWS. See section Alternate Windowing System (AWS).

### AWS Changes

The trigger system in AWS has changed. The trigger callback function now has an additional ``unsigned long'` parameter like this:

    static void TriggerFunc (unsigned long, intptr_t, iAwsSource*);

This extra parameter is the id of the given trigger name as returned by the standard string set (``crystalspace.shared.stringset'`).

### Transform Split

To allow more control over how geometry is transformed when using shaders the ``csRenderMesh::object2camera'` has been split into two transforms: ``object2world'` and ``world2camera'`. The ``object2world'` transform is sent via a shader variable, while ``world2camera'` is specified via `iGraphics3D::SetWorldToCamera()` (but it is also available as a shader variable to shader programs).

### ``chunklod'` Terrain Removal

The ``chunklod'` terrain plugin has been removed:

`crystalspace.mesh.object.terrain.chunklod`

Instead use the ``bruteblock'` terrain engine.

`crystalspace.mesh.object.terrain.bruteblock`

### ``csHashMap'` and ``csHashSet'` Removal

The long-deprecated ``csHashMap'`, ``csHashMapReversible'`, and ``csHashSet'` classes have been removed. Instead, use the templated classes `csHash<>`, `csHashReversible<>`, and `csSet<>`. For string-related set functionality, you may also want to consider using ``csStringHash'` and ``csStringSet'`.

### `csObjectPool<>` Removal

The `csObjectPool<>` utility class has been removed since it managed memory poorly, and failed to invoke the destructor of contained objects at the time they were recycled via `csObjectPool<>::Free()`, which meant that the objects might not release their own resources in a timely fashion. (It did correctly destroy the freed objects when the pool itself was destroyed, but should have been doing so at `Free()`-time.)

You can use `csBlockAllocator<>` (see ``csutil/blockallocator.h'`) as a drop-in replacement for `csObjectPool<>` since the API of `csBlockAllocator<>` is a proper superset of the `csObjectPool<>` API. A global search and replace should be sufficient to account for this change.

### ``csStringSetIterator'` and ``csStringHashIterator'` Removal

``csStringSetIterator'` and ``csStringHashIterator'` have been replaced with the iterator classes ``csStringSet::GlobalIterator'` and ``csStringHash::GlobalIterator'`, respectively. Rather than instantiating iterators directly, you now ask the set or hash for an iterator. This brings the ``csStringSet'` and ``csStringHash'` API's in line with other container classes which vend iterators. Given old code which is using ``csStringSetIterator'`:

    csStringSet set;
    // ...populate set...
    csStringSetIterator iter(&set);
    while (iter.HasNext())
    {
      char const* s = iter.Next();
      // ...do something with `s'...
    }

Convert it like this:

    csStringSet::GlobalIterator iter = set.GetIterator();
    while (iter.HasNext())
    {

Code using ``csStringHashIterator'` can be fixed using the same simple transformation.

### Miscellaneous Removals

The following facilities have been removed because they were unused and/or of questionable use.

- `csCrystalBall` and ``csgeom/crysball.h'`
- `csIndPrint` and ``csutil/indprint.h'`
- `iMaterialHandle`. Use ``iTextureHandle'` or ``iMaterial'` directly (whichever is more appropriate) to achieve equivalent functionality.
- `csRenderMeshHolderMultiple`. Equivalent functionality can be achieved by using ``csFrameDataHolder<csDirtyAccessArray<csRenderMesh*> >'`.

### `csRenderMeshHolderSingle` Renamed

``csRenderMeshHolderSingle'` has been renamed to ``csRenderMeshHolder'` as a consequence of the removal of ``csRenderMeshHolderMultiple'`.

### C++ Standard Conformance

Crystal Space's public header files are now C++ Language Standard conformant. This means that Crystal Space-based projects which choose to adhere strictly to the C++ Language Standard (such as those which employ gcc's ``-ansi'` and ``-pedantic'` options) can now include Crystal Space headers safely.

### ``imap/parser.h'` Deprecated

All functionality in the header ``imap/parser.h'` was long ago moved to ``imap/loader.h'`, which declares interfaces to access the Crystal Space map loader. At that time, ``imap/parser.h'` became a very thin wrapper which merely included ``imap/loader.h'` and did nothing more. Since ``imap/parser.h'` has no useful purpose, it is now officially deprecated, and deprecation warnings have been added. Use ``imap/loader.h'` instead.

### `csSet<>` Relocation and Changes

The declaration of `csSet<>` was moved out from ``csutil/hash.h'` and into its own header file, ``csutil/set.h'`. The method `csSet<>::GetHash()` has likewise been removed since it unnecessarily exposed an underlying implementation detail of `csSet<>`.

However, this implementation detail still affects the use of `csSet<>` as for storage of pointers in a `csSet<>` the `csPtrKey<>` wrapper must be used.

### `csHash<>` Changes

The way `csHash<>` handles support for arbitrary key types has been changed. Previously, a so-called "hash key handler" was passed as an optional third template parameter that computed hash keys and was able to compare keys. Now, the hash computation is handled through the new `csHashComputer<>` template, and key comparison through `csComparator<>`. To provide hash computation and comparisons for specific types used as hash keys, specializations of the templates mentioned above are needed. Alternatively the default comparator uses the ``operator <'` and ``operator >'` operators, so you can also implement those operators instead of a `csComparator<>` specialization. The default `csHashComputer<>` implementation assumes that a type provides a ``GetHash()'` method that computes the hash value for an object. However, this means that integral types need a specialization. As a convenience, Crystal Space already provides specializations of `csHashComputer<>` for a number of commonly used intergrals. Further, `csComparator<>` and/or `csHashComputer<>` specializations are provided for the commonly used types ``csString'`, ``const char*'` and ``csStrKey'`; and the default comparison semantics of ``operator <'` and ``operator >'` handle the remaining fundamental types and any composite types which provide these operators. Pointers (other than ``void*'` for which exists a specialization) as hash keys are a special case: to use a pointer of type ``Foo*'` as a hash key, employ ``csPtrKey<Foo>'` as the key type in the hash declaration.

### `iConfig` Renamed

The `iConfig` interface has been renamed to the more fitting `iPluginConfig`, and the containing header from ``iutil/config.h'` to `iutil/pluginconfig.h`. Other changes have not been made.

### Changes for Mesh Object Writers

`iMeshObject::SetLogicalParent()` has been renamed to `iMeshObject::SetMeshWrapper()`. Same for `GetLogicalParent()`. It also uses a `iMeshWrapper` instead of `iBase` as the type of the parameter. `iMeshObjectFactory::SetLogicalParent()` has been renamed to `iMeshObjectFactory::SetMeshFactoryWrapper()`. Same for `GetLogicalParent()`. It also uses a `iMeshFactoryWrapper` instead of `iBase` as the type of the parameter.

### `csRGBVector` Removed

The `csRGBVector` class has been removed. A `csComparator<>` specialization has been provided, so equivalent functionality can be achieved by simply using `csArray<csRGBcolor*>`.

### Changes for hierarchical objects

Meshes and lights can now properly be used as hierarchical objects with the same API. Here is how it works: meshes and lights implement the new `iSceneNode` interface. You can do `QuerySceneNode()` to get the scene object from the mesh, light, or camera without having to do `scfQueryInterface<>`. To make some object a child of another you simply do:

    object_child->QuerySceneNode ()->SetParent (
    	    	  object_parent->QuerySceneNode ());

To remove some object from a parent you do:

    object_child->QuerySceneNode ()->SetParent (0);

You can get the children by calling `iSceneNode->GetChildren()`.

The following methods have been removed:

- `iMeshWrapper->GetChildren()`
- `iMeshWrapper->GetParentContainer()`
- `iMeshWrapper->SetParentContainer()`
- `iMovable->GetParent()`
- `iMovable->SetParent()`

### Model Importing

The old model importing system has been completely removed. That means the following interfaces and classes are gone:

- `csSingleIndexVertexSet`
- `csModelDataTools`
- `csModelConverterFormat`
- `iModelConverter`
- `iModelDataTexture`
- `iModelDataMaterial`
- `iModelDataVertices`
- `iModelDataAction`
- `iModelDataPolygon`
- `iModelDataObject`
- `iModelDataCamera`
- `iModelDataLight`
- `iModelData`
- `csModelDataTexture`
- `csModelDataMaterial`
- `csModelDataVertices`
- `csModelDataAction`
- `csModelDataPolygon`
- `csModelDataObject`
- `csModelDataCamera`
- `csModelDataLight`
- `csModelData`
- `iCrossBuilder`

Instead it is now possible to load 3DS models as genmesh mesh objects and MD2 models as 3D sprites. See section Loading 3DS and MD2 Models.

### Render Priority System

It is no longer possible to define render priorities in a map file. You can now only redefine render priorities from the engine API. See section Render Priorities and Objects in Sectors.

### Ball Mesh Removed

The ball mesh has been removed. The genmesh mesh can now be used to generate spheres instead. Here is an example how you would have to change the map file. First here is the old way:

    <meshfact name="ballFact">
      <plugin>crystalspace.mesh.loader.factory.ball</plugin>
      <params />
    </meshfact>
    ...
    <sector name="room">
      <meshobj name="ball">
        <plugin>crystalspace.mesh.loader.ball</plugin>
        <params>
          <factory>ballFact</factory>
          <material>plasma</material>
          <numrim>16</numrim>
          <radius x="2" y="1" z=".5" />
          <shift x="0" y=".5" z="0" />
          <reversed />
          <toponly />
          <cylindrical />
        </params>
        <move> <v x="15" y="4" z="14" /> </move>
      </meshobj>
    </sector>

And here is the new way:

    <meshfact name="ballFact">
      <plugin>crystalspace.mesh.loader.factory.genmesh</plugin>
      <params>
        <sphere rimvertices="16" reversed="true" toponly="true" cylindrical="true" >
          <radius x="2" y="1" z=".5" />
          <center x="0" y=".5" z="0" />
        </sphere>
      </params>
    </meshfact>
    ...
    <sector name="room">
      <meshobj name="transpBall">
        <plugin>crystalspace.mesh.loader.genmesh</plugin>
        <params>
          <factory>ballFact</factory>
          <material>plasma</material>
        </params>
        <move> <v x="15" y="4" z="14" /> </move>
      </meshobj>
    </sector>

It is important to note that the geometry defining the sphere is now in the factory (as with all genmeshes).

If you want to create them from code then you have to get rid of using the `iBallState` and instead use `iGeneralFactoryState->GenerateSphere()` to generate the desired sphere in a genmesh factory.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ]

This document was generated using texi2html 1.76.