engineAPI.h

Engine/source/console/engineAPI.h

Definitions for exposing engine functionality to the control layer.

More...

Classes:

class

Unmarshal data from client form to engine form.

Namespaces:

namespace

API Definition Macros

The macros in this group allow to create engine API functions that work both with the legacy console system as well as with the new engine export system.

As such, they only support those function features that are available in both systems. This means that for console-style variadic functions, the ConsoleXXX must be used and that for overloaded and/or C-style variadic functions as well as for placing functions in export scopes, DEFINE_CALLIN must be used directly.

When the console system is removed, the console thunking functionality will be removed from these macros but otherwise they will remain unchanged and in place.

define
_CHECK_ENGINE_INITIALIZED(fnName, returnType) ( fnName, returnType )
define
_CHECK_ENGINE_INITIALIZED_IMPL(fnName, returnType)       ( ! )                                                                                           \
      {                                                                                                                          \
         ( "EngineAPI: Engine not initialized when calling " #fnName );                                               \
         return < returnType >::ReturnValue( < returnType >::ReturnValueType() );                \
      }
define
_DefineMethodTrampoline(className, name, returnType, args)    TORQUE_API < returnType >::ReturnValueType \
      fn ## className ## _ ## name ( className* object, < _ ## className ## name ## frame, returnType args >::Args  )\
   {                                                                                                                                            \
      ( className::name, returnType );                                                                                 \
      return < returnType >::ReturnValue(                                                                                       \
         < _ ## className ## name ## frame, returnType args >::jmp( object,  )                                          \
      );                                                                                                                                        \
   }
define
DefineEngineFunction(name, returnType, args, defaultArgs, usage) 

Define a call-in point for calling into the engine.

define
DefineEngineMethod(className, name, returnType, args, defaultArgs, usage) 

Define a call-in point for calling a method on an engine object.

define
DefineEngineStaticMethod(className, name, returnType, args, defaultArgs, usage) 

Define a call-in point for calling into the engine.

define
DefineEngineStringlyVariadicFunction(name, returnType, minArgs, maxArgs, usage)    static inline returnType _fn ## name ## impl ( *,  argc,  *argv);                                  \
   TORQUE_API < returnType >::ReturnValueType fn ## name                                                         \
      (< char*>* vec)                                                                                                 \
   {                                                                                                                             \
      ( name, returnType );                                                                             \
       args(vec->(), vec->address());                                                               \
      return < returnType >::ReturnValue(                                                                        \
         _fn ## name ## impl(, (), args)                                                                           \
      );                                                                                                                         \
   }                                                                                                                             \
   static <  (< char*>* vec) > _fn ## name ## DefaultArgs;                         \
   static  _fn ## name ## FunctionInfo(                                                                        \
      #name,                                                                                                                     \
      &<>()(),                                                                                                             \
      usage,                                                                                                                     \
      #returnType " " #name "(Vector<> args)",                                                                             \
      "fn" #name,                                                                                                                \
      < returnType (< char*>* vec) >(),                                                                           \
      &_fn ## name ## DefaultArgs,                                                                                               \
      ( * ) &fn ## name,                                                                                                     \
      0                                                                                                                          \
   );                                                                                                                            \
    cc_##name##_obj(,#name,_fn ## name ## impl,usage,minArgs,maxArgs); \
      returnType _fn ## name ## impl( *,  argc,  *argv)
define
DefineEngineStringlyVariadicMethod(className, name, returnType, minArgs, maxArgs, usage) 
define
DefineNewEngineFunction(name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## name ## impl args;                                                                            \
   TORQUE_API < returnType >::ReturnValueType fn ## name                                                         \
      ( < returnType args >::Args  )                                                                   \
   {                                                                                                                             \
      ( name, returnType );                                                                             \
      return < returnType >::ReturnValue(                                                                        \
         < returnType args >::jmp( _fn ## name ## impl,  )                                             \
      );                                                                                                                         \
   }                                                                                                                             \
   static <  args > _fn ## name ## DefaultArgs defaultArgs;                                   \
   static  _fn ## name ## FunctionInfo(                                                                        \
      #name,                                                                                                                     \
      &<>()(),                                                                                                             \
      usage,                                                                                                                     \
      #returnType " " #name #args,                                                                                               \
      "fn" #name,                                                                                                                \
      < returnType args >(),                                                                                                 \
      &_fn ## name ## DefaultArgs,                                                                                               \
      ( * ) &fn ## name,                                                                                                     \
      0                                                                                                                          \
   );                                                                                                                            \
   static inline returnType _fn ## name ## impl args
define
DefineNewEngineMethod(className, name, returnType, args, defaultArgs, usage)    struct _ ## className ## name ## frame                                                                                                       \
   {                                                                                                                                            \
      typedef className ObjectType;                                                                                                             \
      className* object;                                                                                                                        \
      inline returnType _exec args ;                                                                                                       \
   };                                                                                                                                           \
   ( className, name, returnType, args );                                                                                \
   static < < _ ## className ## name ## frame,  args >::FunctionType >                \
      _fn ## className ## name ## DefaultArgs defaultArgs;                                                                                      \
   static  _fn ## className ## name ## FunctionInfo(                                                                          \
      #name,                                                                                                                                    \
      &< className >()(),                                                                                                                 \
      usage,                                                                                                                                    \
      "virtual " #returnType " " #name #args,                                                                                                   \
      "fn" #className "_" #name,                                                                                                                \
      < < _ ## className ## name ## frame, returnType args >::FunctionType >(),                                      \
      &_fn ## className ## name ## DefaultArgs,                                                                                                 \
      ( * ) &fn ## className ## _ ## name,                                                                                                  \
      0                                                                                                                                         \
   );                                                                                                                                           \
   returnType _ ## className ## name ## frame::_exec args 
define
DefineNewEngineStaticMethod(className, name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## className ## name ## impl args;                                                                     \
   TORQUE_API < returnType >::ReturnValueType fn ## className ## _ ## name                                             \
      ( < returnType args >::Args  )                                                                         \
   {                                                                                                                                   \
      ( className::name, returnType );                                                                        \
      return < returnType >::ReturnValue(                                                                              \
         < returnType args >::jmp( _fn ## className ## name ## impl,  )                                      \
      );                                                                                                                               \
   }                                                                                                                                   \
   static <  args > _fn ## className ## name ## DefaultArgs defaultArgs;                            \
   static  _fn ## name ## FunctionInfo(                                                                              \
      #name,                                                                                                                           \
      &< className >()(),                                                                                                        \
      usage,                                                                                                                           \
      #returnType " " #name #args,                                                                                                     \
      "fn" #className "_" #name,                                                                                                       \
      < returnType args >(),                                                                                                       \
      &_fn ## className ## name ## DefaultArgs,                                                                                        \
      ( * ) &fn ## className ## _ ## name,                                                                                         \
      0                                                                                                                                \
   );                                                                                                                                  \
   static inline returnType _fn ## className ## name ## impl args

Marshalling

Functions for converting to/from string-based data representations.

note:

This functionality is specific to the console interop.

EngineMarshallData(bool arg, S32 & argc, ConsoleValueRef * argv)
const char *
EngineMarshallData(bool value)
EngineMarshallData(char * arg, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(const char * arg, S32 & argc, ConsoleValueRef * argv)
const char *
EngineMarshallData(const T & arg, S32 & argc, ConsoleValueRef * argv)

Marshal data from native into client form stored directly in client function invocation vector.

const char *

Marshal a single piece of data from native into client form.

const char *
EngineMarshallData(const T * object, S32 & argc, ConsoleValueRef * argv)
const char *
EngineMarshallData(T * object, S32 & argc, ConsoleValueRef * argv)

Thunking

Internal functionality for thunks placed between TorqueScript calls of engine functions and their native implementations.

note:

The functionality in this group is specific to the console interop system.

Public Defines

define
IMPLEMENT_CALLBACK(class, name, returnType, args, argNames, usageString) 

Matching implement for DECLARE_CALLBACK.

define
IMPLEMENT_CONSOLE_CALLBACK(class, name, returnType, args, argNames, usageString)    returnType class::name ## _callback args                                                                                                  \
   {                                                                                                                                         \
      (  )                                                                                                    \
      {                                                                                                                                      \
         static  sName = ->insert( #name );                                                                       \
          cbh( sName, this );                                                                                    \
         return returnType( cbh.call< returnType > argNames );                                                                               \
      }                                                                                                                                      \
      return returnType();                                                                                                                   \
   }                                                                                                                                         \
   namespace {                                                                                                                               \
       _ ## class ## name ## header(                                                                                    \
         #returnType, #args, "" );                                                                                                           \
       _ ## class ## name ## obj( #class, #name, usageString, &_ ## class ## name ## header );                             \
   }
define
IMPLEMENT_GLOBAL_CALLBACK(name, returnType, args, argNames, usageString)    ( cb ## name, name,, returnType, args, 0, usageString );                                                                    \
   returnType name ## _callback args                                                                                                         \
   {                                                                                                                                         \
      ( cb ## name )                                                                                                                       \
         return returnType( cb ## name argNames );                                                                                           \
      (  )                                                                                                    \
      {                                                                                                                                      \
         static  sName = ->insert( #name );                                                                       \
          cbh( sName,  );                                                                                    \
         return returnType( cbh.call< returnType > argNames );                                                                               \
      }                                                                                                                                      \
      return returnType();                                                                                                                   \
   }                                                                                                                                         \
   namespace {                                                                                                                               \
       _ ## name ## header(                                                                                             \
         #returnType, #args, "" );                                                                                                           \
       _ ## name ## obj( , #name, usageString, &_ ## name ## header );                                                 \
   }

Used to define global callbacks not associated with any particular class or namespace.

define
IMPLEMENT_NEW_CALLBACK(class, name, returnType, args, argNames, usageString)    struct _ ## class ## name ## frame { typedef class ObjectType; };                                                                         \
   TORQUE_API < _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name;               \
   TORQUE_API  set_cb ## class ## _ ## name(                                                                                             \
      < _ ## class ## name ## frame, returnType args >::FunctionType fn )                                             \
      { cb ## class ## _ ## name = fn; }                                                                                                     \
   < _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name;                          \
   namespace {                                                                                                                               \
      :: _cb ## class ## name(                                                                                             \
         #name,                                                                                                                              \
         &::< class >()(),                                                                                                             \
         usageString,                                                                                                                        \
         "virtual " #returnType " " #name #args,                                                                                             \
         "cb" #class "_" #name,                                                                                                              \
         ::< < _ ## class ## name ## frame, returnType args >::FunctionType >(),                                  \
         ,                                                                                                                               \
         &cb ## class ## _ ## name,                                                                                                          \
                                                                                                                        \
      );                                                                                                                                     \
   }                                                                                                                                         \
   returnType class::name ## _callback args                                                                                                  \
   {                                                                                                                                         \
      ( cb ## class ## _ ## name ) {                                                                                                       \
          cbh( this, reinterpret_cast<  * >( cb ## class ## _ ## name ) );                                     \
         return returnType( cbh.call< returnType > argNames );                                                                               \
      }                                                                                                                                      \
      return returnType();                                                                                                                   \
   }

Detailed Description

Definitions for exposing engine functionality to the control layer.

This file provides a convenience layer around the underlying engine interop system (which at the moment still includes the legacy TorqueScript interop a.k.a. "console system"). The macros exposed here will automatically take care of all marshalling, value type constraints, reflection info instancing, etc. involved in defining engine API call-ins and call-outs.

note:

At the moment, this file supplies both the legacy TorqueScript console system as well as the new engine export system with the structures and information they need. In the near future, the console-based parts will get purged. This will not result in visible changes to users of the functionality here except for the string-based marshalling functions currently exposed (which will also disappear).

API Definition Macros

The macros in this group allow to create engine API functions that work both with the legacy console system as well as with the new engine export system.

As such, they only support those function features that are available in both systems. This means that for console-style variadic functions, the ConsoleXXX must be used and that for overloaded and/or C-style variadic functions as well as for placing functions in export scopes, DEFINE_CALLIN must be used directly.

When the console system is removed, the console thunking functionality will be removed from these macros but otherwise they will remain unchanged and in place.

_CHECK_ENGINE_INITIALIZED(fnName, returnType) ( fnName, returnType )
_CHECK_ENGINE_INITIALIZED_IMPL(fnName, returnType)       ( ! )                                                                                           \
      {                                                                                                                          \
         ( "EngineAPI: Engine not initialized when calling " #fnName );                                               \
         return < returnType >::ReturnValue( < returnType >::ReturnValueType() );                \
      }
_DefineMethodTrampoline(className, name, returnType, args)    TORQUE_API < returnType >::ReturnValueType \
      fn ## className ## _ ## name ( className* object, < _ ## className ## name ## frame, returnType args >::Args  )\
   {                                                                                                                                            \
      ( className::name, returnType );                                                                                 \
      return < returnType >::ReturnValue(                                                                                       \
         < _ ## className ## name ## frame, returnType args >::jmp( object,  )                                          \
      );                                                                                                                                        \
   }
DefineEngineFunction(name, returnType, args, defaultArgs, usage) 

Define a call-in point for calling into the engine.

Parameters:

name

The name of the function as it should be seen by the control layer.

returnType

The value type returned to the control layer.

args

The argument list as it would appear on the function definition

defaultArgs

The list of default argument values.

usage

The usage doc string for the engine API reference.

DefineEngineFunction( myFunction, int, ( float f, const String& s ), ( "value for s" ), "This is my function." )
{
   return int( f ) + dAtoi( s );
}

DefineEngineMethod(className, name, returnType, args, defaultArgs, usage) 

Define a call-in point for calling a method on an engine object.

Parameters:

name

The name of the C++ class.

name

The name of the method as it should be seen by the control layer.

returnType

The value type returned to the control layer.

args

The argument list as it would appear on the function definition

defaultArgs

The list of default argument values.

usage

The usage doc string for the engine API reference.

DefineEngineMethod( MyClass, myMethod, int, ( float f, const String& s ), ( "value for s" ), "This is my method." )
{
   return object->someMethod( f, s );
}

DefineEngineStaticMethod(className, name, returnType, args, defaultArgs, usage) 

Define a call-in point for calling into the engine.

Unlike with DefineEngineFunction, the statically callable function will be confined to the namespace of the given class.

Parameters:

classname

The name of the C++ class (or a registered export scope).

name

The name of the method as it should be seen by the control layer.

returnType

The value type returned to the control layer.

args

The argument list as it would appear on the function definition

defaultArgs

The list of default argument values.

usage

The usage doc string for the engine API reference.

DefineEngineStaticMethod( MyClass, myMethod, int, ( float f, string s ), ( "value for s" ), "This is my method." )
{
}

DefineEngineStringlyVariadicFunction(name, returnType, minArgs, maxArgs, usage)    static inline returnType _fn ## name ## impl ( *,  argc,  *argv);                                  \
   TORQUE_API < returnType >::ReturnValueType fn ## name                                                         \
      (< char*>* vec)                                                                                                 \
   {                                                                                                                             \
      ( name, returnType );                                                                             \
       args(vec->(), vec->address());                                                               \
      return < returnType >::ReturnValue(                                                                        \
         _fn ## name ## impl(, (), args)                                                                           \
      );                                                                                                                         \
   }                                                                                                                             \
   static <  (< char*>* vec) > _fn ## name ## DefaultArgs;                         \
   static  _fn ## name ## FunctionInfo(                                                                        \
      #name,                                                                                                                     \
      &<>()(),                                                                                                             \
      usage,                                                                                                                     \
      #returnType " " #name "(Vector<> args)",                                                                             \
      "fn" #name,                                                                                                                \
      < returnType (< char*>* vec) >(),                                                                           \
      &_fn ## name ## DefaultArgs,                                                                                               \
      ( * ) &fn ## name,                                                                                                     \
      0                                                                                                                          \
   );                                                                                                                            \
    cc_##name##_obj(,#name,_fn ## name ## impl,usage,minArgs,maxArgs); \
      returnType _fn ## name ## impl( *,  argc,  *argv)
DefineEngineStringlyVariadicMethod(className, name, returnType, minArgs, maxArgs, usage) 
DefineNewEngineFunction(name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## name ## impl args;                                                                            \
   TORQUE_API < returnType >::ReturnValueType fn ## name                                                         \
      ( < returnType args >::Args  )                                                                   \
   {                                                                                                                             \
      ( name, returnType );                                                                             \
      return < returnType >::ReturnValue(                                                                        \
         < returnType args >::jmp( _fn ## name ## impl,  )                                             \
      );                                                                                                                         \
   }                                                                                                                             \
   static <  args > _fn ## name ## DefaultArgs defaultArgs;                                   \
   static  _fn ## name ## FunctionInfo(                                                                        \
      #name,                                                                                                                     \
      &<>()(),                                                                                                             \
      usage,                                                                                                                     \
      #returnType " " #name #args,                                                                                               \
      "fn" #name,                                                                                                                \
      < returnType args >(),                                                                                                 \
      &_fn ## name ## DefaultArgs,                                                                                               \
      ( * ) &fn ## name,                                                                                                     \
      0                                                                                                                          \
   );                                                                                                                            \
   static inline returnType _fn ## name ## impl args
DefineNewEngineMethod(className, name, returnType, args, defaultArgs, usage)    struct _ ## className ## name ## frame                                                                                                       \
   {                                                                                                                                            \
      typedef className ObjectType;                                                                                                             \
      className* object;                                                                                                                        \
      inline returnType _exec args ;                                                                                                       \
   };                                                                                                                                           \
   ( className, name, returnType, args );                                                                                \
   static < < _ ## className ## name ## frame,  args >::FunctionType >                \
      _fn ## className ## name ## DefaultArgs defaultArgs;                                                                                      \
   static  _fn ## className ## name ## FunctionInfo(                                                                          \
      #name,                                                                                                                                    \
      &< className >()(),                                                                                                                 \
      usage,                                                                                                                                    \
      "virtual " #returnType " " #name #args,                                                                                                   \
      "fn" #className "_" #name,                                                                                                                \
      < < _ ## className ## name ## frame, returnType args >::FunctionType >(),                                      \
      &_fn ## className ## name ## DefaultArgs,                                                                                                 \
      ( * ) &fn ## className ## _ ## name,                                                                                                  \
      0                                                                                                                                         \
   );                                                                                                                                           \
   returnType _ ## className ## name ## frame::_exec args 
DefineNewEngineStaticMethod(className, name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## className ## name ## impl args;                                                                     \
   TORQUE_API < returnType >::ReturnValueType fn ## className ## _ ## name                                             \
      ( < returnType args >::Args  )                                                                         \
   {                                                                                                                                   \
      ( className::name, returnType );                                                                        \
      return < returnType >::ReturnValue(                                                                              \
         < returnType args >::jmp( _fn ## className ## name ## impl,  )                                      \
      );                                                                                                                               \
   }                                                                                                                                   \
   static <  args > _fn ## className ## name ## DefaultArgs defaultArgs;                            \
   static  _fn ## name ## FunctionInfo(                                                                              \
      #name,                                                                                                                           \
      &< className >()(),                                                                                                        \
      usage,                                                                                                                           \
      #returnType " " #name #args,                                                                                                     \
      "fn" #className "_" #name,                                                                                                       \
      < returnType args >(),                                                                                                       \
      &_fn ## className ## name ## DefaultArgs,                                                                                        \
      ( * ) &fn ## className ## _ ## name,                                                                                         \
      0                                                                                                                                \
   );                                                                                                                                  \
   static inline returnType _fn ## className ## name ## impl args

Marshalling

Functions for converting to/from string-based data representations.

note:

This functionality is specific to the console interop.

EngineMarshallData(bool arg, S32 & argc, ConsoleValueRef * argv)

EngineMarshallData(bool value)

EngineMarshallData(char * arg, S32 & argc, ConsoleValueRef * argv)

EngineMarshallData(const char * arg, S32 & argc, ConsoleValueRef * argv)

EngineMarshallData(const char * str)

EngineMarshallData(const T & arg, S32 & argc, ConsoleValueRef * argv)

Marshal data from native into client form stored directly in client function invocation vector.

EngineMarshallData(const T & value)

Marshal a single piece of data from native into client form.

EngineMarshallData(const T * object)

EngineMarshallData(const T * object, S32 & argc, ConsoleValueRef * argv)

EngineMarshallData(F32 arg, S32 & argc, ConsoleValueRef * argv)

EngineMarshallData(S32 arg, S32 & argc, ConsoleValueRef * argv)

EngineMarshallData(T * object)

EngineMarshallData(T * object, S32 & argc, ConsoleValueRef * argv)

EngineMarshallData(U32 arg, S32 & argc, ConsoleValueRef * argv)

EngineMarshallData(U32 value)

Thunking

Internal functionality for thunks placed between TorqueScript calls of engine functions and their native implementations.

note:

The functionality in this group is specific to the console interop system.

_EngineConsoleThunkReturnValue(bool value)

_EngineConsoleThunkReturnValue(const char * value)

_EngineConsoleThunkReturnValue(const String & str)

_EngineConsoleThunkReturnValue(const T & value)

_EngineConsoleThunkReturnValue(const T * value)

_EngineConsoleThunkReturnValue(F32 value)

_EngineConsoleThunkReturnValue(S32 value)

_EngineConsoleThunkReturnValue(T * value)

Public Defines

IMPLEMENT_CALLBACK(class, name, returnType, args, argNames, usageString) 

Matching implement for DECLARE_CALLBACK.

@warn With the new interop system, method-style callbacks must not be triggered on object that are being created! This is because the control layer will likely not yet have a fully valid wrapper object in place for the EngineObject under construction.

IMPLEMENT_CONSOLE_CALLBACK(class, name, returnType, args, argNames, usageString)    returnType class::name ## _callback args                                                                                                  \
   {                                                                                                                                         \
      (  )                                                                                                    \
      {                                                                                                                                      \
         static  sName = ->insert( #name );                                                                       \
          cbh( sName, this );                                                                                    \
         return returnType( cbh.call< returnType > argNames );                                                                               \
      }                                                                                                                                      \
      return returnType();                                                                                                                   \
   }                                                                                                                                         \
   namespace {                                                                                                                               \
       _ ## class ## name ## header(                                                                                    \
         #returnType, #args, "" );                                                                                                           \
       _ ## class ## name ## obj( #class, #name, usageString, &_ ## class ## name ## header );                             \
   }
IMPLEMENT_GLOBAL_CALLBACK(name, returnType, args, argNames, usageString)    ( cb ## name, name,, returnType, args, 0, usageString );                                                                    \
   returnType name ## _callback args                                                                                                         \
   {                                                                                                                                         \
      ( cb ## name )                                                                                                                       \
         return returnType( cb ## name argNames );                                                                                           \
      (  )                                                                                                    \
      {                                                                                                                                      \
         static  sName = ->insert( #name );                                                                       \
          cbh( sName,  );                                                                                    \
         return returnType( cbh.call< returnType > argNames );                                                                               \
      }                                                                                                                                      \
      return returnType();                                                                                                                   \
   }                                                                                                                                         \
   namespace {                                                                                                                               \
       _ ## name ## header(                                                                                             \
         #returnType, #args, "" );                                                                                                           \
       _ ## name ## obj( , #name, usageString, &_ ## name ## header );                                                 \
   }

Used to define global callbacks not associated with any particular class or namespace.

IMPLEMENT_NEW_CALLBACK(class, name, returnType, args, argNames, usageString)    struct _ ## class ## name ## frame { typedef class ObjectType; };                                                                         \
   TORQUE_API < _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name;               \
   TORQUE_API  set_cb ## class ## _ ## name(                                                                                             \
      < _ ## class ## name ## frame, returnType args >::FunctionType fn )                                             \
      { cb ## class ## _ ## name = fn; }                                                                                                     \
   < _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name;                          \
   namespace {                                                                                                                               \
      :: _cb ## class ## name(                                                                                             \
         #name,                                                                                                                              \
         &::< class >()(),                                                                                                             \
         usageString,                                                                                                                        \
         "virtual " #returnType " " #name #args,                                                                                             \
         "cb" #class "_" #name,                                                                                                              \
         ::< < _ ## class ## name ## frame, returnType args >::FunctionType >(),                                  \
         ,                                                                                                                               \
         &cb ## class ## _ ## name,                                                                                                          \
                                                                                                                        \
      );                                                                                                                                     \
   }                                                                                                                                         \
   returnType class::name ## _callback args                                                                                                  \
   {                                                                                                                                         \
      ( cb ## class ## _ ## name ) {                                                                                                       \
          cbh( this, reinterpret_cast<  * >( cb ## class ## _ ## name ) );                                     \
         return returnType( cbh.call< returnType > argNames );                                                                               \
      }                                                                                                                                      \
      return returnType();                                                                                                                   \
   }
   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 _ENGINEAPI_H_
  25#define _ENGINEAPI_H_
  26
  27#include <tuple>
  28#include <utility>
  29
  30#ifndef _FIXEDTUPLE_H_
  31#include "fixedTuple.h"
  32#endif
  33
  34#ifndef _CONSOLETYPES_H_
  35#include "console/consoleTypes.h"
  36#endif
  37
  38#ifndef _CONSOLE_H_
  39#include "console/console.h"
  40#endif
  41
  42#ifndef _STRINGFUNCTIONS_H_
  43#include "core/strings/stringFunctions.h"
  44#endif
  45
  46#ifndef _SIMOBJECT_H_
  47#include "console/simObject.h"
  48#endif
  49
  50#ifndef _ENGINEFUNCTIONS_H_
  51#include "console/engineFunctions.h"
  52#endif
  53
  54// Whatever types are used in API definitions, their DECLAREs must be visible to the
  55// macros.  We include the basic primitive and struct types here.
  56
  57#ifndef _ENGINEPRIMITIVES_H_
  58   #include "console/enginePrimitives.h"
  59#endif
  60#ifndef _ENGINESTRUCTS_H_
  61   #include "console/engineStructs.h"
  62#endif
  63
  64// Needed for the executef macros. Blame GCC.
  65#ifndef _SIMEVENTS_H_
  66#include "console/simEvents.h"
  67#endif
  68
  69
  70/// @file
  71/// Definitions for exposing engine functionality to the control layer.
  72///
  73/// This file provides a convenience layer around the underlying engine interop system (which at
  74/// the moment still includes the legacy TorqueScript interop a.k.a. "console system").  The
  75/// macros exposed here will automatically take care of all marshalling, value type constraints,
  76/// reflection info instancing, etc. involved in defining engine API call-ins and call-outs.
  77///
  78/// @note At the moment, this file supplies both the legacy TorqueScript console system as well
  79///   as the new engine export system with the structures and information they need.  In the
  80///   near future, the console-based parts will get purged.  This will not result in visible
  81///   changes to users of the functionality here except for the string-based marshalling
  82///   functions currently exposed (which will also disappear).
  83
  84
  85
  86//TODO: Disable warning for extern "C" functions returning UDTs for now; need to take a closer look at this
  87#pragma warning( disable : 4190 )
  88
  89
  90
  91// Disable some VC warnings that are irrelevant to us.
  92#pragma warning( push )
  93#pragma warning( disable : 4510 ) // default constructor could not be generated; all the Args structures are never constructed by us
  94#pragma warning( disable : 4610 ) // can never be instantiated; again Args is never constructed by us
  95
  96
  97namespace engineAPI {
  98
  99   /// Flag for enabling legacy console behavior in the interop system while
 100   /// we still have it around.  Will disappear along with console.
 101   extern bool gUseConsoleInterop;
 102   
 103   /// Flag to allow engine functions to detect whether the engine had been
 104   /// initialized or shut down.
 105   extern bool gIsInitialized;
 106}
 107
 108/// @name Marshalling
 109///
 110/// Functions for converting to/from string-based data representations.
 111///
 112/// @note This functionality is specific to the console interop.
 113/// @{
 114
 115/// Marshal a single piece of data from native into client form.
 116template< typename T >
 117inline const char* EngineMarshallData( const T& value )
 118{
 119   return castConsoleTypeToString( value );
 120}
 121inline const char* EngineMarshallData( bool value )
 122{
 123   if( value )
 124      return "1";
 125   else
 126      return "0";
 127}
 128inline const char* EngineMarshallData( const char* str )
 129{
 130   // The API assumes that if you pass a plain "const char*" through it, then you are referring
 131   // to string storage with non-local lifetime that can be safely passed to the control layer.
 132   return str;
 133}
 134template< typename T >
 135inline const char* EngineMarshallData( T* object )
 136{
 137   return ( object ? object->getIdString() : "0" );
 138}
 139template< typename T >
 140inline const char* EngineMarshallData( const T* object )
 141{
 142   return ( object ? object->getIdString() : "0" );
 143}
 144inline const char* EngineMarshallData( U32 value )
 145{
 146   return EngineMarshallData( S32( value ) );
 147}
 148
 149/// Marshal data from native into client form stored directly in
 150/// client function invocation vector.
 151template< typename T >
 152inline void EngineMarshallData( const T& arg, S32& argc, ConsoleValueRef *argv )
 153{
 154   argv[ argc ] = castConsoleTypeToString( arg );
 155   argc ++;
 156}
 157inline void EngineMarshallData( bool arg, S32& argc, ConsoleValueRef *argv )
 158{
 159   if( arg )
 160      argv[ argc ] = 1;
 161   else
 162      argv[ argc ] = 0;
 163   argc ++;
 164}
 165inline void EngineMarshallData( S32 arg, S32& argc, ConsoleValueRef *argv )
 166{
 167   argv[ argc ] = arg;
 168   argc ++;
 169}
 170inline void EngineMarshallData( U32 arg, S32& argc, ConsoleValueRef *argv )
 171{
 172   EngineMarshallData( S32( arg ), argc, argv );
 173}
 174inline void EngineMarshallData( F32 arg, S32& argc, ConsoleValueRef *argv )
 175{
 176   argv[ argc ] = arg;
 177   argc ++;
 178}
 179inline void EngineMarshallData( const char* arg, S32& argc, ConsoleValueRef *argv )
 180{
 181   argv[ argc ] = arg;
 182   argc ++;
 183}
 184inline void EngineMarshallData( char* arg, S32& argc, ConsoleValueRef *argv )
 185{
 186   argv[ argc ] = arg;
 187   argc ++;
 188}
 189
 190template< typename T >
 191inline void EngineMarshallData( T* object, S32& argc, ConsoleValueRef *argv )
 192{
 193   argv[ argc ] = object ? object->getId() : 0;
 194   argc ++;
 195}
 196template< typename T >
 197inline void EngineMarshallData( const T* object, S32& argc, ConsoleValueRef *argv )
 198{
 199   argv[ argc ] = object ? object->getId() : 0;
 200   argc ++;
 201}
 202
 203/// Unmarshal data from client form to engine form.
 204///
 205/// This is wrapped in an a struct as partial specializations on function
 206/// templates are not allowed in C++.
 207template< typename T >
 208struct EngineUnmarshallData
 209{
 210   T operator()( const char* str ) const
 211   {
 212      T value;
 213      castConsoleTypeFromString( value, str );
 214      return value;
 215   }
 216};
 217template<>
 218struct EngineUnmarshallData< S32 >
 219{
 220   S32 operator()( ConsoleValueRef &ref ) const
 221   {
 222      return (S32)ref;
 223   }
 224
 225   S32 operator()( const char* str ) const
 226   {
 227      return dAtoi( str );
 228   }
 229};
 230template<>
 231struct EngineUnmarshallData< U32 >
 232{
 233   U32 operator()( ConsoleValueRef &ref ) const
 234   {
 235      return (U32)((S32)ref);
 236   }
 237
 238   U32 operator()( const char* str ) const
 239   {
 240      return dAtoui( str );
 241   }
 242};
 243template<>
 244struct EngineUnmarshallData< F32 >
 245{
 246   F32 operator()( ConsoleValueRef &ref ) const
 247   {
 248      return (F32)ref;
 249   }
 250
 251   F32 operator()( const char* str ) const
 252   {
 253      return dAtof( str );
 254   }
 255};
 256template<>
 257struct EngineUnmarshallData< U8 >
 258{
 259   U8 operator()( ConsoleValueRef &ref ) const
 260   {
 261      return (U8)((S32)ref);
 262   }
 263
 264   U8 operator()( const char* str ) const
 265   {
 266      return dAtoui( str );
 267   }
 268};
 269template<>
 270struct EngineUnmarshallData< const char* >
 271{
 272   const char* operator()( ConsoleValueRef &ref ) const
 273   {
 274      return ref.getStringValue();
 275   }
 276
 277   const char* operator()( const char* str ) const
 278   {
 279      return str;
 280   }
 281};
 282template< typename T >
 283struct EngineUnmarshallData< T* >
 284{
 285   T* operator()( ConsoleValueRef &ref ) const
 286   {
 287      return dynamic_cast< T* >( Sim::findObject( ref.getStringValue() ) );
 288   }
 289
 290   T* operator()( const char* str ) const
 291   {
 292      return dynamic_cast< T* >( Sim::findObject( str ) );
 293   }
 294};
 295template<>
 296struct EngineUnmarshallData< void >
 297{
 298   void operator()( ConsoleValueRef& ) const {}
 299   void operator()( const char* ) const {}
 300};
 301
 302
 303template<>
 304struct EngineUnmarshallData< ConsoleValueRef >
 305{
 306   ConsoleValueRef operator()( ConsoleValueRef ref ) const
 307   {
 308      return ref;
 309   }
 310};
 311
 312/// @}
 313
 314
 315/// @name C to C++ Trampolines
 316///
 317/// The trampolines serve two purposes:
 318///
 319/// For one, they ensure that no matter what argument types are specified by users of the engine API macros, the correct
 320/// argument value types are enforced on the functions exported by the engine.  Let's say, for example, the user writes
 321/// a function that takes a "Point3F direction" argument, then the template machinery here will automatically expose an
 322/// API function that takes a "Point3F& direction" argument.
 323///
 324/// Secondly, the templates jump the incoming calls from extern "C" space into C++ space.  This is mostly relevant for
 325/// methods only as they will need an implicit object type argument.
 326///
 327/// @{
 328
 329// Helper type to factor out commonalities between function and method trampolines.
 330
 331
 332template<typename T> struct _EngineTrampoline {
 333   struct Args {};
 334};
 335
 336template< typename R, typename ...ArgTs >
 337struct _EngineTrampoline< R( ArgTs ... ) >
 338{
 339   template<typename T> using AVT = typename EngineTypeTraits<T>::ArgumentValueType;
 340   typedef fixed_tuple<AVT<ArgTs> ...> Args;
 341   Args argT;
 342};
 343
 344template< typename T >
 345struct _EngineFunctionTrampolineBase : public _EngineTrampoline< T >
 346{
 347   typedef T FunctionType;
 348};
 349
 350// Trampolines for any call-ins that aren't methods.
 351template< typename T >
 352struct _EngineFunctionTrampoline {};
 353
 354template< typename R, typename ...ArgTs >
 355struct _EngineFunctionTrampoline< R(ArgTs...) > : public _EngineFunctionTrampolineBase< R(ArgTs...) >
 356{
 357private:
 358   using Super = _EngineFunctionTrampolineBase< R(ArgTs...) >;
 359   using SelfType = _EngineFunctionTrampoline< R(ArgTs...) >;
 360   using ArgsType = typename _EngineFunctionTrampolineBase< R(ArgTs ...) >::Args;
 361   
 362   template<size_t ...> struct Seq {};
 363   template<size_t N, size_t ...S> struct Gens : Gens<N-1, N-1, S...> {};
 364   template<size_t ...I> struct Gens<0, I...>{ typedef Seq<I...> type; };
 365
 366   template<size_t I>
 367   static typename fixed_tuple_element<I, fixed_tuple<ArgTs...>>::type getAndToType(const ArgsType& args) {
 368      return EngineTypeTraits<typename fixed_tuple_element<I, fixed_tuple<ArgTs...>>::type>::ArgumentToValue(fixed_tuple_accessor<I>::get(args));
 369   }
 370
 371   template<size_t ...I>
 372   static R dispatchHelper(typename Super::FunctionType fn, const ArgsType& args, Seq<I...>)  {
 373      return R( fn(SelfType::template getAndToType<I>(args) ...) );
 374   }
 375
 376   using SeqType = typename Gens<sizeof...(ArgTs)>::type;
 377public:
 378   static R jmp(typename Super::FunctionType fn, const ArgsType& args )
 379   {
 380      return dispatchHelper(fn, args, SeqType());
 381   }
 382};
 383
 384// Trampolines for engine methods
 385
 386template< typename T >
 387struct _EngineMethodTrampolineBase : public _EngineTrampoline< T > {};
 388
 389template< typename Frame, typename T >
 390struct _EngineMethodTrampoline {};
 391
 392template< typename Frame, typename R, typename ...ArgTs >
 393struct _EngineMethodTrampoline< Frame, R(ArgTs ...) > : public _EngineMethodTrampolineBase< R(ArgTs ...) >
 394{
 395   using FunctionType = R( typename Frame::ObjectType*, ArgTs ...);
 396private:
 397   using Super = _EngineMethodTrampolineBase< R(ArgTs ...) >;
 398   using SelfType = _EngineMethodTrampoline< Frame, R(ArgTs ...) >;
 399   using ArgsType = typename _EngineMethodTrampolineBase< R(ArgTs ...) >::Args;
 400   
 401   template<size_t ...> struct Seq {};
 402   template<size_t N, size_t ...S> struct Gens : Gens<N-1, N-1, S...> {};
 403   template<size_t ...I> struct Gens<0, I...>{ typedef Seq<I...> type; };
 404
 405   template<size_t I>
 406   static typename fixed_tuple_element<I, fixed_tuple<ArgTs...>>::type getAndToType(const ArgsType& args) {
 407      return EngineTypeTraits<typename fixed_tuple_element<I, fixed_tuple<ArgTs...>>::type>::ArgumentToValue(fixed_tuple_accessor<I>::get(args));
 408   }
 409
 410   template<size_t ...I>
 411   static R dispatchHelper(Frame f, const ArgsType& args, Seq<I...>) {
 412      return R(f._exec(SelfType::template getAndToType<I>(args) ...));
 413   }
 414   
 415   using SeqType = typename Gens<sizeof...(ArgTs)>::type;
 416public:
 417   static R jmp( typename Frame::ObjectType* object, const ArgsType& args )
 418   {
 419      
 420      Frame f;
 421      f.object = object;
 422      return dispatchHelper(f, args, SeqType());
 423   }
 424};
 425
 426/// @}
 427
 428
 429/// @name Thunking
 430///
 431/// Internal functionality for thunks placed between TorqueScript calls of engine functions and their native
 432/// implementations.
 433///
 434/// @note The functionality in this group is specific to the console interop system.
 435/// @{
 436
 437
 438// Helper function to return data from a thunk.
 439template< typename T >
 440inline const char* _EngineConsoleThunkReturnValue( const T& value )
 441{
 442   return EngineMarshallData( value );
 443}
 444
 445inline bool _EngineConsoleThunkReturnValue( bool value )
 446{
 447   return value;
 448}
 449inline S32 _EngineConsoleThunkReturnValue( S32 value )
 450{
 451   return value;
 452}
 453inline F32 _EngineConsoleThunkReturnValue( F32 value )
 454{
 455   return value;
 456}
 457inline const char* _EngineConsoleThunkReturnValue( const String& str )
 458{
 459   return Con::getReturnBuffer( str );
 460}
 461inline const char* _EngineConsoleThunkReturnValue( const char* value )
 462{
 463   return EngineMarshallData( value );
 464}
 465template< typename T >
 466inline const char* _EngineConsoleThunkReturnValue( T* value )
 467{
 468   return ( value ? value->getIdString() : "" );
 469}
 470template< typename T >
 471inline const char* _EngineConsoleThunkReturnValue( const T* value )
 472{
 473   return ( value ? value->getIdString() : "" );
 474}
 475
 476
 477
 478// Helper class to determine the type of callback registered with the console system.
 479template< typename R >
 480struct _EngineConsoleThunkType
 481{
 482   typedef const char* ReturnType;
 483   typedef StringCallback CallbackType;
 484};
 485template<>
 486struct _EngineConsoleThunkType< S32 >
 487{
 488   typedef S32 ReturnType;
 489   typedef IntCallback CallbackType;
 490};
 491template<>
 492struct _EngineConsoleThunkType< U32 >
 493{
 494   typedef U32 ReturnType;
 495   typedef IntCallback CallbackType;
 496};
 497template<>
 498struct _EngineConsoleThunkType< F32 >
 499{
 500   typedef F32 ReturnType;
 501   typedef FloatCallback CallbackType;
 502};
 503template<>
 504struct _EngineConsoleThunkType< bool >
 505{
 506   typedef bool ReturnType;
 507   typedef BoolCallback CallbackType;
 508};
 509template<>
 510struct _EngineConsoleThunkType< void >
 511{
 512   typedef void ReturnType;
 513   typedef VoidCallback CallbackType;
 514};
 515
 516
 517// Helper struct to count the number of parameters in a function list.
 518// The setup through operator () allows omitting the the argument list entirely.
 519struct _EngineConsoleThunkCountArgs
 520{
 521
 522   template<typename ...ArgTs> U32 operator()(ArgTs... args){
 523      return sizeof...(ArgTs);
 524   }
 525   
 526   operator U32() const{ // FIXME: WHAT IS THIS?? I'm pretty sure it's incorrect, and it's the version that is invoked by all the macros
 527      return 0;
 528   }
 529};
 530
 531
 532
 533
 534// Encapsulation of a legacy console function invocation.
 535namespace engineAPI{
 536   namespace detail{
 537      template<S32 startArgc, typename R, typename ...ArgTs>
 538      struct ThunkHelpers {
 539         using SelfType = ThunkHelpers<startArgc, R, ArgTs...>;
 540         using FunctionType = R(*)(ArgTs...);
 541         template<typename Frame> using MethodType = R(Frame::*)(ArgTs ...) const;
 542         template<size_t I> using IthArgType = typename std::tuple_element<I, std::tuple<ArgTs ...> >::type;
 543         
 544         template<size_t ...> struct Seq {};
 545         template<size_t N, size_t ...S> struct Gens : Gens<N-1, N-1, S...> {};
 546         template<size_t ...I> struct Gens<0, I...>{ typedef Seq<I...> type; };
 547         
 548         typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType;
 549         static const S32 NUM_ARGS = sizeof...(ArgTs) + startArgc;
 550         
 551         template<size_t index, size_t method_offset = 0, typename ...RealArgTs>
 552         static IthArgType<index> getRealArgValue(S32 argc, ConsoleValueRef *argv, const _EngineFunctionDefaultArguments< void(RealArgTs...) >& defaultArgs)
 553         {
 554            if((startArgc + index) < argc)
 555            {
 556               return EngineUnmarshallData< IthArgType<index> >()( argv[ startArgc + index ] );
 557            } else {
 558               return fixed_tuple_accessor<index + method_offset>::get(defaultArgs.mArgs);
 559            }
 560         }
 561         
 562         template<size_t ...I>
 563         static R dispatchHelper(S32 argc, ConsoleValueRef *argv, FunctionType fn, const _EngineFunctionDefaultArguments< void(ArgTs...) >& defaultArgs, Seq<I...>){
 564            return fn(SelfType::getRealArgValue<I>(argc, argv, defaultArgs) ...);
 565         }
 566         
 567         template<typename Frame, size_t ...I>
 568         static R dispatchHelper(S32 argc, ConsoleValueRef *argv, MethodType<Frame> fn, Frame* frame, const _EngineFunctionDefaultArguments< void( typename Frame::ObjectType*, ArgTs...) >& defaultArgs, Seq<I...>){
 569            return (frame->*fn)(SelfType::getRealArgValue<I,1>(argc, argv, defaultArgs) ...);
 570         }
 571         
 572         using SeqType = typename Gens<sizeof...(ArgTs)>::type;
 573      };
 574      
 575      template<typename ArgVT> struct MarshallHelpers {
 576         template<typename ...ArgTs> static void marshallEach(S32 &argc, ArgVT *argv, const ArgTs& ...args){}
 577         template<typename H, typename ...Tail> static void marshallEach(S32 &argc, ArgVT *argv, const H& head, const Tail& ...tail){
 578            argv[argc++] = EngineMarshallData(head);
 579            marshallEach(argc, argv, tail...);
 580         }
 581      };
 582      
 583      template<> struct MarshallHelpers<ConsoleValueRef> {
 584         template<typename ...ArgTs> static void marshallEach(S32 &argc, ConsoleValueRef *argv, const ArgTs& ...args){}
 585         template<typename H, typename ...Tail> static void marshallEach(S32 &argc, ConsoleValueRef *argv, const H& head, const Tail& ...tail){
 586            EngineMarshallData(head, argc, argv);
 587            marshallEach(argc, argv, tail...);
 588         }
 589      };
 590   }
 591}
 592
 593template< S32 startArgc, typename T >
 594struct _EngineConsoleThunk {};
 595
 596template< S32 startArgc, typename R, typename ...ArgTs >
 597struct _EngineConsoleThunk< startArgc, R(ArgTs...) >
 598{
 599private:
 600   using Helper = engineAPI::detail::ThunkHelpers<startArgc, R, ArgTs...>;
 601   using SeqType = typename Helper::SeqType;
 602public:
 603   typedef typename Helper::FunctionType FunctionType;
 604   typedef typename Helper::ReturnType ReturnType;
 605   template<typename Frame> using MethodType = typename Helper::template MethodType<Frame>;
 606   static const S32 NUM_ARGS = Helper::NUM_ARGS;
 607   
 608   static ReturnType thunk( S32 argc, ConsoleValueRef *argv, FunctionType fn, const _EngineFunctionDefaultArguments< void(ArgTs...) >& defaultArgs)
 609   {
 610      return _EngineConsoleThunkReturnValue( Helper::dispatchHelper(argc, argv, fn, defaultArgs, SeqType()));
 611   }
 612   template< typename Frame >
 613   static ReturnType thunk( S32 argc, ConsoleValueRef *argv, MethodType<Frame> fn, Frame* frame, const _EngineFunctionDefaultArguments< void( typename Frame::ObjectType*, ArgTs...) >& defaultArgs)
 614   {
 615      return _EngineConsoleThunkReturnValue( Helper::dispatchHelper(argc, argv, fn, frame, defaultArgs, SeqType()));
 616   }
 617};
 618
 619// Have to do a partial specialization for void-returning functions :(
 620template<S32 startArgc, typename ...ArgTs>
 621struct _EngineConsoleThunk<startArgc, void(ArgTs...)> {
 622private:
 623   using Helper = engineAPI::detail::ThunkHelpers<startArgc, void, ArgTs...>;
 624   using SeqType = typename Helper::SeqType;
 625public:
 626   typedef typename Helper::FunctionType FunctionType;
 627   typedef typename Helper::ReturnType ReturnType;
 628   template<typename Frame> using MethodType = typename Helper::template MethodType<Frame>;
 629   static const S32 NUM_ARGS = Helper::NUM_ARGS;
 630   
 631   static void thunk( S32 argc, ConsoleValueRef *argv, FunctionType fn, const _EngineFunctionDefaultArguments< void(ArgTs...) >& defaultArgs)
 632   {
 633      Helper::dispatchHelper(argc, argv, fn, defaultArgs, SeqType());
 634   }
 635   template< typename Frame >
 636   static void thunk( S32 argc, ConsoleValueRef *argv, MethodType<Frame> fn, Frame* frame, const _EngineFunctionDefaultArguments< void( typename Frame::ObjectType*, ArgTs...) >& defaultArgs)
 637   {
 638      Helper::dispatchHelper(argc, argv, fn, frame, defaultArgs, SeqType());
 639   }
 640};
 641
 642
 643/// @}
 644
 645/// @name API Definition Macros
 646///
 647/// The macros in this group allow to create engine API functions that work both with the
 648/// legacy console system as well as with the new engine export system.  As such, they only
 649/// support those function features that are available in both systems.  This means that for
 650/// console-style variadic functions, the ConsoleXXX must be used and that for overloaded
 651/// and/or C-style variadic functions as well as for placing functions in export scopes,
 652/// DEFINE_CALLIN must be used directly.
 653///
 654/// When the console system is removed, the console thunking functionality will be removed
 655/// from these macros but otherwise they will remain unchanged and in place.
 656///
 657/// @{
 658
 659
 660// Helpers to implement initialization checks.  Pulled out into separate macros so this can be deactivated easily.
 661// Especially important for the initialize() function itself.
 662
 663#define _CHECK_ENGINE_INITIALIZED_IMPL( fnName, returnType )                                                                     \
 664      if( !engineAPI::gIsInitialized )                                                                                           \
 665      {                                                                                                                          \
 666         Con::errorf( "EngineAPI: Engine not initialized when calling " #fnName );                                               \
 667         return EngineTypeTraits< returnType >::ReturnValue( EngineTypeTraits< returnType >::ReturnValueType() );                \
 668      }
 669
 670#define _CHECK_ENGINE_INITIALIZED( fnName, returnType ) _CHECK_ENGINE_INITIALIZED_IMPL( fnName, returnType )
 671
 672
 673/// Define a call-in point for calling into the engine.
 674///
 675/// @param name The name of the function as it should be seen by the control layer.
 676/// @param returnType The value type returned to the control layer.
 677/// @param args The argument list as it would appear on the function definition
 678/// @param defaultArgs The list of default argument values.
 679/// @param usage The usage doc string for the engine API reference.
 680///
 681/// @code
 682/// DefineEngineFunction( myFunction, int, ( float f, const String& s ), ( "value for s" ), "This is my function." )
 683/// {
 684///    return int( f ) + dAtoi( s );
 685/// }
 686/// @endcode
 687#define DefineEngineFunction( name, returnType, args, defaultArgs, usage )                                                       \
 688   static inline returnType _fn ## name ## impl args;                                                                            \
 689   TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## name                                                         \
 690      ( _EngineFunctionTrampoline< returnType args >::Args a )                                                              \
 691   {                                                                                                                             \
 692      _CHECK_ENGINE_INITIALIZED( name, returnType );                                                                             \
 693      return EngineTypeTraits< returnType >::ReturnValue(                                                                        \
 694         _EngineFunctionTrampoline< returnType args >::jmp( _fn ## name ## impl, a )                                             \
 695      );                                                                                                                         \
 696   }                                                                                                                             \
 697   static _EngineFunctionDefaultArguments< void args > _fn ## name ## DefaultArgs defaultArgs;                                   \
 698   static EngineFunctionInfo _fn ## name ## FunctionInfo(                                                                        \
 699      #name,                                                                                                                     \
 700      &_SCOPE<>()(),                                                                                                             \
 701      usage,                                                                                                                     \
 702      #returnType " " #name #args,                                                                                               \
 703      "fn" #name,                                                                                                                \
 704      TYPE< returnType args >(),                                                                                                 \
 705      &_fn ## name ## DefaultArgs,                                                                                               \
 706      ( void* ) &fn ## name,                                                                                                     \
 707      0                                                                                                                          \
 708   );                                                                                                                            \
 709   static _EngineConsoleThunkType< returnType >::ReturnType _ ## name ## caster( SimObject*, S32 argc, ConsoleValueRef *argv )   \
 710   {                                                                                                                             \
 711      return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 1, returnType args >::thunk(                \
 712         argc, argv, &_fn ## name ## impl, _fn ## name ## DefaultArgs                                                            \
 713      ) );                                                                                                                       \
 714   }                                                                                                                             \
 715   static ConsoleFunctionHeader _ ## name ## header                                                                              \
 716      ( #returnType, #args, #defaultArgs );                                                                                      \
 717   static ConsoleConstructor                                                                                                     \
 718      _ ## name ## obj( NULL, #name, _EngineConsoleThunkType< returnType >::CallbackType( _ ## name ## caster ), usage,          \
 719         _EngineConsoleThunk< 1, returnType args >::NUM_ARGS - _EngineConsoleThunkCountArgs() defaultArgs,                       \
 720         _EngineConsoleThunk< 1, returnType args >::NUM_ARGS,                                                                    \
 721         false, &_ ## name ## header                                                                                             \
 722      );                                                                                                                         \
 723   static inline returnType _fn ## name ## impl args
 724   
 725   
 726// The next thing is a bit tricky.  DefineEngineMethod allows to make the 'object' (=this) argument to the function
 727// implicit which presents quite an obstacle for the macro internals as the engine export system requires the
 728// name of a DLL symbol that represents an extern "C" function with an explicit first object pointer argument.
 729//
 730// Even if we ignored the fact that we don't have a guarantee how the various C++ compilers implement implicit 'this' arguments,
 731// we could still not just use a C++ method for this as then we would have to get past the C++ compiler's mangling to
 732// get to the function symbol name (let alone the fact that typing this method correctly would be tricky).
 733//
 734// So, the trick employed here is to package all but the implicit 'this' argument in a structure and then define an
 735// extern "C" function that takes the object pointer as a first argument and the struct type as the second argument.
 736// This will result in a function with an identical stack call frame layout to the function we want.
 737//
 738// Unfortunately, that still requires that function to chain on to the real user-defined function.  To do this
 739// cleanly and portably, _EngineMethodTrampoline is used to unpack and jump the call from extern "C" into C++ space.
 740// In optimized builds, the compiler should be smart enough to pretty much optimize all our trickery here away.
 741
 742#define _DefineMethodTrampoline( className, name, returnType, args ) \
 743   TORQUE_API EngineTypeTraits< returnType >::ReturnValueType \
 744      fn ## className ## _ ## name ( className* object, _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::Args a )\
 745   {                                                                                                                                            \
 746      _CHECK_ENGINE_INITIALIZED( className::name, returnType );                                                                                 \
 747      return EngineTypeTraits< returnType >::ReturnValue(                                                                                       \
 748         _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::jmp( object, a )                                          \
 749      );                                                                                                                                        \
 750   }
 751
 752
 753/// Define a call-in point for calling a method on an engine object.
 754///
 755/// @param name The name of the C++ class.
 756/// @param name The name of the method as it should be seen by the control layer.
 757/// @param returnType The value type returned to the control layer.
 758/// @param args The argument list as it would appear on the function definition
 759/// @param defaultArgs The list of default argument values.
 760/// @param usage The usage doc string for the engine API reference.
 761///
 762/// @code
 763/// DefineEngineMethod( MyClass, myMethod, int, ( float f, const String& s ), ( "value for s" ), "This is my method." )
 764/// {
 765///    return object->someMethod( f, s );
 766/// }
 767/// @endcode
 768#define DefineEngineMethod( className, name, returnType, args, defaultArgs, usage )                                                             \
 769   struct _ ## className ## name ## frame                                                                                                       \
 770   {                                                                                                                                            \
 771      typedef className ObjectType;                                                                                                             \
 772      className* object;                                                                                                                        \
 773      inline returnType _exec args const;                                                                                                       \
 774   };                                                                                                                                           \
 775   _DefineMethodTrampoline( className, name, returnType, args );                                                                                \
 776   static _EngineFunctionDefaultArguments< _EngineMethodTrampoline< _ ## className ## name ## frame, void args >::FunctionType >                \
 777      _fn ## className ## name ## DefaultArgs defaultArgs;                                                                                      \
 778   static EngineFunctionInfo _fn ## className ## name ## FunctionInfo(                                                                          \
 779      #name,                                                                                                                                    \
 780      &_SCOPE< className >()(),                                                                                                                 \
 781      usage,                                                                                                                                    \
 782      "virtual " #returnType " " #name #args,                                                                                                   \
 783      "fn" #className "_" #name,                                                                                                                \
 784      TYPE< _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::FunctionType >(),                                      \
 785      &_fn ## className ## name ## DefaultArgs,                                                                                                 \
 786      ( void* ) &fn ## className ## _ ## name,                                                                                                  \
 787      0                                                                                                                                         \
 788   );                                                                                                                                           \
 789   static _EngineConsoleThunkType< returnType >::ReturnType _ ## className ## name ## caster( SimObject* object, S32 argc, ConsoleValueRef *argv )  \
 790   {                                                                                                                                            \
 791      _ ## className ## name ## frame frame;                                                                                                    \
 792      frame.object = static_cast< className* >( object );                                                                                       \
 793      return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 2, returnType args >::thunk(                               \
 794         argc, argv, &_ ## className ## name ## frame::_exec, &frame, _fn ## className ## name ## DefaultArgs                                   \
 795      ) );                                                                                                                                      \
 796   }                                                                                                                                            \
 797   static ConsoleFunctionHeader _ ## className ## name ## header                                                                                \
 798      ( #returnType, #args, #defaultArgs );                                                                                                     \
 799   static ConsoleConstructor                                                                                                                    \
 800      className ## name ## obj( #className, #name,                                                                                              \
 801         _EngineConsoleThunkType< returnType >::CallbackType( _ ## className ## name ## caster ), usage,                                        \
 802         _EngineConsoleThunk< 2, returnType args >::NUM_ARGS - _EngineConsoleThunkCountArgs() defaultArgs,                                      \
 803         _EngineConsoleThunk< 2, returnType args >::NUM_ARGS,                                                                                   \
 804         false, &_ ## className ## name ## header                                                                                               \
 805      );                                                                                                                                        \
 806   returnType _ ## className ## name ## frame::_exec args const
 807   
 808   
 809/// Define a call-in point for calling into the engine.  Unlike with DefineEngineFunction, the statically
 810/// callable function will be confined to the namespace of the given class.
 811///
 812/// @param classname The name of the C++ class (or a registered export scope).
 813/// @param name The name of the method as it should be seen by the control layer.
 814/// @param returnType The value type returned to the control layer.
 815/// @param args The argument list as it would appear on the function definition
 816/// @param defaultArgs The list of default argument values.
 817/// @param usage The usage doc string for the engine API reference.
 818///
 819/// @code
 820/// DefineEngineStaticMethod( MyClass, myMethod, int, ( float f, string s ), ( "value for s" ), "This is my method." )
 821/// {
 822/// }
 823/// @endcode
 824#define DefineEngineStaticMethod( className, name, returnType, args, defaultArgs, usage )                                              \
 825   static inline returnType _fn ## className ## name ## impl args;                                                                     \
 826   TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## className ## _ ## name                                             \
 827      ( _EngineFunctionTrampoline< returnType args >::Args a )                                                                    \
 828   {                                                                                                                                   \
 829      _CHECK_ENGINE_INITIALIZED( className::name, returnType );                                                                        \
 830      return EngineTypeTraits< returnType >::ReturnValue(                                                                              \
 831         _EngineFunctionTrampoline< returnType args >::jmp( _fn ## className ## name ## impl, a )                                      \
 832      );                                                                                                                               \
 833   }                                                                                                                                   \
 834   static _EngineFunctionDefaultArguments< void args > _fn ## className ## name ## DefaultArgs defaultArgs;                            \
 835   static EngineFunctionInfo _fn ## name ## FunctionInfo(                                                                              \
 836      #name,                                                                                                                           \
 837      &_SCOPE< className >()(),                                                                                                        \
 838      usage,                                                                                                                           \
 839      #returnType " " #name #args,                                                                                                     \
 840      "fn" #className "_" #name,                                                                                                       \
 841      TYPE< returnType args >(),                                                                                                       \
 842      &_fn ## className ## name ## DefaultArgs,                                                                                        \
 843      ( void* ) &fn ## className ## _ ## name,                                                                                         \
 844      0                                                                                                                                \
 845   );                                                                                                                                  \
 846   static _EngineConsoleThunkType< returnType >::ReturnType _ ## className ## name ## caster( SimObject*, S32 argc, ConsoleValueRef *argv )\
 847   {                                                                                                                                   \
 848      return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 1, returnType args >::thunk(                      \
 849         argc, argv, &_fn ## className ## name ## impl, _fn ## className ## name ## DefaultArgs                                        \
 850      ) );                                                                                                                             \
 851   }                                                                                                                                   \
 852   static ConsoleFunctionHeader _ ## className ## name ## header                                                                       \
 853      ( #returnType, #args, #defaultArgs, true );                                                                                      \
 854   static ConsoleConstructor                                                                                                           \
 855      _ ## className ## name ## obj( #className, #name, _EngineConsoleThunkType< returnType >::CallbackType( _ ## className ## name ## caster ), usage, \
 856         _EngineConsoleThunk< 1, returnType args >::NUM_ARGS - _EngineConsoleThunkCountArgs() defaultArgs,                             \
 857         _EngineConsoleThunk< 1, returnType args >::NUM_ARGS,                                                                          \
 858         false, &_ ## className ## name ## header                                                                                      \
 859      );                                                                                                                               \
 860   static inline returnType _fn ## className ## name ## impl args
 861
 862#  define DefineEngineStringlyVariadicFunction(name,returnType,minArgs,maxArgs,usage)                                            \
 863   static inline returnType _fn ## name ## impl (SimObject *, S32 argc, ConsoleValueRef *argv);                                  \
 864   TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## name                                                         \
 865      (Vector<const char*>* vec)                                                                                                 \
 866   {                                                                                                                             \
 867      _CHECK_ENGINE_INITIALIZED( name, returnType );                                                                             \
 868      StringStackConsoleWrapper args(vec->size(), vec->address());                                                               \
 869      return EngineTypeTraits< returnType >::ReturnValue(                                                                        \
 870         _fn ## name ## impl(NULL, args.count(), args)                                                                           \
 871      );                                                                                                                         \
 872   }                                                                                                                             \
 873   static _EngineFunctionDefaultArguments< void (Vector<const char*>* vec) > _fn ## name ## DefaultArgs;                         \
 874   static EngineFunctionInfo _fn ## name ## FunctionInfo(                                                                        \
 875      #name,                                                                                                                     \
 876      &_SCOPE<>()(),                                                                                                             \
 877      usage,                                                                                                                     \
 878      #returnType " " #name "(Vector<String> args)",                                                                             \
 879      "fn" #name,                                                                                                                \
 880      TYPE< returnType (Vector<const char*>* vec) >(),                                                                           \
 881      &_fn ## name ## DefaultArgs,                                                                                               \
 882      ( void* ) &fn ## name,                                                                                                     \
 883      0                                                                                                                          \
 884   );                                                                                                                            \
 885   ConsoleConstructor cc_##name##_obj(NULL,#name,_fn ## name ## impl,usage,minArgs,maxArgs); \
 886      returnType _fn ## name ## impl(SimObject *, S32 argc, ConsoleValueRef *argv)
 887
 888#  define DefineEngineStringlyVariadicMethod(className, name,returnType,minArgs,maxArgs,usage)                                   \
 889   struct _ ## className ## name ## frame                                                                                        \
 890   {                                                                                                                             \
 891      typedef className ObjectType;                                                                                              \
 892      className* object;                                                                                                         \
 893      inline returnType _exec (S32 argc, ConsoleValueRef* argv) const;                                                           \
 894   };                                                                                                                            \
 895   TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## className ## _ ## name                                       \
 896      (className* object, Vector<const char*>* vec)                                                                              \
 897   {                                                                                                                             \
 898      _CHECK_ENGINE_INITIALIZED( name, returnType );                                                                             \
 899      StringStackConsoleWrapper args(vec->size(), vec->address());                                                               \
 900      _ ## className ## name ## frame frame {};                                                                                  \
 901      frame.object = static_cast< className* >( object );                                                                        \
 902      return EngineTypeTraits< returnType >::ReturnValue(                                                                        \
 903         frame._exec(args.count(), args)                                                                                         \
 904      );                                                                                                                         \
 905   }                                                                                                                             \
 906   static _EngineFunctionDefaultArguments< void (className* object, S32 argc, const char** argv) >                               \
 907      _fn ## className ## name ## DefaultArgs;                                                                                   \
 908   static EngineFunctionInfo _fn ## className ## name ## FunctionInfo(                                                           \
 909      #name,                                                                                                                     \
 910      &_SCOPE< className >()(),                                                                                                  \
 911      usage,                                                                                                                     \
 912      "virtual " #returnType " " #name "(Vector<String> args)",                                                                  \
 913      "fn" #className "_" #name,                                                                                                 \
 914      TYPE< _EngineMethodTrampoline< _ ## className ## name ## frame, returnType (Vector<const char*> vec) >::FunctionType >(),  \
 915      &_fn ## className ## name ## DefaultArgs,                                                                                  \
 916      ( void* ) &fn ## className ## _ ## name,                                                                                   \
 917      0                                                                                                                          \
 918   );                                                                                                                            \
 919   returnType cm_##className##_##name##_caster(SimObject* object, S32 argc, ConsoleValueRef* argv) {                             \
 920      AssertFatal( dynamic_cast<className*>( object ), "Object passed to " #name " is not a " #className "!" );                  \
 921      _ ## className ## name ## frame frame {};                                                                                  \
 922      frame.object = static_cast< className* >( object );                                                                        \
 923      conmethod_return_##returnType ) frame._exec(argc,argv);                                                                    \
 924   };                                                                                                                            \
 925   ConsoleConstructor cc_##className##_##name##_obj(#className,#name,cm_##className##_##name##_caster,usage,minArgs,maxArgs);    \
 926   inline returnType _ ## className ## name ## frame::_exec(S32 argc, ConsoleValueRef *argv) const
 927
 928
 929
 930// The following three macros are only temporary.  They allow to define engineAPI functions using the framework
 931// here in this file while being visible only in the new API.  When the console interop is removed, these macros
 932// can be removed and all their uses be replaced with their corresponding versions that now still include support
 933// for the console (e.g. DefineNewEngineFunction should become DefineEngineFunction).
 934#define DefineNewEngineFunction( name, returnType, args, defaultArgs, usage )                                                    \
 935   static inline returnType _fn ## name ## impl args;                                                                            \
 936   TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## name                                                         \
 937      ( _EngineFunctionTrampoline< returnType args >::Args a )                                                                   \
 938   {                                                                                                                             \
 939      _CHECK_ENGINE_INITIALIZED( name, returnType );                                                                             \
 940      return EngineTypeTraits< returnType >::ReturnValue(                                                                        \
 941         _EngineFunctionTrampoline< returnType args >::jmp( _fn ## name ## impl, a )                                             \
 942      );                                                                                                                         \
 943   }                                                                                                                             \
 944   static _EngineFunctionDefaultArguments< void args > _fn ## name ## DefaultArgs defaultArgs;                                   \
 945   static EngineFunctionInfo _fn ## name ## FunctionInfo(                                                                        \
 946      #name,                                                                                                                     \
 947      &_SCOPE<>()(),                                                                                                             \
 948      usage,                                                                                                                     \
 949      #returnType " " #name #args,                                                                                               \
 950      "fn" #name,                                                                                                                \
 951      TYPE< returnType args >(),                                                                                                 \
 952      &_fn ## name ## DefaultArgs,                                                                                               \
 953      ( void* ) &fn ## name,                                                                                                     \
 954      0                                                                                                                          \
 955   );                                                                                                                            \
 956   static inline returnType _fn ## name ## impl args
 957
 958#define DefineNewEngineMethod( className, name, returnType, args, defaultArgs, usage )                                                          \
 959   struct _ ## className ## name ## frame                                                                                                       \
 960   {                                                                                                                                            \
 961      typedef className ObjectType;                                                                                                             \
 962      className* object;                                                                                                                        \
 963      inline returnType _exec args const;                                                                                                       \
 964   };                                                                                                                                           \
 965   _DefineMethodTrampoline( className, name, returnType, args );                                                                                \
 966   static _EngineFunctionDefaultArguments< _EngineMethodTrampoline< _ ## className ## name ## frame, void args >::FunctionType >                \
 967      _fn ## className ## name ## DefaultArgs defaultArgs;                                                                                      \
 968   static EngineFunctionInfo _fn ## className ## name ## FunctionInfo(                                                                          \
 969      #name,                                                                                                                                    \
 970      &_SCOPE< className >()(),                                                                                                                 \
 971      usage,                                                                                                                                    \
 972      "virtual " #returnType " " #name #args,                                                                                                   \
 973      "fn" #className "_" #name,                                                                                                                \
 974      TYPE< _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::FunctionType >(),                                      \
 975      &_fn ## className ## name ## DefaultArgs,                                                                                                 \
 976      ( void* ) &fn ## className ## _ ## name,                                                                                                  \
 977      0                                                                                                                                         \
 978   );                                                                                                                                           \
 979   returnType _ ## className ## name ## frame::_exec args const
 980
 981#define DefineNewEngineStaticMethod( className, name, returnType, args, defaultArgs, usage )                                           \
 982   static inline returnType _fn ## className ## name ## impl args;                                                                     \
 983   TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## className ## _ ## name                                             \
 984      ( _EngineFunctionTrampoline< returnType args >::Args a )                                                                         \
 985   {                                                                                                                                   \
 986      _CHECK_ENGINE_INITIALIZED( className::name, returnType );                                                                        \
 987      return EngineTypeTraits< returnType >::ReturnValue(                                                                              \
 988         _EngineFunctionTrampoline< returnType args >::jmp( _fn ## className ## name ## impl, a )                                      \
 989      );                                                                                                                               \
 990   }                                                                                                                                   \
 991   static _EngineFunctionDefaultArguments< void args > _fn ## className ## name ## DefaultArgs defaultArgs;                            \
 992   static EngineFunctionInfo _fn ## name ## FunctionInfo(                                                                              \
 993      #name,                                                                                                                           \
 994      &_SCOPE< className >()(),                                                                                                        \
 995      usage,                                                                                                                           \
 996      #returnType " " #name #args,                                                                                                     \
 997      "fn" #className "_" #name,                                                                                                       \
 998      TYPE< returnType args >(),                                                                                                       \
 999      &_fn ## className ## name ## DefaultArgs,                                                                                        \
1000      ( void* ) &fn ## className ## _ ## name,                                                                                         \
1001      0                                                                                                                                \
1002   );                                                                                                                                  \
1003   static inline returnType _fn ## className ## name ## impl args
1004
1005/// @}
1006
1007
1008//=============================================================================
1009//    Callbacks.
1010//=============================================================================
1011
1012/// Matching implement for DECLARE_CALLBACK.
1013///
1014///
1015/// @warn With the new interop system, method-style callbacks <em>must not</em> be triggered on object
1016///   that are being created!  This is because the control layer will likely not yet have a fully valid wrapper
1017///   object in place for the EngineObject under construction.
1018#define IMPLEMENT_CALLBACK( class, name, returnType, args, argNames, usageString )                                                           \
1019   struct _ ## class ## name ## frame { typedef class ObjectType; };                                                                         \
1020   TORQUE_API _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name;               \
1021   TORQUE_API void set_cb ## class ## _ ## name(                                                                                             \
1022      _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType fn )                                             \
1023      { cb ## class ## _ ## name = fn; }                                                                                                     \
1024   _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name;                          \
1025   namespace {                                                                                                                               \
1026      ::EngineFunctionInfo _cb ## class ## name(                                                                                             \
1027         #name,                                                                                                                              \
1028         &::_SCOPE< class >()(),                                                                                                             \
1029         usageString,                                                                                                                        \
1030         "virtual " #returnType " " #name #args,                                                                                             \
1031         "cb" #class "_" #name,                                                                                                              \
1032         ::TYPE< _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType >(),                                  \
1033         NULL,                                                                                                                               \
1034         ( void* ) &cb ## class ## _ ## name,                                                                                                \
1035         EngineFunctionCallout                                                                                                               \
1036      );                                                                                                                                     \
1037   }                                                                                                                                         \
1038   returnType class::name ## _callback args                                                                                                  \
1039   {                                                                                                                                         \
1040      if( cb ## class ## _ ## name ) {                                                                                                       \
1041         _EngineCallbackHelper cbh( this, reinterpret_cast< const void* >( cb ## class ## _ ## name ) );                                     \
1042         return returnType( cbh.call< returnType > argNames );                                                                               \
1043      }                                                                                                                                      \
1044      if( engineAPI::gUseConsoleInterop )                                                                                                    \
1045      {                                                                                                                                      \
1046         static StringTableEntry sName = StringTable->insert( #name );                                                                       \
1047         _EngineConsoleCallbackHelper cbh( sName, this );                                                                                    \
1048         return returnType( cbh.call< returnType > argNames );                                                                               \
1049      }                                                                                                                                      \
1050      return returnType();                                                                                                                   \
1051   }                                                                                                                                         \
1052   namespace {                                                                                                                               \
1053      ConsoleFunctionHeader _ ## class ## name ## header(                                                                                    \
1054         #returnType, #args, "" );                                                                                                           \
1055      ConsoleConstructor _ ## class ## name ## obj( #class, #name, usageString, &_ ## class ## name ## header );                             \
1056   }
1057
1058
1059/// Used to define global callbacks not associated with 
1060/// any particular class or namespace.
1061#define IMPLEMENT_GLOBAL_CALLBACK( name, returnType, args, argNames, usageString )                                                           \
1062   DEFINE_CALLOUT( cb ## name, name,, returnType, args, 0, usageString );                                                                    \
1063   returnType name ## _callback args                                                                                                         \
1064   {                                                                                                                                         \
1065      if( cb ## name )                                                                                                                       \
1066         return returnType( cb ## name argNames );                                                                                           \
1067      if( engineAPI::gUseConsoleInterop )                                                                                                    \
1068      {                                                                                                                                      \
1069         static StringTableEntry sName = StringTable->insert( #name );                                                                       \
1070         _EngineConsoleCallbackHelper cbh( sName, NULL );                                                                                    \
1071         return returnType( cbh.call< returnType > argNames );                                                                               \
1072      }                                                                                                                                      \
1073      return returnType();                                                                                                                   \
1074   }                                                                                                                                         \
1075   namespace {                                                                                                                               \
1076      ConsoleFunctionHeader _ ## name ## header(                                                                                             \
1077         #returnType, #args, "" );                                                                                                           \
1078      ConsoleConstructor _ ## name ## obj( NULL, #name, usageString, &_ ## name ## header );                                                 \
1079   }
1080   
1081   
1082// Again, temporary macros to allow splicing the API while we still have the console interop around.
1083
1084#define IMPLEMENT_CONSOLE_CALLBACK( class, name, returnType, args, argNames, usageString )                                                   \
1085   returnType class::name ## _callback args                                                                                                  \
1086   {                                                                                                                                         \
1087      if( engineAPI::gUseConsoleInterop )                                                                                                    \
1088      {                                                                                                                                      \
1089         static StringTableEntry sName = StringTable->insert( #name );                                                                       \
1090         _EngineConsoleCallbackHelper cbh( sName, this );                                                                                    \
1091         return returnType( cbh.call< returnType > argNames );                                                                               \
1092      }                                                                                                                                      \
1093      return returnType();                                                                                                                   \
1094   }                                                                                                                                         \
1095   namespace {                                                                                                                               \
1096      ConsoleFunctionHeader _ ## class ## name ## header(                                                                                    \
1097         #returnType, #args, "" );                                                                                                           \
1098      ConsoleConstructor _ ## class ## name ## obj( #class, #name, usageString, &_ ## class ## name ## header );                             \
1099   }
1100   
1101#define IMPLEMENT_NEW_CALLBACK( class, name, returnType, args, argNames, usageString )                                                       \
1102   struct _ ## class ## name ## frame { typedef class ObjectType; };                                                                         \
1103   TORQUE_API _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name;               \
1104   TORQUE_API void set_cb ## class ## _ ## name(                                                                                             \
1105      _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType fn )                                             \
1106      { cb ## class ## _ ## name = fn; }                                                                                                     \
1107   _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name;                          \
1108   namespace {                                                                                                                               \
1109      ::EngineFunctionInfo _cb ## class ## name(                                                                                             \
1110         #name,                                                                                                                              \
1111         &::_SCOPE< class >()(),                                                                                                             \
1112         usageString,                                                                                                                        \
1113         "virtual " #returnType " " #name #args,                                                                                             \
1114         "cb" #class "_" #name,                                                                                                              \
1115         ::TYPE< _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType >(),                                  \
1116         NULL,                                                                                                                               \
1117         &cb ## class ## _ ## name,                                                                                                          \
1118         EngineFunctionCallout                                                                                                               \
1119      );                                                                                                                                     \
1120   }                                                                                                                                         \
1121   returnType class::name ## _callback args                                                                                                  \
1122   {                                                                                                                                         \
1123      if( cb ## class ## _ ## name ) {                                                                                                       \
1124         _EngineCallbackHelper cbh( this, reinterpret_cast< const void* >( cb ## class ## _ ## name ) );                                     \
1125         return returnType( cbh.call< returnType > argNames );                                                                               \
1126      }                                                                                                                                      \
1127      return returnType();                                                                                                                   \
1128   }
1129
1130
1131
1132
1133// Internal helper class for doing call-outs in the new interop.
1134struct _EngineCallbackHelper
1135{
1136   protected:
1137    
1138      EngineObject* mThis;
1139      const void* mFn;
1140            
1141   public:
1142
1143      _EngineCallbackHelper( EngineObject* pThis, const void* fn )
1144         : mThis( pThis ),
1145           mFn( fn ) {}
1146      
1147      template< typename R, typename ...ArgTs >
1148      R call(ArgTs ...args) const
1149      {
1150         typedef R( FunctionType )( EngineObject*, ArgTs... );
1151         return R( reinterpret_cast< FunctionType* >( const_cast<void*>(mFn) )( mThis, args... ) );
1152      }
1153
1154};
1155
1156
1157#include "console/stringStack.h"
1158
1159// Internal helper for callback support in legacy console system.
1160struct _BaseEngineConsoleCallbackHelper
1161{
1162public:
1163
1164   /// Matches up to storeArgs.
1165   static const U32 MAX_ARGUMENTS = 11;
1166
1167   SimObject* mThis;
1168   S32 mInitialArgc;
1169   S32 mArgc;
1170   StringTableEntry mCallbackName;
1171   ConsoleValueRef mArgv[ MAX_ARGUMENTS + 2 ];
1172
1173   ConsoleValueRef _exec();
1174   ConsoleValueRef _execLater(SimConsoleThreadExecEvent *evt);
1175
1176   _BaseEngineConsoleCallbackHelper(): mThis(NULL), mInitialArgc(0), mArgc(0), mCallbackName(StringTable->EmptyString()){;}
1177};
1178
1179
1180
1181// Base helper for console callbacks
1182struct _EngineConsoleCallbackHelper : public _BaseEngineConsoleCallbackHelper
1183{
1184private:
1185   using Helper = engineAPI::detail::MarshallHelpers<ConsoleValueRef>;
1186public:
1187
1188   _EngineConsoleCallbackHelper( StringTableEntry callbackName, SimObject* pThis )
1189   {
1190      mThis = pThis;
1191      mArgc = mInitialArgc = pThis ? 2 : 1 ;
1192      mCallbackName = callbackName;
1193   }
1194   
1195   template< typename R, typename ...ArgTs >
1196   R call(ArgTs ...args)
1197   {
1198      if (Con::isMainThread())
1199      {
1200         ConsoleStackFrameSaver sav; sav.save();
1201         CSTK.reserveValues(mArgc + sizeof...(ArgTs), mArgv);
1202         mArgv[ 0 ].value->setStackStringValue(mCallbackName);
1203        
1204        Helper::marshallEach(mArgc, mArgv, args...);
1205        
1206         return R( EngineUnmarshallData< R>()( _exec() ) );
1207      }
1208      else
1209      {
1210         SimConsoleThreadExecCallback cb;
1211         SimConsoleThreadExecEvent *evt = new SimConsoleThreadExecEvent(mArgc + sizeof...(ArgTs), NULL, false, &cb);
1212         evt->populateArgs(mArgv);
1213         mArgv[ 0 ].value->setStackStringValue(mCallbackName);
1214        
1215        Helper::marshallEach(mArgc, mArgv, args...);
1216        
1217         Sim::postEvent((SimObject*)Sim::getRootGroup(), evt, Sim::getCurrentTime());
1218
1219         return R( EngineUnmarshallData< R>()( cb.waitForResult() ) );
1220      }
1221   }
1222   
1223};
1224
1225
1226// Override for when first parameter is presumably a SimObject*, in which case A will be absorbed as the callback
1227template<typename P1> struct _EngineConsoleExecCallbackHelper : public _BaseEngineConsoleCallbackHelper
1228{
1229private:
1230   using Helper = engineAPI::detail::MarshallHelpers<ConsoleValueRef>;
1231public:
1232
1233   _EngineConsoleExecCallbackHelper( SimObject* pThis )
1234   {
1235      mThis = pThis;
1236      mArgc = mInitialArgc = 2;
1237      mCallbackName = NULL;
1238   }
1239
1240   
1241   template< typename R, typename SCB, typename ...ArgTs >
1242   R call( SCB simCB , ArgTs ...args )
1243   {
1244      if (Con::isMainThread())
1245      {
1246         ConsoleStackFrameSaver sav; sav.save();
1247         CSTK.reserveValues(mArgc+sizeof...(ArgTs), mArgv);
1248         mArgv[ 0 ].value->setStackStringValue(simCB);
1249
1250        Helper::marshallEach(mArgc, mArgv, args...);
1251
1252         return R( EngineUnmarshallData< R>()( _exec() ) );
1253      }
1254      else
1255      {
1256         SimConsoleThreadExecCallback cb;
1257         SimConsoleThreadExecEvent *evt = new SimConsoleThreadExecEvent(mArgc+sizeof...(ArgTs), NULL, true, &cb);
1258         evt->populateArgs(mArgv);
1259         mArgv[ 0 ].value->setStackStringValue(simCB);
1260        
1261        Helper::marshallEach(mArgc, mArgv, args...);
1262
1263         Sim::postEvent(mThis, evt, Sim::getCurrentTime());
1264
1265         return R( EngineUnmarshallData< R>()( cb.waitForResult() ) );
1266      }
1267   }
1268};
1269
1270// Override for when first parameter is const char*
1271template<> struct _EngineConsoleExecCallbackHelper<const char*> : public _BaseEngineConsoleCallbackHelper
1272{
1273private:
1274   using Helper = engineAPI::detail::MarshallHelpers<ConsoleValueRef>;
1275public:
1276   _EngineConsoleExecCallbackHelper( const char *callbackName )
1277   {
1278      mThis = NULL;
1279      mArgc = mInitialArgc = 1;
1280      mCallbackName = StringTable->insert(callbackName);
1281   }
1282
1283   template< typename R, typename ...ArgTs >
1284   R call(ArgTs ...args)
1285   {
1286      if (Con::isMainThread())
1287      {
1288         ConsoleStackFrameSaver sav; sav.save();
1289         CSTK.reserveValues(mArgc+sizeof...(ArgTs), mArgv);
1290         mArgv[ 0 ].value->setStackStringValue(mCallbackName);
1291        
1292        Helper::marshallEach(mArgc, mArgv, args...);
1293        
1294         return R( EngineUnmarshallData< R>()( _exec() ) );
1295      }
1296      else
1297      {
1298         SimConsoleThreadExecCallback cb;
1299         SimConsoleThreadExecEvent *evt = new SimConsoleThreadExecEvent(mArgc+sizeof...(ArgTs), NULL, false, &cb);
1300         evt->populateArgs(mArgv);
1301         mArgv[ 0 ].value->setStackStringValue(mCallbackName);
1302        
1303        Helper::marshallEach(mArgc, mArgv, args...);
1304
1305         Sim::postEvent((SimObject*)Sim::getRootGroup(), evt, Sim::getCurrentTime());
1306         return R( EngineUnmarshallData< R>()( cb.waitForResult() ) );
1307      }
1308   }   
1309};
1310
1311// Re-enable some VC warnings we disabled for this file.
1312#pragma warning( pop ) // 4510 and 4610
1313
1314#endif // !_ENGINEAPI_H_
1315