engineObject.h

Engine/source/console/engineObject.h

Disable TMM for this file.

More...

Classes:

class

Singleton class that uses the C runtime memory routines for allocating objects.

class

Base class for all objects that may be passed to the control layer.

class

Interface for object memory allocation.

class

A statically allocated engine object.

Public Defines

define
DECLARE_ABSTRACT_CLASS(type, super)    public:                                                                             \
      typedef type ThisType;                                                           \
      typedef super SuperType;                                                         \
      template< typename  > friend struct ::;                        \
      template< typename  > friend struct ::;                                   \
      template< typename  > friend * ();                                      \
      template< typename , typename Base > friend class ::;        \
   private:                                                                            \
      typedef ::< ThisType > _ClassBase;                   \
      static < ThisType, _ClassBase > _smTypeInfo;                  \
      static & __engineExportScope();                                 \
      static & _smPropertyTable;                                    \
      virtual  * __typeinfo() ;                                \
   public:

Declare an abstract class type derived from the class super.

define
DECLARE_CALLBACK(returnType, name, args)    virtual returnType name ## _callback args

Define a method that calls back into the control layer.

define
DECLARE_CLASS(type, super)    public:                                                                             \
      typedef type ThisType;                                                           \
      typedef super SuperType;                                                         \
      template< typename  > friend struct ::;                        \
      template< typename  > friend struct ::;                                   \
      template< typename  > friend * ();                                      \
      template< typename , typename Base > friend class ::;        \
   private:                                                                            \
      typedef ::< ThisType > _ClassBase;                   \
      static < ThisType, _ClassBase > _smTypeInfo;                  \
      static & __engineExportScope();                                 \
      static & _smPropertyTable;                                    \
      virtual  * __typeinfo() ;                                \
   public:

Declare a concrete class type derived from the class super.

define
DECLARE_DISPOSABLE()    protected:                                                                          \
      typedef :: __IsDisposableType;                                           \
      ( , onDispose, () );                                         \
   public:                                                                             \
      virtual  destroySelf()                                                       \
      {                                                                                \
         onDispose_callback();                                                         \
         SuperType::destroySelf();                                                     \
      }

Declare a class for which the object's may be forcefully disposed of by the engine.

define
DECLARE_INSCOPE(name)    typedef name __DeclScope;

Assign the current class and all its subclasses to the given export scope.

define
DECLARE_INSTANTIABLE()    typedef :: __IsInstantiableType;

Declare that this class and all its subclasses can be instantiated through the API using their respective create() functions.

define
DECLARE_NONINSTANTIABLE()    typedef :: __IsInstantiableType;

Declare that this class and all its subclasses cannot be instantiated through the API, i.e.

define
DECLARE_SINGLETON()    private:                                                                            \
      static ThisType* _smInstance;                                                    \
      struct _clearInstance;                                                           \
      friend struct _clearInstance;                                                    \
      struct _clearInstance {                                                          \
         ~_clearInstance() { _smInstance = ; }                                     \
      } _clearInstanceInst;                                                            \
   public:                                                                             \
      static ThisType* createSingleton();                                              \
      static  destroySingleton();                                                  \
   protected:                                                                          \
      typedef :: __IsSingletonType;                                            \
                                                                   \
      {                                                                                \
         return createSingleton();                                                     \
      }                                                                                \
   public:                                                                             \
      static ThisType* instance()                                                      \
      {                                                                                \
         return _smInstance;                                                           \
      }

Declare that the current class (and any of its descendents) can only have a single instance.

define
DECLARE_STATIC_CLASS(type)    private:                                                                            \
      static  __engineExportScopeInst;                                \
      static & __engineExportScope()                                  \
         { return __engineExportScopeInst; }                                           \
   public:                                                                             \
      template< typename  > friend struct ::;                                   \

Declare a static class, i.e.

define
DEFINE_CREATE_METHOD()       template< typename  >                                                           \
      static * __create()

Define a custom create function for this class and its subclasses.

define
END_IMPLEMENT_CLASS()          {  }                                                                      \
      };                                                                               \
       _propertyTable                                               \
         ( sizeof( _properties ) / sizeof( _properties[ 0 ] ) - 1, _properties );      \
   } }

Close an IMPLEMENT_CLASS or IMPLEMENT_NONINSTANTIABLE_CLASS block.

define
END_PROPERTY_GROUP()    { , , 0,  },
define
IMPLEMENT_CLASS(type, doc)    ( fn ## type ## _create, create, type, type*, (),,,                    \
      "Create   " #type " instance.\n"                                             \
      "@return A  " #type " instance with  reference  of 1." )                \
   {                                                                                   \
      return ::< type >();                                                      \
   }                                                                                   \
   ( type, doc )

Matching implement to DECLARE_CLASS for classes that are instantiable through the API.

define
IMPLEMENT_DISPOSABLE(type)    ( type, onDispose, , (), (),                              \
      "Called before the instance is disposed." );

Matching implement for DECLARE_DISPOSABLE.

define
IMPLEMENT_NONINSTANTIABLE_CLASS(type, doc)    ( fn ## type ## _staticGetType, staticGetType, type,  *, (),,, \
      "Get the type info object  the " #type " class.\n\n"                          \
      "@return The type info object  " #type )                                      \
   {                                                                                   \
      return ::< type >();                                                         \
   }                                                                                   \
   < type::ThisType, type::_ClassBase >                             \
      type::_smTypeInfo( #type, &< __DeclScope >()(), doc );                     \
   & type::__engineExportScope() { return type::_smTypeInfo; }        \
    * type::__typeinfo()  { return &_smTypeInfo; }             \
   namespace { namespace _ ## type {                                                   \
      extern  _propertyTable;                                       \
   } }                                                                                 \
   & type::_smPropertyTable = _ ## type::_propertyTable;            \
   namespace { namespace _ ## type {                                                   \
       _properties[] = {

Matching implement for DECLARE_ABSTRACT_CLASS or DECLARE_CLASS for classes that are not instantiable through the API.

define
IMPLEMENT_SINGLETON(type)    type::ThisType* type::_smInstance;                                                  \
   type::ThisType* type::createSingleton()                                             \
   {                                                                                   \
      ( _smInstance !=  )                                                        \
      {                                                                                \
         ( "%s::create -  instance already created",               \
            TYPE< ThisType >()->getFullyQualifiedExportName().c_str() );               \
         return ;                                                                  \
      }                                                                                \
      _smInstance =  ThisType();                                                    \
      _smInstance->incRefCount();                                                      \
      return _smInstance;                                                              \
   }                                                                                   \
    type::destroySingleton()                                                       \
   {                                                                                   \
      ( !_smInstance )                                                               \
         return;                                                                       \
      ( ::< __IsDisposableType >() )                                       \
         _smInstance->destroySelf();                                                   \
      else                                                                             \
         _smInstance->decRefCount();                                                   \
   }                                                                                   \
   ( type, getInstance, type*, (),,                         \
      "Get the singleton " #type " instance.\n\n"                                      \
      "@return The " #type " singleton." )                                             \
   {                                                                                   \
      return type::instance();                                                         \
   }

Matching implement for DECLARE_SINGLETON.

define
IMPLEMENT_STATIC_CLASS(type, scope, doc)     type::__engineExportScopeInst( #type, &< scope >()(), doc );

Matching implement for DECLARE_STATIC_CLASS.

define
PROPERTY(name, numElements, doc, flags)    { #name, doc, numElements, flags },

Define a property on the current class.

define
PROPERTY_GROUP(name, numElements, doc)    { #name, doc, numElements,  },

Public Typedefs

EngineObjectRef 
EngineObjectWeakRef 

Public Functions

T *

Return the type info object for the dynamic type of the given object.

Detailed Description

Disable TMM for this file.

This file contains the framework for defining class types for interfacing through engine API.

Public Defines

DECLARE_ABSTRACT_CLASS(type, super)    public:                                                                             \
      typedef type ThisType;                                                           \
      typedef super SuperType;                                                         \
      template< typename  > friend struct ::;                        \
      template< typename  > friend struct ::;                                   \
      template< typename  > friend * ();                                      \
      template< typename , typename Base > friend class ::;        \
   private:                                                                            \
      typedef ::< ThisType > _ClassBase;                   \
      static < ThisType, _ClassBase > _smTypeInfo;                  \
      static & __engineExportScope();                                 \
      static & _smPropertyTable;                                    \
      virtual  * __typeinfo() ;                                \
   public:

Declare an abstract class type derived from the class super.

class MyClass : public EngineObject
{
    DECLARE_ABSTRACT_CLASS( MyClass, EngineObject );
};

Parameters:

type

C++ class type.

super

C++ class type of the superclass. May be void only for EngineObject.

DECLARE_CALLBACK(returnType, name, args)    virtual returnType name ## _callback args

Define a method that calls back into the control layer.

DECLARE_CLASS(type, super)    public:                                                                             \
      typedef type ThisType;                                                           \
      typedef super SuperType;                                                         \
      template< typename  > friend struct ::;                        \
      template< typename  > friend struct ::;                                   \
      template< typename  > friend * ();                                      \
      template< typename , typename Base > friend class ::;        \
   private:                                                                            \
      typedef ::< ThisType > _ClassBase;                   \
      static < ThisType, _ClassBase > _smTypeInfo;                  \
      static & __engineExportScope();                                 \
      static & _smPropertyTable;                                    \
      virtual  * __typeinfo() ;                                \
   public:

Declare a concrete class type derived from the class super.

Whether the class can be instantiated by the control layer depends on its instantiability.

class MyClass : public EngineObject
{
    DECLARE_CLASS( MyClass, EngineObject );
};

Parameters:

type

C++ class type.

super

C++ class type of the superclass. May be void only for EngineObject.

DECLARE_DISPOSABLE()    protected:                                                                          \
      typedef :: __IsDisposableType;                                           \
      ( , onDispose, () );                                         \
   public:                                                                             \
      virtual  destroySelf()                                                       \
      {                                                                                \
         onDispose_callback();                                                         \
         SuperType::destroySelf();                                                     \
      }

Declare a class for which the object's may be forcefully disposed of by the engine.

In essense, this means that such objects can only be weak-referenced from within the control layer as their lifetime is ultimately controlled by the engine. This is used for all resource type objects that are owned by their devices.

An alternative to disposable types would be to shield the control layer from direct access to these objects and rather expose only intermediary objects. However, at some point this just gets crazy. The control layer wraps around engine objects that wrap around internal objects. The internal object goes away, invalidates the native wrapper which invalidates the managed wrapper.

By exposing the control layer directly to in-engine resources using disposable objects, intermediary steps and code are made unnecessary while the control layer is still made aware of the fact that ownership of these objects ultimately and firmly belongs with the engine.

One important guarantee for disposable types is that an object will not go away unless the control layer calls into the engine. This means that these objects will not magically disappear while managed code is running.

note:

This macro automatically redefines destroySelf(). @warn Reference-counting is still used for disposable types!! This means that if the reference-count drops to zero, the object will be deleted as any other object.

DECLARE_INSCOPE(name)    typedef name __DeclScope;

Assign the current class and all its subclasses to the given export scope.

May be overridden by subclasses.

class MyClass : public EngineObject
{
    DECLARE_CLASS( MyClass, EngineObject );
    DECLARE_INSCOPE( MyAPI );
};

DECLARE_INSTANTIABLE()    typedef :: __IsInstantiableType;

Declare that this class and all its subclasses can be instantiated through the API using their respective create() functions.

May be overridden by subclasses.

class MyClass : public EngineObject
{
    DECLARE_CLASS( MyClass, EngineObject );
    DECLARE_INSTANTIABLE;
};

DECLARE_NONINSTANTIABLE()    typedef :: __IsInstantiableType;

Declare that this class and all its subclasses cannot be instantiated through the API, i.e.

objects of these classes can only be created inside the engine.

class MyClass : public EngineObject
{
    DECLARE_CLASS( MyClass, EngineObject );
    DECLARE_NONINSTANTIABLE;
};

DECLARE_SINGLETON()    private:                                                                            \
      static ThisType* _smInstance;                                                    \
      struct _clearInstance;                                                           \
      friend struct _clearInstance;                                                    \
      struct _clearInstance {                                                          \
         ~_clearInstance() { _smInstance = ; }                                     \
      } _clearInstanceInst;                                                            \
   public:                                                                             \
      static ThisType* createSingleton();                                              \
      static  destroySingleton();                                                  \
   protected:                                                                          \
      typedef :: __IsSingletonType;                                            \
                                                                   \
      {                                                                                \
         return createSingleton();                                                     \
      }                                                                                \
   public:                                                                             \
      static ThisType* instance()                                                      \
      {                                                                                \
         return _smInstance;                                                           \
      }

Declare that the current class (and any of its descendents) can only have a single instance.

class MySingletonClass : public EngineObject
{
    DECLARE_CLASS( MySingletonClass, EngineObject );
    DECLARE_SINGLETON;
};

note:

At the moment, DECLARE_SINGLETON disallows the use of custom create methods on the same class.

DECLARE_STATIC_CLASS(type)    private:                                                                            \
      static  __engineExportScopeInst;                                \
      static & __engineExportScope()                                  \
         { return __engineExportScopeInst; }                                           \
   public:                                                                             \
      template< typename  > friend struct ::;                                   \

Declare a static class, i.e.

a class which only acts as an export scope. Static classes cannot be instantiated, neither through the API nor inside the engine (at least in a form that would be usable within the API).

class MyFunctions
{
    DECLARE_STATIC_CLASS( MyFunctions );
};

IMPLEMENT_STATIC_CLASS( MyFunctions,, "doc" );

DefineStaticEngineMethod( MyFunctions, doSomething, void, (),, "" )
{
   // ...
}

Parameters:

type

The C++ class type.

DEFINE_CREATE_METHOD()       template< typename  >                                                           \
      static * __create()

Define a custom create function for this class and its subclasses.

Create functions are used to create new instances of class types. This code will be called by the automatically generated "createXXX" functions exported through the API.

The type of class being created is available to the code as the type parameter "T" which is guaranteed to be a subtype of the current class type.

class MyClass : public EngineObject
{
       DECLARE_CLASS( MyClass, EngineObject );
    protected:
       DEFINE_CREATE_METHOD
       {
          T* object = new T();
          object->incRefCount();
          object->_registerObject();
          return object;
       }
       virtual void _registerObject();
};

note:

A create method must return an object with a reference count of 1.

END_IMPLEMENT_CLASS()          {  }                                                                      \
      };                                                                               \
       _propertyTable                                               \
         ( sizeof( _properties ) / sizeof( _properties[ 0 ] ) - 1, _properties );      \
   } }

Close an IMPLEMENT_CLASS or IMPLEMENT_NONINSTANTIABLE_CLASS block.

END_PROPERTY_GROUP()    { , , 0,  },
IMPLEMENT_CLASS(type, doc)    ( fn ## type ## _create, create, type, type*, (),,,                    \
      "Create   " #type " instance.\n"                                             \
      "@return A  " #type " instance with  reference  of 1." )                \
   {                                                                                   \
      return ::< type >();                                                      \
   }                                                                                   \
   ( type, doc )

Matching implement to DECLARE_CLASS for classes that are instantiable through the API.

note:

engineFunctions.h must be included for this macro to work.

Parameters:
type

The C++ class type.

doc

Documentation string.

IMPLEMENT_DISPOSABLE(type)    ( type, onDispose, , (), (),                              \
      "Called before the instance is disposed." );

Matching implement for DECLARE_DISPOSABLE.

Parameters:

type

The disposable C++ class type.

IMPLEMENT_NONINSTANTIABLE_CLASS(type, doc)    ( fn ## type ## _staticGetType, staticGetType, type,  *, (),,, \
      "Get the type info object  the " #type " class.\n\n"                          \
      "@return The type info object  " #type )                                      \
   {                                                                                   \
      return ::< type >();                                                         \
   }                                                                                   \
   < type::ThisType, type::_ClassBase >                             \
      type::_smTypeInfo( #type, &< __DeclScope >()(), doc );                     \
   & type::__engineExportScope() { return type::_smTypeInfo; }        \
    * type::__typeinfo()  { return &_smTypeInfo; }             \
   namespace { namespace _ ## type {                                                   \
      extern  _propertyTable;                                       \
   } }                                                                                 \
   & type::_smPropertyTable = _ ## type::_propertyTable;            \
   namespace { namespace _ ## type {                                                   \
       _properties[] = {

Matching implement for DECLARE_ABSTRACT_CLASS or DECLARE_CLASS for classes that are not instantiable through the API.

class MyClass : public EngineObject
{
    DECLARE_CLASS( MyClass, EngineObject );
    DECLARE_INSCOPE( MyScope );
    DECLARE_NONINSTANTIABLE;
};

IMPLEMENT_NONINSTANTIABLE_CLASS( MyClass, "My class." )
   PROPERTY( myProperty, 1, "My property.", EnginePropertyTransient )
END_IMPLEMENT_CLASS;

note:

If you want the export name to be different to the actual class name, use a typedef.

Parameters:
type

The C++ class type. @doc Documentation string.

IMPLEMENT_SINGLETON(type)    type::ThisType* type::_smInstance;                                                  \
   type::ThisType* type::createSingleton()                                             \
   {                                                                                   \
      ( _smInstance !=  )                                                        \
      {                                                                                \
         ( "%s::create -  instance already created",               \
            TYPE< ThisType >()->getFullyQualifiedExportName().c_str() );               \
         return ;                                                                  \
      }                                                                                \
      _smInstance =  ThisType();                                                    \
      _smInstance->incRefCount();                                                      \
      return _smInstance;                                                              \
   }                                                                                   \
    type::destroySingleton()                                                       \
   {                                                                                   \
      ( !_smInstance )                                                               \
         return;                                                                       \
      ( ::< __IsDisposableType >() )                                       \
         _smInstance->destroySelf();                                                   \
      else                                                                             \
         _smInstance->decRefCount();                                                   \
   }                                                                                   \
   ( type, getInstance, type*, (),,                         \
      "Get the singleton " #type " instance.\n\n"                                      \
      "@return The " #type " singleton." )                                             \
   {                                                                                   \
      return type::instance();                                                         \
   }

Matching implement for DECLARE_SINGLETON.

Parameters:

type

The C++ class type.

IMPLEMENT_STATIC_CLASS(type, scope, doc)     type::__engineExportScopeInst( #type, &< scope >()(), doc );

Matching implement for DECLARE_STATIC_CLASS.

Parameters:

type

The C++ type of the static class. Also used as export name.

scope

Export scope to place the static class in.

doc

Documentation string.

PROPERTY(name, numElements, doc, flags)    { #name, doc, numElements, flags },

Define a property on the current class.

A property named XXX must have a corresponding "getXXX" and/or "setXXX" accessor method defined on the class. If there is only a "setXXX" method, the property is write-only. If there is only a "getXXX", the property is read-only. If both are defined, the property is read-write.

If the accessors are static methods, the property is a static property. Otherwise it is an instance property.

The type of the property is determined by its accessor methods.

A getXXX method must take no arguments and return a value. A setXXX method must take one argument and return void.

If the property is indexed (numElements != 1), the get and set methods take an additional first argument which is the integer index (type S32). Additionally, the get method must be called "getXXXElement" and the set method must be called "setXXXElement".

Indexed properties may be either fixed-size or variable-sized. Fixed-size indexed properties have numElements count > 1. Variable-size indexed properties have a numElements count of 0. Variable-sized indexed properties must have an additional method "getXXXCount" that returns the current count of elements for the given property.

IMPLEMENT_CLASS( MyClass, "My class." )
   PROPERTY( myProperty, 1, "My property.", EnginePropertyTransient )
END_IMPLEMENT_CLASS;

note:

Case is ignored when matching get and set methods to property definitions.

Parameters:
name

The name of the property. Must correspond with the get and/or set methods.

numElements

If this is a fixed size array property, this is the number of elements the fixed array has. Otherwise 1.

doc

Documentation string.

flags

A combination of EnginePropertyFlags or simply 0 if not applicable.

PROPERTY_GROUP(name, numElements, doc)    { #name, doc, numElements,  },

Public Typedefs

typedef StrongRefPtr< EngineObject > EngineObjectRef 
typedef WeakRefPtr< EngineObject > EngineObjectWeakRef 

Public Functions

_CREATE()

TYPEOF(const EngineObject * object)

Return the type info object for the dynamic type of the given object.

Parameters:

object

An EngineObject or NULL.

return:

An EngineTypeInfo instance or NULL if object is NULL.

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef _ENGINEOBJECT_H_
 25#define _ENGINEOBJECT_H_
 26
 27#ifndef _ENGINETYPES_H_
 28   #include "console/engineTypes.h"
 29#endif
 30#ifndef _REFBASE_H_
 31   #include "core/util/refBase.h"
 32#endif
 33
 34/// Disable TMM for this file.
 35#include "platform/tmm_off.h"
 36
 37
 38/// @file
 39/// This file contains the framework for defining class types for interfacing
 40/// through engine API.
 41
 42
 43class EngineObject;
 44
 45
 46/// Assign the current class and all its subclasses to the given export scope.
 47/// May be overridden by subclasses.
 48///
 49/// @code
 50/// class MyClass : public EngineObject
 51/// {
 52///     DECLARE_CLASS( MyClass, EngineObject );
 53///     DECLARE_INSCOPE( MyAPI );
 54/// };
 55/// @endcode
 56#define DECLARE_INSCOPE( name )                                                        \
 57   typedef name __DeclScope;
 58   
 59/// Declare that this class and all its subclasses cannot be instantiated through
 60/// the API, i.e. objects of these classes can only be created inside the engine.
 61///
 62/// @code
 63/// class MyClass : public EngineObject
 64/// {
 65///     DECLARE_CLASS( MyClass, EngineObject );
 66///     DECLARE_NONINSTANTIABLE;
 67/// };
 68/// @endcode
 69#define DECLARE_NONINSTANTIABLE                                                       \
 70   typedef ::FalseType __IsInstantiableType;
 71      
 72/// Declare that this class and all its subclasses can be instantiated through the
 73/// API using their respective create() functions.
 74///
 75/// May be overridden by subclasses.
 76///
 77/// @code
 78/// class MyClass : public EngineObject
 79/// {
 80///     DECLARE_CLASS( MyClass, EngineObject );
 81///     DECLARE_INSTANTIABLE;
 82/// };
 83/// @endcode
 84#define DECLARE_INSTANTIABLE                                                           \
 85   typedef ::TrueType __IsInstantiableType;
 86
 87/// Declare a class for which the object's may be forcefully disposed of by the engine.
 88/// In essense, this means that such objects can only be weak-referenced from within the
 89/// control layer as their lifetime is ultimately controlled by the engine.  This is
 90/// used for all resource type objects that are owned by their devices.
 91///
 92/// An alternative to disposable types would be to shield the control layer from direct
 93/// access to these objects and rather expose only intermediary objects.  However, at some
 94/// point this just gets crazy.  The control layer wraps around engine objects that wrap
 95/// around internal objects.  The internal object goes away, invalidates the native wrapper
 96/// which invalidates the managed wrapper.
 97///
 98/// By exposing the control layer directly to in-engine resources using disposable objects,
 99/// intermediary steps and code are made unnecessary while the control layer is still made
100/// aware of the fact that ownership of these objects ultimately and firmly belongs with
101/// the engine.
102///
103/// One important guarantee for disposable types is that an object will <em>not</em> go
104/// away <em>unless</em> the control layer calls into the engine.  This means that these
105/// objects will not magically disappear while managed code is running.
106///
107/// @note This macro automatically redefines destroySelf().
108/// @warn Reference-counting is still used for disposable types!!  This means that if the
109///   reference-count drops to zero, the object will be deleted as any other object.
110///
111/// @see IMPLEMENT_DISPOSABLE
112#define DECLARE_DISPOSABLE                                                             \
113   protected:                                                                          \
114      typedef ::TrueType __IsDisposableType;                                           \
115      DECLARE_CALLBACK( void, onDispose, () );                                         \
116   public:                                                                             \
117      virtual void destroySelf()                                                       \
118      {                                                                                \
119         onDispose_callback();                                                         \
120         SuperType::destroySelf();                                                     \
121      }
122
123/// Matching implement for DECLARE_DISPOSABLE.
124///
125/// @param type The disposable C++ class type.
126#define IMPLEMENT_DISPOSABLE( type )                                                   \
127   IMPLEMENT_NEW_CALLBACK( type, onDispose, void, (), (),                              \
128      "Called before the instance is disposed." );
129      
130/// Declare that the current class (and any of its descendents) can only have a single instance.
131///
132/// @code
133/// class MySingletonClass : public EngineObject
134/// {
135///     DECLARE_CLASS( MySingletonClass, EngineObject );
136///     DECLARE_SINGLETON;
137/// };
138/// @endcode
139///
140/// @note At the moment, DECLARE_SINGLETON disallows the use of custom create methods
141///   on the same class.
142#define DECLARE_SINGLETON                                                              \
143   private:                                                                            \
144      static ThisType* _smInstance;                                                    \
145      struct _clearInstance;                                                           \
146      friend struct _clearInstance;                                                    \
147      struct _clearInstance {                                                          \
148         ~_clearInstance() { _smInstance = NULL; }                                     \
149      } _clearInstanceInst;                                                            \
150   public:                                                                             \
151      static ThisType* createSingleton();                                              \
152      static void destroySingleton();                                                  \
153   protected:                                                                          \
154      typedef ::TrueType __IsSingletonType;                                            \
155      DEFINE_CREATE_METHOD                                                             \
156      {                                                                                \
157         return createSingleton();                                                     \
158      }                                                                                \
159   public:                                                                             \
160      static ThisType* instance()                                                      \
161      {                                                                                \
162         return _smInstance;                                                           \
163      }
164
165/// Matching implement for DECLARE_SINGLETON.
166/// @param type The C++ class type.
167#define IMPLEMENT_SINGLETON( type )                                                    \
168   type::ThisType* type::_smInstance;                                                  \
169   type::ThisType* type::createSingleton()                                             \
170   {                                                                                   \
171      if( _smInstance != NULL )                                                        \
172      {                                                                                \
173         Con::errorf( "%s::create - Singleton instance already created",               \
174            TYPE< ThisType >()->getFullyQualifiedExportName().c_str() );               \
175         return NULL;                                                                  \
176      }                                                                                \
177      _smInstance = new ThisType();                                                    \
178      _smInstance->incRefCount();                                                      \
179      return _smInstance;                                                              \
180   }                                                                                   \
181   void type::destroySingleton()                                                       \
182   {                                                                                   \
183      if( !_smInstance )                                                               \
184         return;                                                                       \
185      if( ::IsTrueType< __IsDisposableType >() )                                       \
186         _smInstance->destroySelf();                                                   \
187      else                                                                             \
188         _smInstance->decRefCount();                                                   \
189   }                                                                                   \
190   DefineNewEngineStaticMethod( type, getInstance, type*, (),,                         \
191      "Get the singleton " #type " instance.\n\n"                                      \
192      "@return The " #type " singleton." )                                             \
193   {                                                                                   \
194      return type::instance();                                                         \
195   }
196
197/// Declare a static class, i.e. a class which only acts as an export scope.  Static
198/// classes cannot be instantiated, neither through the API nor inside the engine (at
199/// least in a form that would be usable within the API).
200///
201/// @code
202/// class MyFunctions
203/// {
204///     DECLARE_STATIC_CLASS( MyFunctions );
205/// };
206///
207/// IMPLEMENT_STATIC_CLASS( MyFunctions,, "doc" );
208/// 
209/// DefineStaticEngineMethod( MyFunctions, doSomething, void, (),, "" )
210/// {
211///    // ...
212/// }
213/// @endcode
214///
215/// @param type The C++ class type.
216///
217/// @see IMPLEMENT_STATIC_CLASS
218#define DECLARE_STATIC_CLASS( type )                                                   \
219   private:                                                                            \
220      static EngineExportScope __engineExportScopeInst;                                \
221      static EngineExportScope& __engineExportScope()                                  \
222         { return __engineExportScopeInst; }                                           \
223   public:                                                                             \
224      template< typename T > friend struct ::_SCOPE;                                   \
225      
226/// Matching implement for DECLARE_STATIC_CLASS.
227///
228/// @param type The C++ type of the static class.  Also used as export name.
229/// @param scope Export scope to place the static class in.
230/// @param doc Documentation string.
231#define IMPLEMENT_STATIC_CLASS( type, scope, doc )                                     \
232   EngineExportScope type::__engineExportScopeInst( #type, &_SCOPE< scope >()(), doc );
233
234/// Declare a concrete class @a type derived from the class @a super.  Whether the
235/// class can be instantiated by the control layer depends on its instantiability.
236///
237/// @code
238/// class MyClass : public EngineObject
239/// {
240///     DECLARE_CLASS( MyClass, EngineObject );
241/// };
242/// @endcode
243///
244/// @param type C++ class type.
245/// @param super C++ class type of the superclass.  May be void only for EngineObject.
246///
247/// @see IMPLEMENT_CLASS
248/// @see IMPLEMENT_NONINSTANTIABLE_CLASS
249#define DECLARE_CLASS( type, super )                                                   \
250   public:                                                                             \
251      typedef type ThisType;                                                           \
252      typedef super SuperType;                                                         \
253      template< typename T > friend struct ::_EngineTypeTraits;                        \
254      template< typename T > friend struct ::_SCOPE;                                   \
255      template< typename T > friend T* _CREATE();                                      \
256      template< typename T, typename Base > friend class ::EngineClassTypeInfo;        \
257   private:                                                                            \
258      typedef ::_Private::_ConcreteClassBase< ThisType > _ClassBase;                   \
259      static EngineClassTypeInfo< ThisType, _ClassBase > _smTypeInfo;                  \
260      static EngineExportScope& __engineExportScope();                                 \
261      static EnginePropertyTable& _smPropertyTable;                                    \
262      virtual const EngineTypeInfo* __typeinfo() const;                                \
263   public:
264   
265/// Declare an abstract class @a type derived from the class @a super.
266///
267/// @code
268/// class MyClass : public EngineObject
269/// {
270///     DECLARE_ABSTRACT_CLASS( MyClass, EngineObject );
271/// };
272/// @endcode
273///
274/// @param type C++ class type.
275/// @param super C++ class type of the superclass.  May be void only for EngineObject.
276///
277/// @see IMPLEMENT_NONINSTANTIABLE_CLASS
278#define DECLARE_ABSTRACT_CLASS( type, super )                                          \
279   public:                                                                             \
280      typedef type ThisType;                                                           \
281      typedef super SuperType;                                                         \
282      template< typename T > friend struct ::_EngineTypeTraits;                        \
283      template< typename T > friend struct ::_SCOPE;                                   \
284      template< typename T > friend T* _CREATE();                                      \
285      template< typename T, typename Base > friend class ::EngineClassTypeInfo;        \
286   private:                                                                            \
287      typedef ::_Private::_AbstractClassBase< ThisType > _ClassBase;                   \
288      static EngineClassTypeInfo< ThisType, _ClassBase > _smTypeInfo;                  \
289      static EngineExportScope& __engineExportScope();                                 \
290      static EnginePropertyTable& _smPropertyTable;                                    \
291      virtual const EngineTypeInfo* __typeinfo() const;                                \
292   public:
293
294/// Matching implement for DECLARE_ABSTRACT_CLASS or DECLARE_CLASS for classes
295/// that are not instantiable through the API.
296///
297/// @code
298/// class MyClass : public EngineObject
299/// {
300///     DECLARE_CLASS( MyClass, EngineObject );
301///     DECLARE_INSCOPE( MyScope );
302///     DECLARE_NONINSTANTIABLE;
303/// };
304///
305/// IMPLEMENT_NONINSTANTIABLE_CLASS( MyClass, "My class." )
306///    PROPERTY( myProperty, 1, "My property.", EnginePropertyTransient )
307/// END_IMPLEMENT_CLASS;
308/// @endcode
309///
310/// @note If you want the export name to be different to the actual class
311///   name, use a typedef.
312///
313/// @param type The C++ class type.
314/// @doc Documentation string.
315#define IMPLEMENT_NONINSTANTIABLE_CLASS( type, doc )                                   \
316   DEFINE_CALLIN( fn ## type ## _staticGetType, staticGetType, type, const EngineTypeInfo*, (),,, \
317      "Get the type info object for the " #type " class.\n\n"                          \
318      "@return The type info object for " #type )                                      \
319   {                                                                                   \
320      return ::TYPE< type >();                                                         \
321   }                                                                                   \
322   EngineClassTypeInfo< type::ThisType, type::_ClassBase >                             \
323      type::_smTypeInfo( #type, &_SCOPE< __DeclScope >()(), doc );                     \
324   EngineExportScope& type::__engineExportScope() { return type::_smTypeInfo; }        \
325   const EngineTypeInfo* type::__typeinfo() const { return &_smTypeInfo; }             \
326   namespace { namespace _ ## type {                                                   \
327      extern EnginePropertyTable _propertyTable;                                       \
328   } }                                                                                 \
329   EnginePropertyTable& type::_smPropertyTable = _ ## type::_propertyTable;            \
330   namespace { namespace _ ## type {                                                   \
331      EnginePropertyTable::Property _properties[] = {
332
333/// Matching implement to DECLARE_CLASS for classes that are instantiable
334/// through the API.
335///
336/// @note engineFunctions.h must be included for this macro to work.
337///
338/// @param type The C++ class type.
339/// @param doc Documentation string.
340#define IMPLEMENT_CLASS( type, doc )                                                   \
341   DEFINE_CALLIN( fn ## type ## _create, create, type, type*, (),,,                    \
342      "Create a new " #type " instance.\n"                                             \
343      "@return A new " #type " instance with a reference count of 1." )                \
344   {                                                                                   \
345      return ::_CREATE< type >();                                                      \
346   }                                                                                   \
347   IMPLEMENT_NONINSTANTIABLE_CLASS( type, doc )
348   
349/// Close an IMPLEMENT_CLASS or IMPLEMENT_NONINSTANTIABLE_CLASS block.
350#define END_IMPLEMENT_CLASS                                                            \
351         { NULL }                                                                      \
352      };                                                                               \
353      EnginePropertyTable _propertyTable                                               \
354         ( sizeof( _properties ) / sizeof( _properties[ 0 ] ) - 1, _properties );      \
355   } }
356   
357/// Define a property on the current class.
358///
359/// A property named XXX must have a corresponding "getXXX" and/or "setXXX" accessor
360/// method defined on the class.  If there is only a "setXXX" method, the property is
361/// write-only.  If there is only a "getXXX", the property is read-only.  If both are
362/// defined, the property is read-write.
363///
364/// If the accessors are static methods, the property is a static property.  Otherwise
365/// it is an instance property.
366///
367/// The type of the property is determined by its accessor methods.
368///
369/// A getXXX method must take no arguments and return a value.  A setXXX method must take
370/// one argument and return void.
371///
372/// If the property is indexed (@a numElements != 1), the get and set methods take an
373/// additional first argument which is the integer index (type S32).  Additionally, the get method
374/// must be called "getXXXElement" and the set method must be called "setXXXElement".
375///
376/// Indexed properties may be either fixed-size or variable-sized.  Fixed-size indexed
377/// properties have numElements count > 1.  Variable-size indexed properties have a
378/// numElements count of 0.  Variable-sized indexed properties must have an additional
379/// method "getXXXCount" that returns the current count of elements for the given property.
380///
381/// @code
382/// IMPLEMENT_CLASS( MyClass, "My class." )
383///    PROPERTY( myProperty, 1, "My property.", EnginePropertyTransient )
384/// END_IMPLEMENT_CLASS;
385/// @endcode
386///
387/// @note Case is ignored when matching get and set methods to property definitions.
388///
389/// @param name The name of the property.  Must correspond with the get and/or set methods.
390/// @param numElements If this is a fixed size array property, this is the number of elements
391///   the fixed array has.  Otherwise 1.
392/// @param doc Documentation string.
393/// @param flags A combination of EnginePropertyFlags or simply 0 if not applicable.
394///
395/// @see EnginePropertyFlags
396#define PROPERTY( name, numElements, doc, flags )                                      \
397   { #name, doc, numElements, flags },
398   
399///
400#define PROPERTY_GROUP( name, numElements, doc )                                       \
401   { #name, doc, numElements, EnginePropertyGroupBegin },
402
403///
404#define END_PROPERTY_GROUP                                                             \
405   { NULL, NULL, 0, EnginePropertyGroupEnd },
406
407/// Define a custom create function for this class and its subclasses.  Create
408/// functions are used to create new instances of class types.  This code will be
409/// called by the automatically generated "createXXX" functions exported through
410/// the API.
411///
412/// The type of class being created is available to the code as the type parameter "T"
413/// which is guaranteed to be a subtype of the current class type.
414///
415/// @code
416/// class MyClass : public EngineObject
417/// {
418///        DECLARE_CLASS( MyClass, EngineObject );
419///     protected:
420///        DEFINE_CREATE_METHOD
421///        {
422///           T* object = new T();
423///           object->incRefCount();
424///           object->_registerObject();
425///           return object;
426///        }
427///        virtual void _registerObject();
428/// };
429/// @endcode
430///
431/// @note A create method must return an object with a reference count of 1.
432#define DEFINE_CREATE_METHOD                                                           \
433      template< typename T >                                                           \
434      static T* __create()
435
436/// Define a method that calls back into the control layer.
437///
438/// @see IMPLEMENT_CALLBACK
439#define DECLARE_CALLBACK( returnType, name, args )  \
440   virtual returnType name ## _callback args
441
442
443// Our backdoor into calling the __create method on any class even if it is
444// protected or private.  This function is automatically made friends of any
445// EngineObject class.  Should be used except by internal API code.
446template< typename T >
447inline T* _CREATE()
448{
449   return T::template __create< T >();
450}
451
452
453/// Interface for object memory allocation.
454class IEngineObjectPool
455{
456   public:
457   
458      /// Allocate a new object memory block of the given size.
459      /// @return Pointer to a new memory block or NULL on failure.
460      virtual void* allocateObject( U32 size TORQUE_TMM_ARGS_DECL ) = 0;
461      
462      /// Return the member for the object at the given address to the
463      /// allocator for reuse.
464      /// @param ptr Pointer to an object memory block previously allocated with allocateObject().
465      virtual void freeObject( void* ptr ) = 0;
466      
467      /// Instance of the object pool to use by default.
468      static IEngineObjectPool* DEFAULT;
469};
470
471
472/// Singleton class that uses the C runtime memory routines for allocating objects.
473class EngineCRuntimeObjectPool : public IEngineObjectPool
474{
475   public:
476   
477      typedef IEngineObjectPool Parent;
478      
479   protected:
480   
481      static EngineCRuntimeObjectPool smInstance;
482      
483   public:
484
485      /// Return the singleton instance of this pool.
486      static EngineCRuntimeObjectPool* instance() { return &smInstance; }
487      
488      // IEngineObjectPool
489      virtual void* allocateObject( U32 size TORQUE_TMM_ARGS_DECL );
490      virtual void freeObject( void* ptr );
491};
492
493
494/// Base class for all objects that may be passed to the control layer.
495///
496/// A set of rules applies to all EngineObject-derived classes:
497///
498/// - Every EngineObject class must have a default constructor.
499/// - The default constructor and the destructor of every EngineObject class must be public.
500/// - If an EngineObject class inherits from multiple classes, the class leading back to EngineObject
501///   must be the @b first class in the list to ensure binary-compatible class layouts.
502/// - EngineObjects are cooperatively reference-counted by both the engine as well as the control
503///   layer.
504class EngineObject : public StrongRefBase
505{
506   public:
507   
508      DECLARE_ABSTRACT_CLASS( EngineObject, void );
509      DECLARE_INSCOPE( _GLOBALSCOPE );
510      DECLARE_INSTANTIABLE;
511   
512      friend const EngineTypeInfo* TYPEOF( const EngineObject* ); // __typeinfo
513      friend void*& _USERDATA( EngineObject* ); // mEngineObjectUserData
514      friend class StaticEngineObject; // mEngineObjectPool
515      
516   protected:
517   
518      typedef ::FalseType __IsDisposableType;
519      typedef ::FalseType __IsSingletonType;
520
521      DEFINE_CREATE_METHOD
522      {
523         T* object = new T;
524         object->incRefCount();
525         return object; 
526      }
527
528      /// Subclasses should overload this method instead of the public destroySelf().
529      virtual void _destroySelf() {}
530      
531      ///
532      static void* _allocateObject( size_t size, IEngineObjectPool* pool TORQUE_TMM_ARGS_DECL );
533            
534   public:
535      
536      EngineObject();
537      virtual ~EngineObject();
538
539      /// Return a string that describes this instance.  Meant primarily for debugging.
540      virtual String describeSelf() const;
541                  
542      #ifndef TORQUE_DISABLE_MEMORY_MANAGER
543      // Make sure no matter what, we get the new/delete calls.
544      void* operator new( size_t size );
545      void* operator new( size_t size, IEngineObjectPool* pool );
546      #endif
547      
548      /// Allocate a new object in the default object pool.
549      /// @param size Size of the object in bytes.
550      /// @return Memory block for new object; never NULL.
551      void* operator new( size_t size TORQUE_TMM_ARGS_DECL );
552      
553      /// Allocate a new object in the given object pool.
554      ///
555      /// If the given pool's allocateObject returns NULL, the method will fall back
556      /// to the default pool.
557      ///
558      /// @param size Size of the object in bytes.
559      /// @param pool Object pool to allocate the object in.
560      /// @return Memory block for the new object; never NULL.
561      void* operator new( size_t size, IEngineObjectPool* pool TORQUE_TMM_ARGS_DECL );
562      
563      /// Placement new.
564      void* operator new( size_t size, void* ptr ) { return ptr; }
565            
566      /// Release the given object's memory in the pool it has been allocated from.
567      void operator delete( void* ptr );
568
569      /// Return the pool of EngineObjects to which this object belongs.
570      IEngineObjectPool* getEngineObjectPool() const { return mEngineObjectPool; }
571      
572      // StrongRefBase
573      virtual void destroySelf();
574            
575#ifdef TORQUE_DEBUG
576      
577      /// @name Instance Tracking (debugging only)
578      ///
579      /// In debug builds, all EngineObjects are kept on a global list so that it is easy
580      /// to enumerate all live objects at any time.
581      ///
582      /// @note This is @b NOT thread-safe.
583      /// @{
584      
585      /// Type of callback function for iterating over EngineObject instances.
586      typedef void ( *DebugEnumInstancesCallback )( EngineObject* );
587
588      /// Dump describeSelf()s of all live ConsoleObjects to the console.
589      static void debugDumpInstances();
590
591      /// Call the given callback for all instances of the given type.
592      /// Callback may also be NULL in which case the method just iterates
593      /// over all instances of the given type.  This is useful for setting
594      /// a breakpoint during debugging.
595      static void debugEnumInstances( const std::type_info& type, DebugEnumInstancesCallback callback );
596      
597      /// Same as above but uses an export class name and also includes
598      /// inheritance (i.e. enumerates all instances of the given class and
599      /// its subclasses).
600      static void debugEnumInstances( const char* className, DebugEnumInstancesCallback callback );
601
602   private:
603   
604      /// Next object in global link chain of engine objects.
605      /// @note Debug builds only.
606      EngineObject* mNextEngineObject;
607      
608      /// Previous object in global link chain of engine objects.
609      /// @note Debug builds only.
610      EngineObject* mPrevEngineObject;
611
612      /// Total number of engine objects currently instantiated.
613      /// @note Debug builds only.
614      static U32 smNumEngineObjects;
615      
616      /// First object in the global link chain of engine objects.
617      /// @note Debug builds only.
618      static EngineObject* smFirstEngineObject;
619      
620      /// @}
621      
622#endif
623
624   private:
625         
626      /// Object pool to which this object belongs.  If this is NULL,
627      /// the object will not deallocate itself when it is destructed.
628      /// This is useful for inline allocation of objects.
629      IEngineObjectPool* mEngineObjectPool;
630      
631      /// Opaque user data pointer that the control layer may install
632      /// on any engine object.  Most importantly, this allows control layers
633      /// to very easily keep track of EngineObjects that they have already
634      /// created their own wrapper objects for.
635      void* mEngineObjectUserData;
636
637      // Disable array new/delete operators.
638      void* operator new[]( size_t );
639      void operator delete[]( void* );
640};
641
642
643/// A statically allocated engine object.
644///
645/// Static objects have an implicit initial reference count of one and will not
646/// delete themselves even when asked to do so.
647class StaticEngineObject : public EngineObject
648{
649   public:
650
651      DECLARE_ABSTRACT_CLASS( StaticEngineObject, EngineObject );
652      DECLARE_NONINSTANTIABLE;
653      
654      StaticEngineObject();
655      
656      // EngineObject.
657      virtual void destroySelf();
658};
659
660
661typedef StrongRefPtr< EngineObject> EngineObjectRef;
662typedef WeakRefPtr< EngineObject> EngineObjectWeakRef;
663
664
665/// Return the type info object for the dynamic type of the given object.
666/// @param object An EngineObject or NULL.
667/// @return An EngineTypeInfo instance or NULL if @a object is NULL.
668inline const EngineTypeInfo* TYPEOF( const EngineObject* object )
669{
670   if( !object )
671      return NULL;
672   return object->__typeinfo();
673}
674
675
676#include "platform/tmm_on.h"
677#endif // !_ENGINEOBJECT_H_
678