ArgScript namespace
The Spore scripting language.
ArgScript is a scripting language largely used in Spore. Although it can be used for scripts, it is mostly used as a file format, as a way to store information about multiple objects (for example, effects, property definitions, cinematics, etc). ArgScript can be considered similar to XML: ArgScript is the format, but the interpretation depends on the program. To create a parser for ArgScript, use the ArgScript::
Commands
Commands are the basic element in ArgScript. A command is a single line of words, separated by whitespaces. The first word is the keyword, which determines how the command is processed and executed. The rest of words are the arguments.
Words prefixed with '-', like '-scale', are called options, which are not required (that is, they are optional). Options can have arguments as well; when they don't, they are called flags.
For example, consider this line: model MyCube 3 -scale 2.0 -rigid
This command line is formed by:
- Keyword model.
- 2 arguments: MyCube and 3.
- 1 option called scale, with 1 argument: 2.0.
- 1 option called (something).
- 1 flag (option without arguments) called.
To process commands, the ICommand class is used. On its main method, ICommand::
The cheat console uses commands to process cheats. For more information, check the App::
Blocks
Blocks are groups of commands. A block starts with a command, and ends when a line with the keyword 'end' is reached. Usually, blocks represent groups of data, for example, a scene in a cinematic; commands inside it represent its properties, for example the camera movement. A block can have its own parsers, allowing to have specific blocks and commands that only work on certain blocks.
For example:
effect fire_special_fx # a block is assigned to the keyword 'effect' particles FireParticles # a command inside a block, it does not work outside the block sound fire_sound # indentation is not necessary, but it makes it look more organised end # this is the end of the 'effect' block
To process blocks, the IBlock class is used. The IBlock::
Literals and parenthesis
All the words in a line are separated when whitespaces are found. Sometimes, however, one might be interested in having an argument that has whitespaces inside; in that case, eastl::string literals surrounded by "" can be used. For example: text "Problem solved!"
In that example, Problem solved! will be a single argument.
Parenthesis have the same effect as eastl::string literals; for convention, eastl::string literals are only used for things that are actually text; for everything else, parenthesis are preferred. For example: model MyCube -color (0.2, 0, 1.0)
In that example 0.2, 0, 1.0 will be a single argument.
Mathematical and logical expressions
ArgScript has support for mathematical and logical expressions. For example, imagine there is a command with keyword angle and an argument which is meant to be the angle we want. We can put a mathematical expression there surrounded by parenthesis, like '(3 + 0.2^3 * sqrt(0.2))', '(sind(50) * datan(30))', etc. Check the FormatParser::
Logical expressions are also supported. They accept the operators 'not', 'or', 'and'; check the FormatParser::
Functions
As seen in the mathematical example before, ArgScript has support for functions. Functions cannot be declared in the script file (like one would expect in a programming language); they can only be declared in the code. Functions can take any number of parameters and return a bool, int or float value.
Functions are processed using the IFunction class. To add a function, the Lexer::
Variables
ArgScript has support for variables. Variables are assigned using the 'set...' commands. To get the value of a variable, it must be prefixed with $. For example:
setf kMaxScale 10.0 # set a float variable with value 10.0 model MyCube -scale $kMaxScale
It is also possible to use variables inside other names or variables, using ${var_name}. For example:
set quality low model MyCube_${low}_quality
These are the commands for settings variables:
- set VariableName Value: eastl::strings. For example set name "My name"
- setb VariableName Value: booleans. For example setb render false
- seti VariableName Value: integers. For exmaple seti kMaxInt (2^31)
- setf VariableName Value: floats. For example setf kMaxScale 10.0
- setc VariableName Value: colors. For example setc red (1.0, 0, 0)
- setv2 VariableName Value: vector2. For example setv2 UV_offset (0.5, -0.5)
- setv3 VariableName Value: vector3. For example setv3 offset (0.5, -0.5, 3.0)
- setv4 VariableName Value: vector4. For example setv4 randomv4 (0.5, -0.5, 3.0, 0.2)
- sete VariableName Value Enumeration: special case, the value is restricted to an enumeration of values. For example, sete mode Wireframe (Wireframe Normal), the value can only be 'Wireframe' or 'Normal'.
Variables can also be set and used using the FormatParser::
Namespaces
Namespaces are special blocks that restrict the scope (that is, where it can be used) of a variable. When a variable is assigned, it is automatically assigned in the namespace scope, and therefore it can't be used outside of that scope. Namespace variables can be accessed prefixing the variable name with the namespace name and a ':' sign. For example:
namespace ParticleEffects set EffectTag "particles" # the variable can be used here because we are in the same scope effect ${EffectTag}_01 # this will be 'particles_01' # insert any code here end end namespace SoundEffects set EffectTag "sound" # the variable can be used here because we are in the same scope effect ${EffectTag}_01 # this will be 'sound_01' # insert any code here end end # if we try to use $EffectTag here, it will throw an exception, because EffecTag is not defined in this scope. # however, we can do this: setEffect ${ParticleEffects:EffectTag}_01
Via code, global variables can be set; those can be accessed prefixing the name with ':'. For example, if you set a global variable (using the FormatParser::
Conditionals
Conditions are also supported in ArgScript. Conditional blocks only get executed if a condition is met. To create a conditional block, use the command 'if (condition...)'; to end the conditional block, use the command 'endif'. To define what must be excuted if the condition is NOT met, use the 'else' keyword. To define another condition when the first one is not met, use the command 'elseif (condition..)'. The conditions are logical expressions, like the ones that have been described above.
For example:
seti kQuality 0 if ($kQuality < 0) # do something that is only executed if kQuality is less than 0 else if ($kQuality > 3) # do something that is only executed if kQuality is greater than 3 else # do something that is only executed if kQuality is not less than 0 and not greater than 3. endif # end conditional block # let 'IsInEditor' and 'CinematicSupported' be bool variables set via code if (IsInEditor and CinematicSupported) # do something endif
Definitions
ArgScript has support for definitions, which are blocks of data that can be created multiple times, changing certain parameters. To create a definition, use the 'define DefinitionName(arguments...)' command; to end the conditional block, use the command 'enddef'. When inside the definition, the arguments can be used like variables. For example:
define EDT_currency_materials_MACRO( CURRENCY ) material EDT_currency_&{ CURRENCY }_mtl shader planetLitIcon_material texture sampler0 UI_currency_coin_&{ CURRENCY }_diffuse texture sampler1 UI_currency_coin_&{ CURRENCY }_specBump end enddef
Now, there are three commands that can be used to create instances of that definition:
- create: Instatiate the given definition; an exception is thrown if the definition does not exist. For example: 'create EDT_currency_materials_MACRO( DNA )'.
- screate: Instatiate the given definition, without throwing an error if it does not exist. For example: 'screate EDT_currency_materials_MACRO( DNA )'.
- arrayCreate: Instatiate the given definition a certain number of times. The definition will receive two parameters: the current index and the number of times to instatiate. For example: 'arrayCreate defined_macro 10'.
The command undefine can be used to remove a definition, for example, 'undefine EDT_currency_materials_MACRO'.
Other commands and functions
Here is a list of other commands supported by default in ArgScript:
- include FileName: Includes the given file, throwing an exception if it does not exist. The path uses the format required by http:/
/ www.cplusplus.com/ reference/ cstdio/ fopen/ - sinclude FileName: Includes the given file, with no error if the file does not exist. The path uses the format required by http:/
/ www.cplusplus.com/ reference/ cstdio/ fopen/ - help [Pattern] [-full] [-html]: Shows the description of commands and blocks. Optionally, a pattern (that allows * and ?) that the keywords must follow can be specified; otherwise, all descriptions will be printed. There are two options: '-full' prints a detailed description, and '-html' prints an html description (rarely supported).
- eval Command: Parse the given argument as a command.
- purge Scope: Purge variable definitions from the given namespace scope. Scope must finish in ':'.
- showArguments ...: Output the arguments of this command.
- version Number: Set the version of this script. Using the FormatParser::
SetVersionRange() method, the supported version range of the script can be set; when the command 'version' is found with an unsupported version, an exception is thrown. - trace "Text": Prints the given text to the output stream.
Here is a list of other functions supported by default in ArgScript:
- varExists(name): Returns true if the given variable exists (has a value).
- commandExists(name): Returns true if the given command exists.
- defExists(name): Returns true if the given definition exists.
- eq(eastl::string1, eastl::string2): Compares two eastl::strings.
- match(eastl::string, pattern): Returns true if the eastl::string matches the wildcard pattern (which supports special characters * and ?).
- minVersion(): Returns minimum accepted script version.
- maxVersion(): Returns maximum accepted script version.
Parsing files with
To parse files with ArgScript, first you must get a FormatParser instance using the ArgScript::
Classes
- class FormatParser
- This class contains all the parsers necessary to process a certain ArgScript format.
- class IBlock
- This parser represents a block of ArgScript lines.
- class ICommand
- This class is a type of IParser that can parse a single line of data.
- class IFunction
- Represents an ArgScript function.
- class IParser
- This interface represents a command or block that can be parsed in ArgScript.
- class ISpecialBlock
- This is a special kind of block that can process every line individually, and that uses its own end keywords.
- class ITraceStream
- class LambdaParser
- class Lexer
- This class is used to read and process expressions in ArgScript.
- class Line
- This class represents a line of ArgScript data.
- struct LineOption
- An option of an ArgScript line.
Enums
- enum class DescriptionMode { Basic = 0, Complete = 1, HTML = 2 }
- The type of description required by 'GetDescription' functions; it can be either basic or complete.
Typedefs
- using ArgScriptException = eastl::string&
- A standard ArgScript exception, which is just a eastl::string.
- using LexerString = const char*
- using ParseLine_t = void(*)(const Line&, FormatParser*)
- using GetDescription_t = const char*(*)(DescriptionMode)
- using SetData_t = void(*)(FormatParser*, void*)
- using PrintF_ptr = void*(*)(FormatParser*object, const char*str,...)
- using EnumValue = eastl::pair<const char*, int>
- A key-value pair (c-eastlstring, int) in an enumeration.
- using Arguments = const char*const *
- An array of c-eastlstrings that are the arguments of a line or an option.
Functions
- ASSERT_SIZE(FormatParser, 0x1C0)
- auto CreateStream() -> FormatParser*
- Creates a new ArgScript stream, which is an instance of FormatParser.
- auto Addresses(FormatParser) -> namespace
- ASSERT_SIZE(IBlock, 0x34)
- auto Addresses(IBlock) -> namespace
- auto Addresses(Lexer) -> namespace
- ASSERT_SIZE(Line, 0x44)
- auto Addresses(Line) -> namespace
Variables
-
MODAPI PrintF_
ptr PrintF - A function that prints a formatted text into an ArgScript stream.
Enum documentation
enum class ArgScript:: DescriptionMode
The type of description required by 'GetDescription' functions; it can be either basic or complete.
Typedef documentation
typedef eastl::string& ArgScript:: ArgScriptException
A standard ArgScript exception, which is just a eastl::string.
typedef const char* ArgScript:: LexerString
typedef void(*ArgScript:: ParseLine_t)(const Line&, FormatParser*)
typedef const char*(*ArgScript:: GetDescription_t)(DescriptionMode)
typedef void*(*ArgScript:: PrintF_ptr)(FormatParser*object, const char*str,...)
Function documentation
ArgScript:: ASSERT_SIZE(FormatParser,
0x1C0)
FormatParser* ArgScript:: CreateStream()
Creates a new ArgScript stream, which is an instance of FormatParser.
namespace ArgScript:: Addresses(FormatParser)
ArgScript:: ASSERT_SIZE(IBlock,
0x34)
ArgScript:: ASSERT_SIZE(Line,
0x44)
Variable documentation
MODAPI PrintF_ ptr ArgScript:: PrintF
A function that prints a formatted text into an ArgScript stream.
This uses the same format as the C printf function.