[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section documents the major changes between versions 0.96 and 0.98 of Crystal Space.
The following methods have been removed:
iMeshWrapper::DeferUpdateLighting()
iMeshWrapper::UpdateLighting()
Instead there is a new function iMeshWrapper::SetLightingUpdate()
with
which you can exhibit the same control. The big difference is that you don't
have to call this function every time a light or object moves. This is all
updated automatically now.
Also removed the CS_NLIGHT_
flags. iEngine::GetNearbyLights()
has been modified so that the flags parameter is no longer accepted.
The notion of curve templates has been reworked. `iCurveTemplate' has been removed and it's functionality has moved to `iCurve' itself. As a consequence of this change the bezier addon loader has been removed. Also curves have been separated from the thing plugin and now live in the `bezier' plugin. So, a curve like this in the past:
<addon> <plugin>crystalspace.mesh.loader.thing.bezier</plugin> <params> <name>b1</name> <material>mosaic</material> <v>0</v> <v>1</v> <v>2</v> <v>3</v> <v>4</v> <v>5</v> <v>6</v> <v>7</v> <v>8</v> </params> </addon> <meshfact name="tunnel"> <plugin>crystalspace.mesh.loader.factory.thing</plugin> <params> <curvecenter x="0" y="0" z="0" /> <curvescale>80</curvescale> <curvecontrol x="5" y="2" z="0" u="1" v="0" /> ... <curve name="bez">b1</curve> </params> </meshfact> |
should now become (note the new plugin line):
<meshfact name="tunnel"> <plugin>crystalspace.mesh.loader.factory.bezier</plugin> <params> <curvecenter x="0" y="0" z="0" /> <curvescale>80</curvescale> <curvecontrol x="5" y="2" z="0" u="1" v="0" /> ... <curve name="b1"> <material>mosaic</material> <v>0</v> <v>1</v> <v>2</v> <v>3</v> <v>4</v> <v>5</v> <v>6</v> <v>7</v> <v>8</v> </curve> </params> </meshfact> |
On the API side nothing much changes except that when you use the bezier mesh plugin you need to use `iBezierState' and `iBezierFactoryState'.
The `iThingEnvironment' no longer has code to maintain bezier curve templates.
The interface `iThingState' no longer inherits from
`iObject', thus the QueryObject()
function has been removed.
`iThingState' has been split into `iThingState' and
`iThingFactoryState'. A thing mesh no longer implements both a mesh
object and a mesh object factory. Instead things now work like usual
mesh objects where iMeshObjectType::NewFactory()
creates a
factory that implements `iThingFactoryState' and
iMeshObjectFactory::NewInstance()
creates an instance that implements
`iThingState'. The engine convenience functions to create a thing
mesh will automatically create both the factory and mesh so you don't
have to worry about that. You can use iThingState::GetFactory()
from a thing mesh object to get the `iThingFactoryState' so you can
build the polygons. Note that SCF_QUERY_INTERFACE()
of
`iThingFactoryState' no longer works on a thing mesh object. You must
use GetFactory()
.
iThingState::GetVertexC()
has been removed. It is no longer possible
to get camera space information from a thing.
The method iThingFactoryState::GetFlags()
has been removed. Use the new
method iMeshObjectFactory::GetFlags()
instead.
The interface `iPolygon3D' is completely removed. The `iThingFactoryState' now contains a lot of new functions to create and manipulate polygons. Here is an example:
First the old code:
iPolygon3D* p; p = state->CreatePolygon ("First one"); p->CreateVertex (csVector3 (...)); p->CreateVertex (csVector3 (...)); p->CreateVertex (csVector3 (...)); p->CreateVertex (csVector3 (...)); p->SetMaterial (mat); p = state->CreatePolygon ("Second one"); p->CreateVertex (csVector3 (...)); p->CreateVertex (csVector3 (...)); p->CreateVertex (csVector3 (...)); p->CreateVertex (csVector3 (...)); p->SetMaterial (mat); ... |
Here is the new code:
state->AddQuad ( csVector3 (...), csVector3 (...), csVector3 (...), csVector3 (...)); state->SetPolygonName (CS_POLYRANGE_LAST, "First one"); state->AddQuad ( csVector3 (...), csVector3 (...), csVector3 (...), csVector3 (...)); state->SetPolygonName (CS_POLYRANGE_LAST, "Second one"); state->SetPolygonMaterial (CS_POLYRANGE_ALL, mat); |
If you want to add a box that can be seen from the inside (typically a room) then you can do it like this:
state->AddInsideBox (csVector3 (-5, 0, -5), csVector3 (5, 20, 5)); state->SetPolygonMaterial (CS_POLYRANGE_LAST, mat); state->SetPolygonTextureMapping (CS_POLYRANGE_LAST, 3); |
The interfaces `iStatLight' and `iDynLight' have been removed
and their functionality has been merged into `iLight' (this includes
the function iDynLight::Setup()
. There is now a new function
iLight::GetDynamicType()
which returns one of the following
constants depending on the type of the light:
CS_LIGHT_DYNAMICTYPE_STATIC
: for static lights.
CS_LIGHT_DYNAMICTYPE_PSEUDO
: for pseudo-dynamic lights.
CS_LIGHT_DYNAMICTYPE_DYNAMIC
: for fully dynamic lights.
The method iLight::IsDynamic()
was removed;
use iLight::GetDynamicType()
to get the same information.
The following functions have been modified to work with `iLight' instead of `iStatLight' and `iDynLight':
iEngine::CreateLight()
.
iEngine::FindLight()
.
iEngine::FindLightID()
.
iEngine::ForceRelight()
.
The last parameter of iEngine::CreateLight()
routine has
changed to be the dynamic type of the light (one of the above
`CS_LIGHT_DYNAMICTYPE' constants) instead of a boolean. Thus, the
iEngine::CreateDynLight()
method has been superceded by this
function.
All functions related to dynamic lights have been removed. Dynamic
lights are now treated exactly like static lights. For example, you have to
call iSector::GetLights()
and then Add()
to add the light to the
sector. The iLight::Setup()
function remains, however, and is
specific to dynamic lights.
The following interfaces have been removed: `iPolyTexNone', `iPolyTexGouraud', `iPolyTexFlat', and `iPolyTexLightMap'. The combined API from `iPolyTexNone' and the `iPolyTexLightMap' have moved to `iThingFactoryState'.
It is no longer possible to set mixmode and alpha for individual polygons
Instead use the new iThingState::SetMixMode()
function to set the
mixmode globally. If needed you will have to separate the transparent polygon
in a separate thing mesh.
It is also no longer possible to get camera space information from polygons.
The <shading>
keyword in polygons in map files now accepts a boolean
value instead of `NONE', `FLAT', `GOURAUD', or `LIGHTMAP'.
With this you can enable/disable lightmapping.
If you want gouraud shaded polygons you should use the `genmesh' mesh object plugin instead.
Polygon planes are removed. So it is no longer possible to use the plane addon loader to define texture mapping for a polygon outside of the polygon itself. To fix this you must specify all texture mapping information in the `texmap' statement of the polygon. `map2cs' now correctly outputs polygons like this (no longer outputs planes) and `levtool' can convert old style maps to new format like this:
levtool -planes yourmap.zip |
`iThingEnvironment' no longer has code to maintain polygon texture mapping planes.
The plane loader and saver addons have been removed from the thing loader plugin.
Removed `iPolyTxtPlane' interface.
Several methods in `iPortal' have changed slightly. For example,
SetMirror()
now expects a plane instead of a polygon.
In the map loader the syntax for specifying warp vectors for portals has changed from `v' to `wv' and `w' to `ww'.
Portals in thing have been removed completely! Instead there is now a separate
portal container object which belongs in the engine (otherwise it is just
a mesh like any other mesh). To create a portal you can use the convenience
functions iEngine::CreatePortal()
and
iEngine::CreatePortalContainer()
. Here is an example of old code
and how to change it to new code:
... create thing in sourceSector ... iPolygon3D* p = state->CreatePolygon (); p->CreateVertex (csVector3 (...)); p->CreateVertex (csVector3 (...)); p->CreateVertex (csVector3 (...)); p->CreateVertex (csVector3 (...)); iPortal* portal = p->CreatePortal (destSector); |
New code:
csPoly3D poly; poly.AddVertex (csVector3 (...)); poly.AddVertex (csVector3 (...)); poly.AddVertex (csVector3 (...)); poly.AddVertex (csVector3 (...)); iPortal* portal; csRef<iMeshWrapper> portal_mesh = engine->CreatePortal ( "my_portal", sourceSector, csVector3 (0, 0, 0), destSector, poly.GetVertices (), poly.GetVertexCount (), portal); |
In map files the old way to create portals in a polygon is still supported. Internally it will also create a portal container (as a child mesh of the thing it is in). The new way to create portals is by using the new `portals' and `portal' keywords in sectors or as children of other meshes.
The `csSome', `csConstSome' and `uint' types have been removed. Use `void*', `const void*' and `unsigned int' instead.
Instead of only built-in types, procedural textures have been moved into
plugins. That means that the <type>
token now works the same way
as the <plugin>
token for meshes. That is, either specify a full
class ID (e.g. `crystalspace.proctex.loader.fire'), or a shortcut
specified in the <plugins>
token of the world. To simulate the
old <type>
behaviour, paste the following lines into a map's
<plugin>
section:
<plugin name="dots">crystalspace.texture.loader.dots</plugin> <plugin name="fire">crystalspace.texture.loader.fire</plugin> <plugin name="water">crystalspace.texture.loader.water</plugin> <plugin name="plasma">crystalspace.texture.loader.plasma</plugin> |
This requires that you move the <plugin>
block in front of the
<textures>
block, as otherwise the shortcuts won't be recognised.
The behaviour of procedural textures also differs as a material of the same name was created along with the texture; this isn't the case any more, you have to create a material which uses the procedural texture manually.
In addition, the loader now doesn't distinguish between normal and procedural
textures any more, both are loaded with the same <texture>
block. The
syntax recognized is a combination of both old <texture>
and
<proctex>
tokens--so renaming all <proctex>
to <texture>
tags is sufficient to convert a level (apart from fixing the <type>
tokens.)
Region handling has changed considerably. The engine no longer has the concept of a current region. The engine still manages all regions though. Objects also no longer register themselves to the current region. It is the responsability of the object creator to do that. The standard loader has support for adding objects to a region now.
The following functions have been removed from `iEngine':
SelectRegion()
GetCurrentRegion()
AddToCurrentRegion()
There is one new function iEngine::CreateRegion()
which will create
a new region.
In `iLoader' the functions LoadMapFile()
and
ThreadedLoadMapFile()
now expect an optional pointer to a region
in addition with a boolean to restrict searching to that region.
In addition to all these changes the <region>
keyword in map files is no
longer supported.
Some mesh factories used to support the querying of the `iPolygonMesh' interface (e.g. Thing, Sprite3D, Genmesh). Due to the way this was implemented internally this caused leaks. So, querying `iPolygonMesh' directly from the object is now discouraged. Although it may still work in some cases, this feature may be dropped without further notice and may not work in all cases.
Similar for mesh objects. Querying `iPolygonMesh' is discouraged here, as well.
Instead, if you want the polygon mesh from an object, use the
GetObjectModel()
method from the `iMeshObject' interface;
respectively query for the `iObjectModel' interface in case of a factory,
and utilize one of the GetPolygonMeshXXX()
methods, depending on what
you need (the old interface query returned the collision detection mesh.) This
has also the advantages that you can get different meshes for different
purposes (currently, visibility culling and collision detection in addition the
the base mesh), and that those meshes can be overridden by user-defined meshes
(e.g. if the collision detection mesh needs to have a shape different from the
visible mesh.)
In `iPolygonMesh' the IsDeformable()
method has been replaced
with the more general GetFlags()
. In addition to that Cleanup()
is removed and instead Lock()
and Unlock()
are added.
`iPolygonMesh' now has GetTriangles()
and GetTriangleCount()
.
Check out the API docs for implementation details.
Changed the following iterators to conform to the following iterator standard:
bool iterator->HasNext() // returns true if there are more items. T* iterator->Next() // returns next element or 0. void Reset() // resets iterator (not all implement this). |
iVisibilityObjectIterator
iLightIterator
iSectorIterator
iObjectIterator
iStreamIterator
iObjectRegistryIterator
csTypedObjectIterator
csModelDataActionIterator
csModelDataPolygonIterator
csModelDataTextureIterator
csModelDataMaterialIterator
csModelDataObjectIterator
csNodeIterator
iAWS::CreateCustomCanvas()
was removed. To set up AWS with a
canvas, use iAWS::SetupCanvas()
instead.
iAWS::CreateTransition()
and iAWS::CreateTransitionEx()
have been
changed to take a delay parameter specified in `csTicks' instead of
using a step_size parameter. This change ensures that transitions take
the same amount of time on computers having different processor speeds.
iAWS::ComponentIsInTransition()
has been added to allow users to query
if a specified `iAwsComponent' is in the midst of a transition.
All arrays have been modified to inherit from `csArray'. This means that there are some slight API changes because some methods were not consistent with `csArray'.
`csGrowingArray' has been renamed to `csDirtyAccessArray' in order to
better reflect its intention, which is that it publishes a method allowing the
client to obtain access to the raw memory block containing the items in
contiguous memory. This potentially unsafe operation is not available in the
other array templates. Use this class only in very special-purpose cases where
you need to construct a list of objects dynamically and then pass the address
of the raw memory containing those objects to some foreign function which does
not understand csArray<>
.
`csPArray' has been removed in favor of the csArray<>
template.
So, use csArray<T*>
instead of csPArray<T>
.
`csStrVector' and `iStrVector' have been removed in favor of
`csStringArray' and `iStringArray'. This means that functions like
iVFS::MountRoot()
and iVFS::FindFiles()
now return an
`iStringArray'.
`csVector' and `csBasicVector' have been removed. Instead you
should use one of the templated arrays: csArray<>
, csPDelArray<>
,
or csRefArray<>
.
If you were using a regular `csVector' then this can usually be
replaced directly by csArray<type*>
with `type' the type you
were storing in the vector.
If you subclassed from `csVector' in order to override FreeItem()
then you have to decide what to do depending on the code in FreeItem()
.
If that code performed a `delete' then you can use csPDelArray<>
.
If that code performed a DecRef()
then you can use csRefArray<>
but you still have to be careful because csRefArray<>
will automatically
invoke IncRef()
for objects that are pushed on the array. In other cases
you probably need to handle deletion manually.
`csVector' also allowed you to override Compare()
and
CompareKey()
, and these methods were utilized automatically by
QuickSort()
, FindSortedKey()
, InsertSorted()
, and
FindKey()
. csArray<>
, on the other hand, accepts a comparison
function as an argument to its sorting and searching methods, thus providing
much greater flexibility than `csVector'. You can transform your
csVector
-based code as follows. First, the old code:
class MyVector : public csVector { public: virtual ~MyVector () { DeleteAll (); } virtual void FreeItem (void* item) { delete (MyType*)item; } virtual int Compare (void* i1, void* i2, int mode) const { ... } virtual int CompareKey (void* i, const void* key, int mode) const { ... } }; |
This can be transformed roughly to the following class:
class MyVector : public csPDelArray<MyType> { public: static int Compare (MyType const& i1, MyType const& i2) { ... } static int CompareKey (MyType const& i, MyKey const& key) { ... } }; |
The methods csArray<>::Sort()
and csArray<>::InsertSorted()
accept an optional comparison function (MyVector::Compare()
, in the
example). To use a custom comparison function, invoke these functions like
this:
MyVector v = ...; v.Sort(MyVector::Compare); ... MyType o = ...; v.InsertSorted(o, MyVector::Compare); |
If you do not provide a comparison function, then the array elements are
compared against each other with T::operator<(T)
where `T' is the
type of the element contained in the array. This default comparison semantic
works nicely for all built-in types, as well as for complex types which define
a `<' operator.
The methods csArray<>::FindKey()
and csArray<>::FindSortedKey()
accept a comparison functor which is constructed from the key for which
you are searching and an optional comparison function
(MyVector::CompareKey()
, in the example). Invoke these functions like
this:
int r; MyKey key = ...; MyVector v = ...; r = v.FindKey(csArrayCmp<MyType,MyKey>(key, MyVector::CompareKey)); r = v.FindSortedKey( csArrayCmp<MyType,MyKey>(key, MyVector::CompareKey)); |
In this example, the key's type is `MyKey' (the type expected by
MyVector::CompareKey()
). It is possible and often convenient for
`MyType' and `MyKey' to be the same type (for instance, you might
search for an integer in an array of integers). When the types of
`MyType' and `MyKey' differ, `MyType' is often a composite type,
and `MyKey' is the type of one attribute of `MyType', however you are
not in any way limited to this arrangements. If you do not provide a
comparison function when constructing the functor, then the the elements are
compared with the search key via T::operator<(K)
and
K::operator<(T)
where `T' and `K' are the type of the
contained element and the type of the key, respectively. This default
comparison semantic is especially useful when the contained elements and key
have the same type, provided that the type supports a useful `<' operator.
For example, if you have an array of integers which you want to sort and then
search, you can use the default comparison semantics, rather than writing a
custom comparison function, as shown here:
csArray<int> v = ...; v.Sort(); int r = v.FindSortedKey(csArrayCmp<int,int>(33)); |
The new template classes csHash<>
and csSet<>
are available for
use by new code; and older code will be upgraded over time to use these
template classes. The older `csHashMap' and `csHashSet' classes are
now deprecated.
The deprecated `csHashIterator' can no longer iterate over all objects. To do that you need to use `csGlobalHashIterator'.
Signatures of the iEvent::Find()
methods have been unified so that they
all now accept a reference into which to store the found item. Previously,
some Find()
methods used a reference for this purpose, while others used
a pointer. In addition, rather than accepting a pointer to a pointer of type
`iEvent', the Find()
method for finding an event now takes a
reference to a csRef<iEvent>
.
Previously, iEventQueue::Post()
had a special case where it assumed that
the caller was giving up ownership of the posted `iEvent' if the caller
had allocated the event manually, rather than obtaining the event via
iEventQueue::CreateEvent()
or iEventOutlet::CreateEvent()
. In
this case, Post()
would hijack the caller's reference to the
`iEvent' for itself. This special case allowed the caller to write code,
such as the following, which appeared to leak a reference to the event, but
which did not in fact do so.
iEvent* e = new csEvent(...); eventq->Post(e); |
Now, however, iEventQueue::Post()
takes the more sane approach of
treating all incoming events identically. It never hijacks ownership of the
event by stealing the caller's reference. Instead, Post()
uniformly
invokes IncRef()
on each incoming event in order to claim its own
reference. This means that callers are no longer burdened by having to
determine whether or not the caller's reference is going to be hijacked.
Thus, the above code should now be re-written as:
csRef<iEvent> e; e.AttachNew(new csEvent(...)); eventq->Post(e); |
Events created with iEventQueue::CreateEvent()
or
iEventOutlet::CreateEvent()
are unaffected by this change since the
client has never had to worry about Post()
hijacking the reference in
these cases.
The mesh object API has changed considerably, thus we recommend looking at the documentation on that to see how to modify your own mesh object for the new API. In this section we describe API modifications that are relevant for user applications.
For `iLight': SetRadius()
, GetRadius()
, and
GetSquaredRadius()
have been replaced with SetInfluenceRadius()
,
GetInfluenceRadius()
, and GetInfluenceRadiusSq()
.
For `iMaterialEngine' and related: GetTextureWrapper()
for
layers now expects a `csStringID' instead of an integer.
Written by Eric Sunshine, [email protected].
The monolithic and inflexible plugin-registry database, `scf.cfg', has been eliminated. Instead, plugin modules are now self-describing via a meta-information resource associated with each module. It is possible to access this meta-information without actually loading the plugin, thus avoiding a time-consuming and costly operation.
A plugin's meta-information is now stored in an XML-format file rather than being hard-coded via the plugin's C++ code. The meta-information file is named after the associated plugin module, except with filename extension `.csplugin'. For instance, the meta-information for the `vfs.so' (or `vfs.dll') plugin will be named `vfs.csplugin'.
Since the meta-information is now maintained via an external resource, the following SCF macros, which were used to export this information from the C++ code, have been removed:
SCF_EXPORT_CLASS_TABLE()
SCF_EXPORT_CLASS()
SCF_EXPORT_CLASS_DEP()
SCF_EXPORT_CLASS_TABLE_END
To deal with this change in your own code, simply remove the entire
SCF_EXPORT_CLASS_TABLE()
block from the C++ code which implements the
plugin module.
Creation of the meta-information resource file involves a straight-forward translation of the information from the obsolete SCF macros into a structured XML-format file. For example:
SCF_EXPORT_CLASS_TABLE(foo) SCF_EXPORT_CLASS( MyClass1, "myproj.myplugin.foo1", "My first custom foo class") SCF_EXPORT_CLASS_DEP( MyClass2, "myproj.myplugin.foo2", "My second custom foo class", "myproj.myplugin.bar1,myproj.myplugin.bar2") SCF_EXPORT_CLASS_TABLE_END |
This table exports two C++ classes, `MyClass1' and `MyClass2' under the SCF class names `myproj.myplugin.foo1' and `myproj.myplugin.foo2', respectively. Furthermore, the second exported class has a dependency upon two other SCF classes, `myproj.myplugin.bar1' and `myproj.myplugin.bar2'. To convert this to an XML-format meta-information resource, just copy the above values into the appropriate XML nodes. For instance:
<?xml version="1.0"?> <!-- myplugin.csplugin --> <plugin> <scf> <classes> <class> <name>myproj.myplugin.foo1</name> <implementation>MyClass1</implementation> <description>My first custom foo class</description> </class> <class> <name>myproj.myplugin.foo2</name> <implementation>MyClass2</implementation> <description>My second custom foo class</description> <requires> <class>myproj.myplugin.bar1</class> <class>myproj.myplugin.bar2</class> </requires> </class> </classes> </scf> </plugin> |
The top-level node of a meta-information file is named <plugin>
. All
SCF-related information is contained within an <scf>
child node.
Plugin modules can export multiple named SCF classes. Each exported class
is represented by a <class>
node within the <classes>
group. The
<name>
node of a <class>
is the class' SCF name. The
<implementation>
node references the C++ class which actually implements
the named SCF class. This is the same name that is provided as an
argument to the SCF_IMPLEMENT_FACTORY()
macro. When an SCF class
depends upon other SCF classes, the dependencies are indicated via the
optional <requires>
group, which contains one <class>
node per
dependency.
Meta-information in the `.csplugin' file is extensible; it is not
restricted to SCF-only usage. Plugin authors can choose to publish
supplementary information about plugins in addition to the SCF information
already published. As a hypothetical example, image loading plugins might
desire to publish image indentification information which would allow the
image loading multiplexor to selectively request image loading plugins
on-demand, rather than requesting all plugins unconditionally, even if
they are not needed. Here is a possible meta-information table for a PNG
image loader (with the <scf>
node collapsed to `...' for the
sake of illustration):
<?xml version="1.0"?> <!-- cspngimg.csplugin --> <plugin> <scf>...</scf> <imageloader> <imagetype> <class>crystalspace.graphic.image.io.png</class> <identify> <mimetype>image/png</mimetype> <extension>png</extension> <extension>PNG</extension> <scan length="4" bytes="\0x89PNG"/> </identify> </imagetype> </imageloader> </plugin> |
In this example, the PNG loader meta-information tells the multiplexor several different ways to identify a PNG image:
If the hypothetical multiplexor identifies the image as PNG, only then will it actually request the PNG loader plugin.
If you know the physical pathname of a plugin module, then you can retrieve its
meta-information via csGetPluginMetadata()
(`csutil/csshlib.h'),
which returns an `iDocument'. Alternately, if you know the name of an
SCF class which a plugin exports, then you can retrieve the plugin's
meta-information, by calling iSCF::GetPluginMetadata()
.
At program launch time, SCF discovers plugins automatically by searching a set of directories, and creates an internal database associating available SCF class names with the plugin modules which implement them. The directories which SCF searches by default are:
csGetResourceDir()
.
On most platforms, this is the same as the directory containing the
application, however, on MacOS/X, it is the `Resources' directory within
the Cocoa application wrapper.
csGetAppDir()
.
csGetConfigPath()
. This is often the value of the `CRYSTAL'
environment variable, or the `CrystalSpaceRoot' default setting on MacOS/X
(which is often stored within the `NSGlobalDomain' domain).
If you would like SCF to scan additional directories, you can invoke either of these two functions (multiple times, if necessary):
scfInitialize(csPluginPaths const*)
iSCF::ScanPluginsPath(char const*, bool, char const*)
Finally, if you need to manually register a single plugin module with SCF
for which you know the native pathname (not a VFS pathname), you can
invoke iSCF::RegisterPlugin()
.
For those relatively rare cases when a named SCF class is built
directly into an application, rather than being implemented via a plugin, the
class must be registered with SCF manually since SCF will not
otherwise be able to discover it automatically as is the case with named
classes exported from plugin modules. Manual registration is accomplished with
the SCF_REGISTER_STATIC_CLASS()
macro. This macro existed previously,
but accepted a different set of arguments. The new arguments are:
SCF_REGISTER_STATIC_CLASS( C++Class, "scf.class.name", "description", "comma-separated dependency list" or NULL) |
Invoke this macro in one of the source files of your application; usually in the source file which implements the class. This macro should be invoked at file scope (that is, not from inside a function). For instance:
SCF_REGISTER_STATIC_CLASS( MyClass2, "myproj.myplugin.foo2", "My second custom foo class", "myproj.myplugin.bar1,myproj.myplugin.bar2") |
If you used to use SCF_REGISTER_STATIC_LIBRARY()
or
SCF_REGISTER_STATIC_CLASS_DEP()
for this same purpose, you must now
instead use SCF_REGISTER_STATIC_CLASS()
. (A macro named
SCF_REGISTER_STATIC_LIBRARY()
still exists, but it has a completely
different purpose than the original version, and is typically only used by very
low-level mechanisms, rather than by end-users. See
`CS/include/csutil/scf.h' for the gory details, if you are curious.)
The Crystal Space `configure' script option `--enable-meta-info-embedding' controls whether or not the build system embeds the plugin meta-information into plugin modules (if supported by the platform), and whether or not the plugin loader looks for embedded meta-information. If this option is disabled, or if embedding is not supported by the platform, then the meta-information is laid down alongside the built plugin module (`.so' or `.dll') in a text file with the same name as the plugin module, except with extension `.csplugin'. The meta-information embedding option is enabled by default for most platforms, but is disabled by default for Unix platforms.
Warning: Meta-information embedding on Unix is accomplished via the `libbfd' library which carries a GPL license. This license is incompatible with Crystal Space's LGPL license. Unlike the LGPL which is compatible with closed-source projects, the GPL license is not. For this reason, embedding is disabled by default on Unix, and must be enabled explicitly with the `configure' script's `--enable-meta-info-embedding' option. Enable this option on Unix only if you are certain that your project is compatible with the GPL license.
The platform-specific plugin loaders are capable of reading embedded plugin meta-information, as well as meta-information in stand-alone `.csplugin' files. Even when configured for embedding, the plugin loaders will still be able to recognize and utilize external `.csplugin' resources. This means that Crystal Space-based projects with unsophisticated build systems, which are incapable of embedding meta-information into the plugin module, can still create usable plugins simply by placing a copy of the `.csplugin' file alongside the plugin executable (`.so' or `.dll').
External projects which are based upon Crystal Space's Jam build system (`CS/mk/jam') inherit, for free, the capability of embedding meta-information within plugin modules (if supported by the platform). Simply grab the newer `.jam' files from `CS/mk/jam', and add a few definitions to the project's `Jamconfig' file. The exact set of definitions is platform-specific, so consult the appropriate Jam file (`unix.jam', `win32.jam', or `macosx.jam') to determine precisely which which definitions are required. Here is a list of definitions required at the time of writing:
EMBED_META = yes
LIBBFD.AVAILABLE = yes
OBJCOPY.AVAILABLE = yes
CMD.OBJCOPY = objcopy
EMBED_META = yes
EMBED_META = yes
The `scfreg' tool whose job was to manipulate the monolithic SCF plugin-registry database, `scf.cfg', has been eliminated since it is no longer required.
The macros SCF_DESTRUCT_IBASE()
and SCF_DESTRUCT_EMBEDDED_IBASE()
have been introduced. Just as a destructor reverses initialization performed
by a constructor, these new macros reverse the initialization performed by the
corresponding SCF_CONSTRUCT_IBASE()
and
SCF_CONSTRUCT_EMBEDDED_IBASE()
macros. Typically, you should invoke
these macros within your class' destructor, just as you invoke the
corresponding SCF construction macros in your class' constructor.
The SCF_CREATE_INSTANCE()
macro now returns csPtr<>
to be
consistent with the other SCF instantiation and query macros. This means
that you should now assign the result of SCF_CREATE_INSTANCE()
to a
csRef<>
.
The method iSCF::QueryClassList()
, which used to return a raw
`iStringArray*' that the client had to dispose of manually, now returns a
csRef<iStringArray>
.
The macros SCF_SET_REF()
, SCF_INC_REF()
, and SCF_DEC_REF()
have been removed. Instead you should use csRef<>
.
The method iSCF::GetInterfaceName(scfInterfaceID)
has been added to
complement the existing iSCF::GetInterfaceID()
.
The query template class scfInterface<>
has been introduced. This class
provides a means to query static information about SCF interfaces, such as
an interface's version number. Presently, this class allows access to the
following static information:
GetID()
--Retrieves the interface's low-level identifier as an
`scfInterfaceID', which is typically a small integer. SCF identifies
interfaces internally by an ID for performance reasons.
GetName()
--Retrieves the interface's name as a null-terminated
C-string.
GetVersion()
--Retrieves the interface's current version number.
Here is an example illustrating how to retrieve various pieces of information about an interface.
int ver = scfInterface<iFoo>::GetVersion(); scfInterfaceID ident = scfInterface<iFoo>::GetID(); char const* name = scfInterface<iFoo>::GetName(); |
An important benefit of the new scfInterface<>
template class is that it
is now possible for template authors to perform queries for interface-related
information. For example, the author of a new template class may know an
SCF interface via only the opaque identifier T
, yet it is still
possible to query T
's version using
scfInterface<T>::GetVersion()
.
The old hidden, semi-private API for obtaining interface information via
the global `name_VERSION' constant and global name_scfGetID()
function has been removed. Conversion from the old API to the new is
straight forward. For example:
iFoo_VERSION
=> scfInterface<iFoo>::GetVersion()
iFoo_scfGetID()
=> scfInterface<iFoo>::GetID()
A consequence of this change is that it is no longer possible to invoke the
SCF_VERSION()
macro inside an alternate namespace. If previously you
were invoking this macro within your project's own namespace, you must relocate
the invocation so that it appears outside the namespace. For example:
#include <csutil/scf.h> namespace MyProject { struct iMyInterface : public iBase { ... }; } SCF_VERSION(MyProject::iMyInterface, 1, 0, 0); |
The `cssys' library has been merged into the `csutil' library. This eliminates many problems resulting from the large number of circular dependencies which existed between these two libraries. From the client viewpoint, this change manifests in two ways:
#include <cssys/header.h>
to
#include <csutil/header.h>
.
The `csengine' library has been removed. Direct use of this library has long been deprecated, so its removal will probably go unnoticed by most or all projects. Any projects which were using this library must now instead interact with the 3D engine via the `engine' plugin and the SCF interfaces in the `CS/include/iengine' directory.
The `csappframe' library has been merged into the `cstool' library.
Furthermore, the main()
function, which client application's got for
free when linking against this library, has been removed since it proved to be
an obstacle to making Crystal Space libraries available as shared
libraries. Instead, you must now provide your own main()
function, like
this:
// main.cpp CS_IMPLEMENT_APPLICATION class MyApp : public csApplicationFramework { /* ... */ }; int main (int argc, char* argv[]) { MyApp myApp; return myApp.Main (argc, argv); } |
The csString::strlwr()
method was renamed to Downcase()
. A
complementary Upcase()
method was added for completeness. These methods
were also added to `iString'. A Slice()
method was added to
`iString' and `csString' which copies a sub-portion of a string.
Slice()
is similar to the existing SubString()
method, but
follows a more natural calling convention. Several `iString' methods
which were incorrectly returning raw `iString*' or `iString&' now
correctly return csRef<iString>
.
`csString' now makes a distinction between a null-string (think
`(char const*)0'), and a zero-length string (think ""
). Client
code can check for these conditions in the normal fashion by invoking
csString::GetData()
or operator char const*()
to retrieve a
C-string representation of the string. If the result is zero, then it is a
null-string. If the result is non-zero but csString::Length()
returns
zero, then it is a zero-length string. The new convenience method
csString::GetDataSafe()
will always return a valid C-string, even if the
underlying `csString' represents a null-string (in which case a
zero-length C-string ""
will be returned). This means that the result
of GetDataSafe()
can be used directly without performing a null check.
In previous releases, `csString' would also sometimes return a null
pointer or a zero-length string from csString::GetData()
or
operator char const*()
, but there was no controlled way to know when one
or the other would be returned since `csString' was doing so haphazardly.
Worse, several of the `csString' methods failed to check the underlying
representation, and would crash if the string's state was not what the methods
expected. Now, however, `csString' itself makes a proper distinction
between these cases, and the user has direct (and documented) control over when
a `csString' will represent a null-string or a zero-length string.
A csMD5(csString const&)
constructor was added to complement the
existing csMD5(char const*)
constructor. The new method
csMD5::Digest:HexString()
returns a hexadecimal string representation of
the MD5 digest using lowercase hexadecimal characters.
csMD5::Digest::HEXString()
returns uppercase hexadecimal characters.
IntersectSegment()
for `iThingFactoryState' and `iThingState'
has been removed. Use iMeshObject::HitBeamObject()
instead.
iMeshObject::HitBeamObject()
now has an optional polygon index
parameter so you can get the index of the polygon that was hit.
iSector::HitBeam()
which doesn't support portals now returns a polygon
index instead of a polygon pointer.
iSector::HitBeam()
that supports portals has been renamed
to HitBeamPortals()
. It additionally returns a polygon index.
Same for iPortal::HitBeam()
which has also been renamed
to HitBeamPortals()
.
iCamera::GetHit()
has been removed. Instead, use the completely
equivalent function iSector::HitBeamPortals()
.
iVisibilityCuller::IntersectSegment()
now returns a polygon index
instead of a portal.
The following low-level functions, declared in `csutil/syspath.h' can be
used to query various directories and paths. Each of these functions expects
to be passed argv[0]
obtained from the program's main()
function.
csGetAppPath()
Returns the absolute path of the application executable file.
csGetAppDir()
Returns the absolute path of the directory containing the application executable file; or the path of the directory containing the Cocoa application wrapper on MacOS/X for GUI applications.
csGetResourceDir()
Returns the absolute path of the directory in which the application's resources
reside. On many platforms, resources, such as configuration files, data files,
etc., reside in the same directory as the application itself. On such
platforms, this function will typically return the same directory as
csGetAppDir()
. On MacOS/X, however, for GUI applications, this
function will return the `Resources' directory within the Cocoa
application wrapper.
Since it is rarely convenient to squirrel-away argv[0]
, the following
higher-level methods, declared in `iutil/cmdline.h', are also available
for obtaining the same information once the application has been initialized.
These methods do not require access to argv[0]
. You can obtain a handle
to the shared `iCommandLineParser' from the object registry,
`iObjectRegistry', which is declared in `iutil/objreg.h'.
iCommandLineParser::GetAppPath()
iCommandLineParser::GetAppDir()
iCommandLineParser::GetResourceDir()
VFS (see section Virtual File System (VFS)) now understands two new pseudo-variables, `$*' and `$^', in its configuration file, `vfs.cfg', and during programmatic mounts. The full list of pseudo-variables is:
$/
Platform-specific path delimiter (`/' on Unix and MacOS/X; `\' on Windows).
$@
Crystal Space installation directory; same as csGetConfigPath()
.
$*
Application resource directory; same as csGetResourceDir()
.
$^
Directory where application resides, or directory containing Cocoa application
wrapper on MacOS/X; same as csGetAppDir()
.
The expansions of the `$@', `$*', and `$^' variables always contain a trailing path delimiter.
At initialization time, VFS now searches for its configuration file,
`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 first `vfs.cfg' file found during this
search is the one used to initialize the facility. In the past, VFS
searched for `vfs.cfg' only in the Crystal Space installation directory.
The VFS volume `/temp' has been renamed to `/varia' in the default `vfs.cfg' file in order to avoid confusion with the like-named VFS volume `/tmp', which represents user-writable temporary storage. The `/varia' volume (née `/temp'), on the other hand, resides within `${prefix}/etc/crystal' (where `${prefix}' is the installation location), and this location usually is not writable by the typical user. External projects may, of course, still create any VFS volume desired, including `/temp', by supplying a project-specific `vfs.cfg'.
Some work to improve internationalization support in Crystal Space has been performed. Crystal Space now has more complete support for Unicode input and output.
The `csUnicodeTransform' class provides functions to deal with and convert between UTF-8, UTF-16, and UTF-32 encoded strings.
Several portions of the CrystalSpace API now accept UTF-8-encoded strings. These include:
csPrintf()
csPrintfV()
csFPutErr()
iGraphics2D::Write()
csReport()
csReportV()
iReporter::Report()
iReporter::ReportV()
iNativeWindowManager::Alert()
iNativeWindowManager::AlertV()
iNativeWindow::SetTitle()
Keyboard events have changed. The event data related to keyboard events is no
longer stored in a structure inside `iEvent', but instead now resides
within `iEvent''s property bag. That means the way to access the event
data has changed slightly; you now either query for the data via
iEvent::Find()
to get a specific property, or you access it via the the
`csKeyEventHelper' class.
Another change is that the `csevKeyDown' and `csevKeyUp' events have been collapsed to a single `csevKeyboard' event; the up/down information is transported along with the event data.
The notion of scan code and characters has been replaced with raw and cooked codes. Basically, the raw code identifies the key uniquely, while the cooked code is a processed version of it. An important aspect of this is that both the raw and cooked codes are Unicode characters. Special keys (such as function keys) are encoded as characters from a Unicode private use area. Almost all event handling code should consult the raw code because the raw code is invariant; that is, an a is an `a' even if the ALT or SHIFT key, or both, are depressed. This is useful for games, for instance, which need to map keys to particular actions. Cooked codes are useful typically only for text input, such as within a text input field.
You can find additional information in Crystal Space's public API documentation in the Event Handling and Keyboard Events sections.
To understand how to adjust your code for these changes, see the following examples.
iEvent& e = ...; if (e.Type == csevKeyDown && e.Key.Code == CSKEY_ESC) { |
Change to:
if (e.Type == csevKeyboard && csKeyEventHelper::GetEventType(&e) == csKeyEventTypeDown) && csKeyEventHelper::GetCookedCode(&e) == CSKEY_ESC)) { |
Another example:
iEvent& e = ...; switch (e.Type) { case csevKeyDown: Foo(); break; case csevKeyUp: Bar(); break; } |
Change to:
switch (e.Type) { case csevKeyboard: if (csKeyEventHelper::GetEventType(&e) == csKeyEventTypeDown) Foo(); else Bar(); break; } |
The functionality provided by WriteBaseline()
is now available by
specifying the `CS_WRITE_BASELINE' flag when calling
iGraphics2D::Write()
. Hence, WriteBaseline()
is superfluous and
has been deprecated.
csInitializer::RequestPlugins(csArray<csPluginRequest>)
has been added
to complement the existing RequestPlugins(...)
which accepts a variable
number of arguments. The new overload allows the list of requested plugins to
be composed at run-time, whereas the older variable-argument method required
the list be known at compile-time, which was not always convenient or possible.
The following symbols have been renamed in order to avoid pollution of the global namespace.
STATIC_CAST()
=> CS_STATIC_CAST()
DYNAMIC_CAST()
=> CS_DYNAMIC_CAST()
REINTERPRET_CAST()
=> CS_REINTERPRET_CAST()
CONST_CAST()
=> CS_CONST_CAST()
The iTextureManager::SetVerbose()
function has been removed. It
was not useful.
iFont::SetSize()
has been removed. Instead, the font size is
supplied when the font is created with iFontServer::LoadFont()
.
This change has been made to fix the problem that multiple LoadFont()
calls were returning the same instance of a font, and thus subsequent calls
of SetSize()
affected a font globally (e.g. all Arial fonts would
be the same size). The new behaviour is to return only an existing
instance of a font when both the font name and font size match. If there is
no existing instance with the requested name and size, then a new instance
is created and returned.
Font-related client code, such as the following:
csRef<iFont> font = fontserver->LoadFont ("myfont.ttf"); font->SetSize (23); g2d->Write (font, ...); |
Should be changed to:
csRef<iFont> font = fontserver->LoadFont ("myfont.ttf", 23); g2d->Write (font, ...); |
There is a new flag CS_ENTITY_INVISIBLEMESH
which controls visibility
(and ONLY visibility) of a mesh. There is also a new flag
CS_ENTITY_NOHITBEAM
which controls if calling HitBeam()
will
ever return that mesh. The old CS_ENTITY_INVISIBLE
has been changed
so that it is now a combination of both flags.
An important change is that setting the CS_ENTITY_INVISIBLEMESH
flag
on a parent in a hierarchy will no longer make the children invisible. You
now have to set the invisible flag manually on all children in the hierarchy.
Support for skeletal sprites has been removed, along with the following related interfaces. Use the `sprcal3d' mesh object instead. It is more flexible and works correctly. These interfaces have been retired:
iSkeletonState
iSkeletonLimbState
iSkeletonConnection
iSkeletonConnectionState
iSkeletonLimb
In addition, the motion manager plugin has been removed, along with the following related interfaces:
iMotionTemplate
iMotionManager
iSkeletonBone
Meshes that use the CS_ENTITY_CAMERA
flag no longer have to be placed
in a render priority that has the `camera' flag set. This render
priority flag is no longer required (but CS_ENTITY_CAMERA
still is!).
Gouraud is much more commonly used than flat shading and is thus the default
now. To achieve the opposite behaviour (ie the behaviour when
CS_FX_GOURAUD
was not present), use the CS_FX_FLAT
flag.
The most important change is that OPCODE is now prefered over RAPID. The OPCODE plugin is free of restrictions (as opposed to RAPID which can't be used in commercial programs), it is faster, and uses a lot less memory. In future we will remove the RAPID plugin.
The iCollideSystem::CollidePath()
utility method has been relocated to
csColliderHelper::CollidePath()
. In addition there are a few extra
overloads that can make life easier for calculating collisions on a path.
The isometric engine has been removed. It was beyond repair. The `isotest' application remains, though, and demonstrates how you can simulate an isometric look with the normal 3D engine.
The following plugins and programs also have been removed (along with any parts of the API they provided exclusively), because they are unmaintained and not currently usable. For more discussion see mailing list posts at:
http://sourceforge.net/mailarchive/message.php?msg_id=8645194
http://sourceforge.net/mailarchive/message.php?msg_id=8296024
http://sourceforge.net/mailarchive/message.php?msg_id=8296017
http://sourceforge.net/mailarchive/message.php?msg_id=8295883
terrbig
(use new terrain features in the new renderer)
cloth
cocoa2d
graphics driver for MacOSX
rle
video codec
milk2spr
(use the cal3d conversion)
svgalib
graphics driver
cssocket
(provided iNetworkDriver
, iNetworkListener
, and iNetworkConnection
)
ensocket
(provided iNetworkDriver2
and iNetworkSocket2
)
netman
picogui
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated using texi2html 1.76.