HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Calling an hscript Script from C++ Code

Introduction

hscript script is a scripting language interpreted by Houdini. For quick evaluation, you can type the hscript commands in the Textport window in Houdini. The hscript has many useful commands that you may want to invoke in the C++ code, for example to source own script file (using source command) or to display a dialog box (using message command). There is an CMD_Manager class to facilitate the script invocation, and its CMD_Manager::execute() method can be used to run the command.

The CMD_Manager::execute() signature looks like this:

void execute(const char * cmd, // command to run
int add_to_history = 0, // add the command to history
ostream * out=0, // stream to print output to
ostream *err=0, // stream to print errors to
int do_alias_expansion = 1, // perform command alias expansion
bool create_block = true); // run commands in one go

At the minimum, you need to pass a string representing the hscript command, which will be executed. If you provide the output stream, any output produced by the command will be written there. Also, if you pass in an error stream pointer, any error messages will be printed there.

The command manager instance is owned by the OP_Director and can be obtained by OP_Director::getCommandManager(). The OP_Director instance, in turn, is accessible via the global function OPgetDirector(). OP_Director class represents the root of the node hierarchy (ie, the node "/"), and therefore there is only one instance of this class. This class has several OP_Managers as its children.

See Also
Class Hierarchy

About OP_Director

In addition to being the root of the node hierarchy, OP_Director's role is to hold references to several other global instances of classes such as OP_CommandManager, OP_BundleList, OP_Take, OP_OTLManager. Also, OP_Director maintains some global states, such as currently selected nodes OP_Director::getPickedNodes() or current working directory OP_Director::getCwd(), which represents the path of a node the director considers to be the current.

See Also
Paths, Grouping Nodes in Bundles

The current working directory is particularly relevant for executing hscript commands because some of them operate with respect to that directory. For example opadd will create a new node inside the current working directory. You can use pwd and cd commands to print and change the current directory. You can also use the C++ methods OP_Director::getCwd() and OP_Director::setCwd() to achieve the same thing.

Example Code Description

Let's say that we want to pop up a message dialog and detect which button was pressed by the user. The hscript command that displays the dialog is called message, and its -b switch defines the buttons (separated by a comma). The -d switch specifies the default button.

UT_String command = "message "
"-b \"Left,Middle,Right\" "
"-d 0 "
"Please press any button.";

We will run the message command and retrieve the button index from the output stream. To obtain the command manager object, we query the global director.

OPgetDirector()->getCommandManager()->execute( command, false, &os );

Now, we need to parse the output stream and determine what number was printed out. We obtain the string using UT_OStrStream::str() but, after that, we have to unlock the buffer using the freeze(0) method.

UT_String result_str;
int result_int;
result_str.harden( os.str() );
result_str.trimSpace();
os.freeze(0);
if( result_str.isstring() && result_str.isInteger() )
result_int = result_str.toInt();
else
result_int = -1;

And now we can provide feedback to test if the code works correctly.

const char * button;
UT_String feedback_cmd;
if( result_int == 0 )
button = "first";
else if( result_int == 1 )
button = "second";
else if( result_int == 2 )
button = "third";
else
button = "invalid";
feedback_cmd.sprintf( "message You pressed the %s button", button );
OPgetDirector()->getCommandManager()->execute( feedback_cmd );

Full Example Code

void hdkExecuteMessageCmd()
{
UT_String result_str;
int result_int;
const char * button;
UT_String command;
// construct and run the command
command = "message "
"-b \"Left,Middle,Right\" "
"-d 0 "
"Please press any button.";
OPgetDirector()->getCommandManager()->execute( command, false, &os );
// retrieve the output stream string and convert it into an integer
result_str.harden( os.str() );
result_str.trimSpace();
os.freeze(0);
if( result_str.isstring() && result_str.isInteger() )
result_int = result_str.toInt();
else
result_int = -1;
// construct the feedback command and run it
if( result_int == 0 )
button = "first";
else if( result_int == 1 )
button = "second";
else if( result_int == 2 )
button = "third";
else
button = "invalid";
command.sprintf( "message You pressed the %s button", button );
}