| AngelScript |

Script builder

Path: /sdk/add_on/scriptbuilder/

This class is a helper class for loading and building scripts, with a basic pre-processor that supports conditional compilation, include directives, pragma directives, and metadata declarations.

By default the script builder resolves include directives by loading the included file from the relative directory of the file it is included from. If you want to do this in another way, then you should implement the include callback which will let you process the include directive in a custom way, e.g. to load the included file from memory, or to support multiple search paths. The include callback should call the AddSectionFromFile or AddSectionFromMemory to include the section in the current build.

If the application should to support pragma directives, it must register the pragma callback to process the text provided for the pragma directive. Without the callback the script builder will give an error when encountering a pragma directive.

The script builder will also remove any lines that start with `#!` as comments. This is done to support shebang interpreter directives often used on Linux and UNIX based operative systems.

If you do not want process metadata then you can compile the add-on with the define AS_PROCESS_METADATA 0, which will exclude the code for processing this. This define can be made in the project settings or directly in the header.

# Public C++ interface

class CScriptBuilder
{
public:
// Start a new module
int StartNewModule(asIScriptEngine *engine, const char *moduleName);
// Load a script section from a file on disk
// Returns 1 if the file was included
// 0 if the file had already been included before
// <0 on error
int AddSectionFromFile(const char *filename);
// Load a script section from memory
// Returns 1 if the section was included
// 0 if a section with the same name had already been included before
// <0 on error
int AddSectionFromMemory(const char *sectionName,
const char *scriptCode,
unsigned int scriptLength = 0,
int lineOffset = 0);
// Build the added script sections
int BuildModule();
// Returns the script engine
asIScriptEngine *GetEngine();
// Returns the current module
asIScriptModule *GetModule();
// Register the callback for resolving include directive
void SetIncludeCallback(INCLUDECALLBACK_t callback, void *userParam);
// Register the callback for resolving pragma directive
void SetPragmaCallback(PRAGMACALLBACK_t callback, void *userParam);
// Add a pre-processor define for conditional compilation
void DefineWord(const char *word);
// Enumerate included script sections
unsigned int GetSectionCount() const;
string GetSectionName(unsigned int idx) const;
// Get metadata declared for classes, interfaces, and enums
// Each metadata block, i.e. [...], is returned as a separate string
std::vector<std::string> GetMetadataStringForType(int typeId);
// Get metadata declared for functions
// Each metadata block, i.e. [...], is returned as a separate string
std::vector<std::string> GetMetadataStringForFunc(asIScriptFunction *func);
// Get metadata declared for global variables
// Each metadata block, i.e. [...], is returned as a separate string
std::vector<std::string> GetMetadataStringForVar(int varIdx);
// Get metadata declared for a class method
// Each metadata block, i.e. [...], is returned as a separate string
// Use the asIScriptFunction for the virtual method for lookup
std::vector<std::string> GetMetadataStringForTypeMethod(int typeId, asIScriptFunction *method);
// Get metadata declared for a class property
// Each metadata block, i.e. [...], is returned as a separate string
std::vector<std::string> GetMetadataStringForTypeProperty(int typeId, int varIdx);
};

## The include callback signature

// This callback will be called for each #include directive encountered by the
// builder. The callback should call the AddSectionFromFile or AddSectionFromMemory
// to add the included section to the script. If the include cannot be resolved
// then the function should return a negative value to abort the compilation.
typedef int (*INCLUDECALLBACK_t)(const char *include, const char *from, CScriptBuilder *builder, void *userParam);

## The pragma callback signature

// This callback will be called for each #pragma directive encountered by the builder.
// The application can interpret the pragmaText and decide what do to based on that.
// If the callback returns a negative value the builder will report an error and abort the compilation.
typedef int(*PRAGMACALLBACK_t)(const std::string &pragmaText, CScriptBuilder &builder, void *userParam);

# Include directives

Example script with include directive:

      #include "commonfuncs.as"

      void main()
      {
        // Call a function from the included file
        CommonFunc();
      }

# Conditional programming

The builder supports conditional programming through the #if/#endif preprocessor directives. The application may define a word with a call to DefineWord(), then the scripts may check for this definition in the code in order to include/exclude parts of the code.

This is especially useful when scripts are shared between different binaries, for example, in a client/server application.

Example script with conditional compilation:

      class CObject
      {
        void Process()
        {
      #if SERVER
          // Do some server specific processing
      #endif

      #if CLIENT
          // Do some client specific processing
      #endif

          // Do some common processing
        }
      }

# Metadata in scripts

Metadata can be added before script class, interface, function, and global variable declarations. The metadata is removed from the script by the builder class and stored for post build lookup by the type id, function id, or variable index.

Exactly what the metadata looks like is up to the application. The builder class doesn't impose any rules, except that the metadata should be added between brackets []. After the script has been built the application can obtain the metadata strings and interpret them as it sees fit. Multiple metadata blocks, i.e. [], can be defined for each entity.

Example script with metadata:

      [factory func = CreateOgre]
      class COgre
      {
        [editable]
        vector3 myPosition;

        [editable]
        [range [10, 100]]
        int     myStrength;
      }

      [factory]
      COgre @CreateOgre()
      {
        return @COgre();
      }

Example usage:

CScriptBuilder builder;
int r = builder.StartNewModule(engine, "my module");
if( r >= 0 )
r = builder.AddSectionFromMemory(script);
if( r >= 0 )
r = builder.BuildModule();
if( r >= 0 )
{
// Find global variables that have been marked as editable by user
asIScriptModule *mod = engine->GetModule("my module");
int count = mod->GetGlobalVarCount();
for( int n = 0; n < count; n++ )
{
vector<string> metadata = builder.GetMetadataStringForVar(n);
for( int m = 0; m < metadata.size(); m++ )
{
if( metadata[m] == "editable" )
{
// Show the global variable in a GUI
...
}
}
}
}
asIScriptModule::GetGlobalVarCount
virtual asUINT GetGlobalVarCount() const =0
Returns the number of global variables in the module.
asIScriptEngine::GetModule
virtual asIScriptModule * GetModule(const char *module, asEGMFlags flag=asGM_ONLY_IF_EXISTS)=0
Return an interface pointer to the module.
asIScriptEngine
The engine interface.
Definition: angelscript.h:1102
asIScriptFunction
The interface for a script function description.
Definition: angelscript.h:3996
asIScriptModule
The interface to the script modules.
Definition: angelscript.h:2232