Commands Manual
maxon::CommandClassInterface is a base interface for standardized commands. Such a command operates solely on the given input data and can be used in various situations.
A custom command must implement these two methods:
An implementation for such a data object must be based on maxon::CommandDataInterface which in return in based on maxon::DataDictionaryObjectInterface .
Interactive commands (e.g. tools) can also implement maxon::CommandInteractionClassInterface :
//------------------------------------------------------------------------------ // Simple data //------------------------------------------------------------------------------ class ExampleDataImpl : public 组件 <ExampleDataImpl, CommandDataInterface> { MAXON_COMPONENT ( NORMAL , DataDictionaryObjectClass);
// register data MAXON_COMPONENT_CLASS_REGISTER (ExampleDataImpl, CommandDataClasses, "net.maxonexample.commanddata.exampledata" );
//------------------------------------------------------------------------------ // Simple command //------------------------------------------------------------------------------ class ExampleCommandImpl : public 组件 <ExampleCommandImpl, CommandClassInterface> { MAXON_COMPONENT (); public : MAXON_METHOD Result<COMMANDSTATE> GetState(CommandDataRef& data) const { return maxon::COMMANDSTATE::ENABLED ; } MAXON_METHOD Result<COMMANDRESULT> Execute(CommandDataRef& data) const { iferr_scope ; const COMMANDSTATE commandState = self .GetState(data) iferr_return ; if (commandState != COMMANDSTATE::ENABLED ) return COMMANDRESULT::SKIP ;
// get data from context const maxon::Int32 valueA = data.Get< maxon::Int32 >(0) iferr_return ; const maxon::Int32 valueB = data.Get< maxon::Int32 >(1) iferr_return ;
// perform command const maxon::Int32 res = valueA + valueB;
// store result in the context data.Set(2, res) iferr_return ; return maxon::COMMANDRESULT::OK ; } };
// register command MAXON_COMPONENT_OBJECT_REGISTER (ExampleCommandImpl, CommandClasses, "net.maxonexample.command.addition" );
Some classic data types like BaseContainer cannot be stored in a maxon::DataDictionary. Therefore a custom data class is needed to store specific custom data. Such a data class can be implemented based on maxon::LegacyCommandDataInterface :
maxon::LegacyCommandClassInterface is based on maxon::CommandClassInterface . It can be implemented if custom data should be handled.
// This example shows the implementation of a simple command that handles "legacy" data.
//------------------------------------------------------------------------------ // MoGraph setup data //------------------------------------------------------------------------------ class MoGraphSetupDataImpl : public 组件 <MoGraphSetupDataImpl, LegacyCommandDataInterface> { MAXON_COMPONENT ( NORMAL , DataDictionaryObjectClass); public : MAXON_METHOD Int GetLegacyDataCount() const { return 1; } MAXON_METHOD Result<Generic*> GetLegacyData( Int index) { Generic* const dtaPtr = reinterpret_cast< Generic* > (&_data); return dtaPtr; } MAXON_METHOD Result<void> SetLegacyData( const Generic* data, Int index) { iferr_scope ; if (data == nullptr ) return maxon::NullptrError( MAXON_SOURCE_LOCATION ); const MoGraphSetupData* const moGraphData = reinterpret_cast< const MoGraphSetupData* > (data); _data.CopyFrom(*moGraphData) iferr_return ; return OK ; } MAXON_METHOD Result<void> SetData(ForwardingDataPtr&& key, Data&& data) { return super.SetData(std::move(key), std::move(data)); } MAXON_METHOD Result<Data> GetData( const ConstDataPtr& key) const { return super.GetData(std::move(key)); } private : MoGraphSetupData _data; };
//------------------------------------------------------------------------------ // register data //------------------------------------------------------------------------------ MAXON_COMPONENT_CLASS_REGISTER (MoGraphSetupDataImpl, LegacyCommandDataClasses, "net.maxonexample.legacycommanddata.mographsetup" );
//------------------------------------------------------------------------------ // MoGraph setup command. Creates a cloner and uses the given object as input. //------------------------------------------------------------------------------ class MoGraphSetupCommandImpl : public 组件 <MoGraphSetupCommandImpl, CommandClassInterface> { MAXON_COMPONENT (); public : MAXON_METHOD Result<COMMANDSTATE> GetState(CommandDataRef& data) const { return maxon::COMMANDSTATE::ENABLED ; } MAXON_METHOD Result<COMMANDRESULT> Execute(CommandDataRef& data) const { iferr_scope ; const COMMANDSTATE commandState = self .GetState(data) iferr_return ; if (commandState != COMMANDSTATE::ENABLED ) return COMMANDRESULT::SKIP ;
// get and check input data LegacyCommandDataRef legacyData = Cast<LegacyCommandDataRef>(data); const maxon::Int dataIndex = 0; MoGraphSetupData& moData = legacyData.GetLegacyData<MoGraphSetupData>(dataIndex) iferr_return ; if (moData._doc == nullptr ) return maxon::NullptrError( MAXON_SOURCE_LOCATION );
// check for object if (moData._object == nullptr ) { // if no object is given, use the active object BaseObject * const activeObject = moData._doc->GetActiveObject(); // if no object is active, there is nothing to do if (activeObject == nullptr ) return COMMANDRESULT::SKIP ; moData._object = activeObject; }
// create cloner BaseObject * const cloner = BaseObject::Alloc (1018544); if (cloner == nullptr ) return maxon::OutOfMemoryError( MAXON_SOURCE_LOCATION ); moData._doc->InsertObject(cloner, nullptr , nullptr ); // place the object under the cloner moData._object->Remove(); moData._doc->InsertObject(moData._object, cloner, nullptr );
// store result moData._cloner = cloner; return maxon::COMMANDRESULT::OK ; } };
//------------------------------------------------------------------------------ // register command //------------------------------------------------------------------------------ MAXON_COMPONENT_OBJECT_REGISTER (MoGraphSetupCommandImpl, CommandClasses, "net.maxonexample.command.mographsetup" );
The data a command operates on is stored in a data object. A default data implementation is stored at maxon::CommandDataClasses::BASE. A custom data class can be implemented based on:
A given command can be executed by calling the "Invoke" of the data object.
// This example shows the declarations of published objects // giving access to the data and command implementations namespace CommandDataClasses { // example data MAXON_DECLARATION (CommandDataClasses::EntryType, EXAMPLEDATA, "net.maxonexample.commanddata.exampledata" ); } namespace CommandClasses { // example command MAXON_DECLARATION (CommandClasses::EntryType, EXAMPLE, "net.maxonexample.command.addition" ); // MoGraph setup command. Must be used with MOGRAPHSETUPDATA. MAXON_DECLARATION (CommandClasses::EntryType, MOGRAPHSETUP, "net.maxonexample.command.mographsetup" ); } namespace LegacyCommandDataClasses { // MoGraph setup data for MOGRAPHSETUP command MAXON_DECLARATION (LegacyCommandDataClasses::EntryType, MOGRAPHSETUPDATA, "net.maxonexample.legacycommanddata.mographsetup" ); }// This example creates an example data and calls the example command.
// create data maxon::CommandDataRef data = maxon::CommandDataClasses::EXAMPLEDATA().Create() iferr_return ; data.Set(0, maxon::Int32 (100)) iferr_return ; data.Set(1, maxon::Int32 (200)) iferr_return ;
// invoke command const auto command = maxon::CommandClasses::EXAMPLE(); const maxon::COMMANDRESULT res = data.Invoke(command, false ) iferr_return ; if (res != maxon::COMMANDRESULT::OK ) return maxon::OK ;
// get result const maxon::Int32 resultValue = data.Get< maxon::Int32 >(2) iferr_return ; DiagnosticOutput ( "Result: @" , resultValue);
// This example creates a specific data for the given command, // calls that command and receives the resulting object.
// prepare mograph data // no object is set; the active object of the given document should be used MoGraphSetupData data; data._doc = doc; data._object = nullptr ; const maxon::Int dataIndex = 0;
// create data maxon::LegacyCommandDataRef legacyData = maxon::LegacyCommandDataClasses::MOGRAPHSETUPDATA().Create() iferr_return ; legacyData.SetLegacyData<MoGraphSetupData>(data, dataIndex) iferr_return ;
// invoke command const auto command = maxon::CommandClasses::MOGRAPHSETUP(); const maxon::COMMANDRESULT res = legacyData.Invoke(command, false ) iferr_return ; if (res != maxon::COMMANDRESULT::OK ) return maxon::OK ;
// get result const MoGraphSetupData result = legacyData.GetLegacyData<MoGraphSetupData>(dataIndex) iferr_return ; result._cloner->SetName( "The New Cloner" _s);