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 a )   \
   {                                                                                                                                            \
      ( className::name, returnType );                                                                                 \
      return < returnType >::ReturnValue(                                                                                       \
         < _ ## className ## name ## frame, returnType args >::jmp( object, a )                                          \
      );                                                                                                                                        \
   }
define
DefineConsoleFunction(name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## name ## impl args;                                                                            \
   static <  args > _fn ## name ## DefaultArgs defaultArgs;                                   \
   static < returnType >:: _ ## name ## caster( *,  argc,  *argv )       \
   {                                                                                                                             \
      return < returnType >::( < 1, returnType args >::thunk(                \
         argc, argv, &_fn ## name ## impl, _fn ## name ## DefaultArgs                                                            \
      ) );                                                                                                                       \
   }                                                                                                                             \
   static  _ ## name ## header                                                                              \
      ( #returnType, #args, #defaultArgs );                                                                                      \
   static                                                                                                      \
      _ ## name ## obj( , #name, < returnType >::CallbackType( _ ## name ## caster ), usage,          \
         < 1, returnType args >::NUM_ARGS - () defaultArgs,                       \
         < 1, returnType args >::NUM_ARGS,                                                                    \
         false, &_ ## name ## header                                                                                             \
      );                                                                                                                         \
   static inline returnType _fn ## name ## impl args
define
DefineConsoleMethod(className, name, returnType, args, defaultArgs, usage)    struct _ ## className ## name ## frame                                                                                                       \
   {                                                                                                                                            \
      typedef className ObjectType;                                                                                                             \
      className* object;                                                                                                                        \
      inline returnType _exec args ;                                                                                                       \
   };                                                                                                                                           \
   static < < _ ## className ## name ## frame,  args >::FunctionType >                \
      _fn ## className ## name ## DefaultArgs defaultArgs;                                                                                      \
   static < returnType >:: _ ## className ## name ## caster( * object,  argc,  *argv )  \
   {                                                                                                                                            \
      _ ## className ## name ## frame frame;                                                                                                    \
      frame.object = static_cast< className* >( object );                                                                                       \
      return < returnType >::( < 2, returnType args >::thunk(                               \
         argc, argv, &_ ## className ## name ## frame::_exec, &frame, _fn ## className ## name ## DefaultArgs                                   \
      ) );                                                                                                                                      \
   }                                                                                                                                            \
   static  _ ## className ## name ## header                                                                                \
      ( #returnType, #args, #defaultArgs );                                                                                                     \
   static                                                                                                                     \
      className ## name ## obj( #className, #name,                                                                                              \
         < returnType >::CallbackType( _ ## className ## name ## caster ), usage,                                        \
         < 2, returnType args >::NUM_ARGS - () defaultArgs,                                      \
         < 2, returnType args >::NUM_ARGS,                                                                                   \
         false, &_ ## className ## name ## header                                                                                               \
      );                                                                                                                                        \
   returnType _ ## className ## name ## frame::_exec args 
define
DefineConsoleStaticMethod(className, name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## className ## name ## impl args;                                                                     \
   static <  args > _fn ## className ## name ## DefaultArgs defaultArgs;                            \
   static < returnType >:: _ ## className ## name ## caster( *,  argc,  *argv )\
   {                                                                                                                                   \
      return < returnType >::( < 1, returnType args >::thunk(                      \
         argc, argv, &_fn ## className ## name ## impl, _fn ## className ## name ## DefaultArgs                                        \
      ) );                                                                                                                             \
   }                                                                                                                                   \
   static  _ ## className ## name ## header                                                                       \
      ( #returnType, #args, #defaultArgs, true );                                                                                      \
   static                                                                                                            \
      _ ## className ## name ## obj( #className, #name, < returnType >::CallbackType( _ ## className ## name ## caster ), usage, \
         < 1, returnType args >::NUM_ARGS - () defaultArgs,                             \
         < 1, returnType args >::NUM_ARGS,                                                                          \
         false, &_ ## className ## name ## header                                                                                      \
      );                                                                                                                               \
   static inline returnType _fn ## className ## name ## impl args
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
DefineNewEngineFunction(name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## name ## impl args;                                                                            \
   TORQUE_API < returnType >::ReturnValueType fn ## name                                                         \
      ( < returnType args >::Args a )                                                                   \
   {                                                                                                                             \
      ( name, returnType );                                                                             \
      return < returnType >::ReturnValue(                                                                        \
         < returnType args >::jmp( _fn ## name ## impl, a )                                             \
      );                                                                                                                         \
   }                                                                                                                             \
   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 a )                                                                         \
   {                                                                                                                                   \
      ( className::name, returnType );                                                                        \
      return < returnType >::ReturnValue(                                                                              \
         < returnType args >::jmp( _fn ## className ## name ## impl, a )                                      \
      );                                                                                                                               \
   }                                                                                                                                   \
   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 a )   \
   {                                                                                                                                            \
      ( className::name, returnType );                                                                                 \
      return < returnType >::ReturnValue(                                                                                       \
         < _ ## className ## name ## frame, returnType args >::jmp( object, a )                                          \
      );                                                                                                                                        \
   }
DefineConsoleFunction(name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## name ## impl args;                                                                            \
   static <  args > _fn ## name ## DefaultArgs defaultArgs;                                   \
   static < returnType >:: _ ## name ## caster( *,  argc,  *argv )       \
   {                                                                                                                             \
      return < returnType >::( < 1, returnType args >::thunk(                \
         argc, argv, &_fn ## name ## impl, _fn ## name ## DefaultArgs                                                            \
      ) );                                                                                                                       \
   }                                                                                                                             \
   static  _ ## name ## header                                                                              \
      ( #returnType, #args, #defaultArgs );                                                                                      \
   static                                                                                                      \
      _ ## name ## obj( , #name, < returnType >::CallbackType( _ ## name ## caster ), usage,          \
         < 1, returnType args >::NUM_ARGS - () defaultArgs,                       \
         < 1, returnType args >::NUM_ARGS,                                                                    \
         false, &_ ## name ## header                                                                                             \
      );                                                                                                                         \
   static inline returnType _fn ## name ## impl args
DefineConsoleMethod(className, name, returnType, args, defaultArgs, usage)    struct _ ## className ## name ## frame                                                                                                       \
   {                                                                                                                                            \
      typedef className ObjectType;                                                                                                             \
      className* object;                                                                                                                        \
      inline returnType _exec args ;                                                                                                       \
   };                                                                                                                                           \
   static < < _ ## className ## name ## frame,  args >::FunctionType >                \
      _fn ## className ## name ## DefaultArgs defaultArgs;                                                                                      \
   static < returnType >:: _ ## className ## name ## caster( * object,  argc,  *argv )  \
   {                                                                                                                                            \
      _ ## className ## name ## frame frame;                                                                                                    \
      frame.object = static_cast< className* >( object );                                                                                       \
      return < returnType >::( < 2, returnType args >::thunk(                               \
         argc, argv, &_ ## className ## name ## frame::_exec, &frame, _fn ## className ## name ## DefaultArgs                                   \
      ) );                                                                                                                                      \
   }                                                                                                                                            \
   static  _ ## className ## name ## header                                                                                \
      ( #returnType, #args, #defaultArgs );                                                                                                     \
   static                                                                                                                     \
      className ## name ## obj( #className, #name,                                                                                              \
         < returnType >::CallbackType( _ ## className ## name ## caster ), usage,                                        \
         < 2, returnType args >::NUM_ARGS - () defaultArgs,                                      \
         < 2, returnType args >::NUM_ARGS,                                                                                   \
         false, &_ ## className ## name ## header                                                                                               \
      );                                                                                                                                        \
   returnType _ ## className ## name ## frame::_exec args 
DefineConsoleStaticMethod(className, name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## className ## name ## impl args;                                                                     \
   static <  args > _fn ## className ## name ## DefaultArgs defaultArgs;                            \
   static < returnType >:: _ ## className ## name ## caster( *,  argc,  *argv )\
   {                                                                                                                                   \
      return < returnType >::( < 1, returnType args >::thunk(                      \
         argc, argv, &_fn ## className ## name ## impl, _fn ## className ## name ## DefaultArgs                                        \
      ) );                                                                                                                             \
   }                                                                                                                                   \
   static  _ ## className ## name ## header                                                                       \
      ( #returnType, #args, #defaultArgs, true );                                                                                      \
   static                                                                                                            \
      _ ## className ## name ## obj( #className, #name, < returnType >::CallbackType( _ ## className ## name ## caster ), usage, \
         < 1, returnType args >::NUM_ARGS - () defaultArgs,                             \
         < 1, returnType args >::NUM_ARGS,                                                                          \
         false, &_ ## className ## name ## header                                                                                      \
      );                                                                                                                               \
   static inline returnType _fn ## className ## name ## impl args
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:

name

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." )
{
}

DefineNewEngineFunction(name, returnType, args, defaultArgs, usage)    static inline returnType _fn ## name ## impl args;                                                                            \
   TORQUE_API < returnType >::ReturnValueType fn ## name                                                         \
      ( < returnType args >::Args a )                                                                   \
   {                                                                                                                             \
      ( name, returnType );                                                                             \
      return < returnType >::ReturnValue(                                                                        \
         < returnType args >::jmp( _fn ## name ## impl, a )                                             \
      );                                                                                                                         \
   }                                                                                                                             \
   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 a )                                                                         \
   {                                                                                                                                   \
      ( className::name, returnType );                                                                        \
      return < returnType >::ReturnValue(                                                                              \
         < returnType args >::jmp( _fn ## className ## name ## impl, a )                                      \
      );                                                                                                                               \
   }                                                                                                                                   \
   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();                                                                                                                   \
   }

Public Functions

TYPE< const char *>()

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