File Browser Command

From The Foundry MODO SDK wiki
Jump to: navigation, search

Introduction

This article provides C++ source code for spawning a file browser from a command.

File dialogs are documented in depth, here: File Dialogs

Code

cmd_filebrowse.cpp
/*
 *
 *	Implement a simple command for spawning a file browser.
 *
 *	Usage: "file.browse"
 *
 */
 
#include <lx_plugin.hpp>
#include <lxu_command.hpp>
#include <lx_value.hpp>
#include <lx_command.hpp>
 
#define SERVER_NAME		"file.browse"
 
#define ARG_FILENAME		"filename"
#define ARGi_FILENAME		0
 
/*
 *	Disambiguate everything with a namespace. This isn't necessary,
 *	but it's good practice and allows generic names to be used for
 *	things like the Command class.
 */
 
namespace FileBrowse_Cmd
{
 
/*
 *	Implement the command class. This inherits from CLxBasicCommand,
 *	which is a wrapper class that does a lot of the heavy lifting
 *	when implementing a command.
 */
 
class Command : public CLxBasicCommand
{
	public:
		static void initialize ()
		{
			CLxGenericPolymorph		*srv;
 
			srv = new CLxPolymorph							<Command>;
			srv->AddInterface		(new CLxIfc_Command			<Command>);
			srv->AddInterface		(new CLxIfc_Attributes			<Command>);
			srv->AddInterface		(new CLxIfc_AttributesUI		<Command>);
			srv->AddInterface		(new CLxIfc_StaticDesc			<Command>);
 
			lx::AddServer			(SERVER_NAME, srv);
		}
 
		Command ();
 
		int		basic_CmdFlags		()					LXx_OVERRIDE;
		bool		basic_Enable		(CLxUser_Message &msg)			LXx_OVERRIDE;
		void		cmd_Interact		()					LXx_OVERRIDE;
		void		cmd_Execute		(unsigned int flags)			LXx_OVERRIDE;
 
		static LXtTagInfoDesc	descInfo[];
};
 
Command::Command ()
{
	/*
	 *	The constructor is a good place to add arguments and
	 *	set flags for those arguments. This command will have
	 *	a single argument for the filename. The flags will mark
	 *	the argument as optional. This will prevent modo from
	 *	launching a dialog to ask for a filename string and
	 *	instead allow the command to handle the missing argument
	 *	value by spawning a file dialog.
	 */
 
	dyna_Add (ARG_FILENAME, LXsTYPE_FILEPATH);
	basic_SetFlags (ARGi_FILENAME, LXfCMDARG_OPTIONAL);
}
 
int Command::basic_CmdFlags ()
{
	/*
	 *	The flags define if this should be an undoable command
	 *	or not. If the command changes the state of the scene,
	 *	then it should implement both the MODEL and UNDO flags.
	 */
 
	return LXfCMD_MODEL | LXfCMD_UNDO;
}
 
bool Command::basic_Enable (CLxUser_Message &msg)
{
	/*
	 *	In practice, a command usually has an enabled state and
	 *	a disabled state. This function allows you to return True
	 *	or False to enable/disable the command. A message interface
	 *	is provided to allow you to pass detailed information about
	 *	the enable state back to the user. This command is always
	 *	enabled.
	 */
 
	return true;
}
 
void Command::cmd_Interact ()
{
	/*
	 *	When the command is executed, this function is first called.
	 *	It's the ideal place to open a file dialog and ask for user
	 *	interaction. The resulting path can then be passed to the
	 *	commands execute method using the filename argument.
	 *
	 *	No scene or state altering code should be performed here.
	 */
 
	CLxUser_CommandService		cmd_svc;
	CLxUser_Command			command;
	CLxUser_ValueArray		val_array;
 
	LXtObjectID			obj = NULL;
	std::string			filename = "";
	unsigned			n = 0;
 
 
	/*
	 *	Check if the filename argument is set, if it is, return early.
	 */
 
	if (dyna_IsSet (ARGi_FILENAME))
		return;
 
	/*
	 *	Fire the commands to open the file dialog.
	 */
 
	cmd_svc.ExecuteArgString (-1, LXiCTAG_NULL, "dialog.setup fileOpen");
	cmd_svc.ExecuteArgString (-1, LXiCTAG_NULL, "dialog.title {Browse For Files...}");
	cmd_svc.ExecuteArgString (-1, LXiCTAG_NULL, "dialog.fileTypeCustom movie {Quicktime Movie} {*.mov;*.mp4} mov");
	cmd_svc.ExecuteArgString (-1, LXiCTAG_NULL, "dialog.open");
 
	/*
	 *	Spawn a command that can be queried for the result.
	 */
 
	if (LXx_FAIL (cmd_svc.NewCommand (command, "dialog.result")))
		return;
 
	/*
 	 *	Query the first argument on the dialog.result command
	 *	and store the results in a value array.
	 */
 
	if (LXx_FAIL (cmd_svc.QueryIndex (command, 0, val_array)))
		return;
 
	/*
	 *	Get the number of elements in the array. There should
	 *	only be one. If there are none, return early.
	 */
 
	n  = val_array.Count ();
 
	if (!n)
		return;
 
	/*
	 *	Read the string from the value array and set the filename
	 *	argument to the value of the string.
	 */
 
	val_array.String (0, filename);
	attr_SetString (ARGi_FILENAME, filename.c_str());
}
 
void Command::cmd_Execute (unsigned int flags)
{
	/*
	 *	As the name suggests, this is where the command is executed.
	 *	In this command, we won't actually do anything, other than
	 *	read the filename argument into a string.
	 */
 
	std::string			filename_arg = "";
 
	if (dyna_IsSet (ARGi_FILENAME))
		attr_GetString (ARGi_FILENAME, filename_arg);
}
 
void initialize ()
{
	Command :: initialize ();
}
 
LXtTagInfoDesc Command::descInfo[] = {
	{ 0 }
};
 
};	// End Namespace.
 
/*
 *	Initialize the servers.
 */
 
void initialize ()
{
	FileBrowse_Cmd :: initialize ();
}