engineObject.h
Engine/source/console/engineObject.h
Disable TMM for this file.
Classes:
Singleton class that uses the C runtime memory routines for allocating objects.
Base class for all objects that may be passed to the control layer.
Interface for object memory allocation.
A statically allocated engine object.
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.
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.
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.
DECLARE_INSCOPE(name) typedef name __DeclScope;
Assign the current class and all its subclasses to the given export scope.
DECLARE_INSTANTIABLE() typedef :: __IsInstantiableType;
Declare that this class and all its subclasses can be instantiated through the API using their respective create() functions.
DECLARE_NONINSTANTIABLE() typedef :: __IsInstantiableType;
Declare that this class and all its subclasses cannot be instantiated through the API, i.e.
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.
DECLARE_STATIC_CLASS(type) private: \ static __engineExportScopeInst; \ static & __engineExportScope() \ { return __engineExportScopeInst; } \ public: \ template< typename > friend struct ::; \
Declare a static class, i.e.
DEFINE_CREATE_METHOD() template< typename > \ static * __create()
Define a custom create function for this class and its subclasses.
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.
IMPLEMENT_DISPOSABLE(type) ( type, onDispose, , (), (), \ "Called before the instance is disposed." );
Matching implement for DECLARE_DISPOSABLE.
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.
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.
IMPLEMENT_STATIC_CLASS(type, scope, doc) type::__engineExportScopeInst( #type, &< scope >()(), doc );
Matching implement for DECLARE_STATIC_CLASS.
PROPERTY(name, numElements, doc, flags) { #name, doc, numElements, flags },
Define a property on the current class.
PROPERTY_GROUP(name, numElements, doc) { #name, doc, numElements, },
Public Typedefs
EngineObjectRef
EngineObjectWeakRef
Public Functions
TYPEOF(const EngineObject * object)
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:Parameters:engineFunctions.h must be included for this macro to work.
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:Parameters:If you want the export name to be different to the actual class name, use a typedef.
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:Parameters:Case is ignored when matching get and set methods to property definitions.
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. |
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