AlUserCommand
 
 
 

Encapsulates the user defined interface to command history.

Synopsis

#include <AlUserCommand.h>
class AlOutput
virtual statusCode output( const void *data, int size );
virtual statusCode declareObject( AlObject *obj );
class AlInput
virtual statusCode	input( void *data, int size );
virtual int	inputRemaining() const;
virtual AlObject*	resolveObject( AlObject *obj );
class AlUserCommand
// overloaded user functions
// do not call these directly or the command history may not be correctly
// maintained
//
virtual	~AlUserCommand();
virtual int	isValid();
virtual int	execute();
virtual int	declareReferences();
virtual int	instanceDag( AlDagNode *oldDag, AlDagNode *newDag );
virtual int	undo();
virtual int	dagModified( AlDagNode *dag );
virtual int	geometryModified( AlDagNode *dag );
virtual int	curveOnSurfaceModified( AlCurveOnSurface *surf );
virtual int  	listModifiedDagNodes( const AlNotifyDagNode *dagMod, AlObject *obj );
virtual int	debug( const char *prefix );
virtual void *	asDerivedPtr();
virtual statusCode	storeWire( AlOutput *output );
virtual statusCode	storeSDL( ofstream &outputSDL );
virtual statusCode 	retrieveWire( AlInput *input );
virtual statusCode	resolveWire( AlInput *input );
// for your own use
virtual int	type();
// general utility functions
const char *	name() const;
AlCommand *	command() const;
// declare utility functions
AlCommandRef*	firstConstructorRef();
statusCode	addConstructorRef( AlDagNode * );
statusCode	addConstructorRef( AlCurveOnSurface *);
statusCode	addConstructorContact( AlDagNode *, AlContact * );
AlCommandRef*	firstTargetRef();
statusCode	addTargetRef( AlDagNode * );
statusCode	addTargetRef( AlCurveOnSurface * );
statusCode	addTargetContact( AlDagNode *, AlContact * );
statusCode	deleteAllReferences();
boolean	isDagNodeAConstructor( AlDagNode * ) const;
boolean	isDagNodeATarget( AlDagNode *, boolean includeCOS = FALSE ) const;
boolean	isCurveOnSurfaceAConstructor( AlCurveOnSurface *) const;
boolean	isCurveOnSurfaceATarget( AlCurveOnSurface *) const;

Description

This class contains the definitions required to define a user command history command. The developer will be implementing many of these functions and must follow the return value conventions of this class.

statusCode AlOutput::declareObject( AlObject *objectPtr )

Description

Used by the calling routine to declare that it references an AlObject pointer in its private data so that it can use the AlInput::relocateObject to relocate an object on the retrieve.

Arguments

< objectPtr - the pointer that is referenced

Return Codes

sSuccess - the method worked

sFailure - the method failed.

AlData* resolveData( int type, int typeId )

AlObject *resolveObject()

Description

This method is used by the AlUserCommand class to resolve pointers to AlObjects. Object resolution must be performed in the same order as object declaration. This preserves the object types that will be saved in the command.

AlCommand *AlUserCommand::command() const

Description

Returns the parent command object. This may not be possible when the command is being initialized.

AlUserCommand::AlUserCommand()

Description

Default constructor for the user data for a command.

AlUserCommand::~AlUserCommand()

Description

A default destructor for the user command. This method is called whenever the command is about to be freed. It is the responsibility of this function to free all of the data contained in the command, including lists and geometry used locally. Care should be taken not to free data that is referenced elsewhere; for instance, in the DAG. This routine should only free data that is not referenced elsewhere.

int AlUserCommand::isValid()

Description

Used to determine if a command is valid by returning a value. Examples of a command being invalid are: essential DAG pointers becoming NULL, input out of range or the geometry that this command depends on being modified in such a way that this command is no longer valid (for example, curve CVs are deleted until there are fewer than one span). The function returns 0 if the command is valid; otherwise, a non zero value indicates what is wrong with it. These values are defined by the specific command. An invalid command is freed when it is executed during an update of the construction history list. It can be freed when executing it explicitly if the execute function is told to do so.

int AlUserCommand::execute()

Description

Called when the command should be executed. Before this function is executed, the isValid() method is called to ensure that the command is valid. Invalid commands are not executed. Most commands may behave differently if they are being called for the first time. For example, the fillet command saves a reference to a DAG node on the first call. If the command is re-executed, the previous DAG node pointer is used instead of the new one. This method returns 0 on success and non-zero on failure.

int AlUserCommand::undo()

Description

Undoes what is done by the execution of the command. This may require the original execution of the command to record the state of the model before execution. It is valid not to define this method. This method returns 0 on success and non-zero on failure.

int AlUserCommand::declareReferences()

Description

Appends constructor and target references to the command for each reference that it makes to the geometry in the model. Use the command() method to find the parent command. From the parent command, use the addTargetRef() and addConstructorRef() methods to create references to the geometry. The command system may dynamically free all references and ask the declareReferences() method to rebuild the list. It is very important that every reference be declared. Failing to do so may result in unpredictable behaviour in the user interface. This method returns 0 on success and non-zero on failure.

int AlUserCommand::instanceDag( AlDagNode *oldDag, AlDagNode *newDag )

Description

Changes all references to oldDag to newDag. This may involve walking the reference list for this command and changing the DAG node pointers to point to the new DAG node. This method returns 0 on success and non-zero on failure.

Arguments

< oldDag - the old DAG node to look for

< newDag - the new DAG node to replace it with

int AlUserCommand::dagModified( AlDagNode *dag )

Description

Called whenever the DAG node passed in is modified. This usually means a transformation in the DAG node has changed. This function will only be called if the DAG node is present in the reference list for the command. Some commands do not need to implement this function, since they may only be required to execute after the DAG is modified. Only implement this command if the command block needs to be updated when the DAG is modified. It is valid not to define this method. This method returns 0 on success and non-zero on failure.

Arguments

< dag - the DAG node to update

int AlUserCommand::geometryModified( AlDagNode *dag )

Description

Called when the geometry beneath the DAG node is modified. An example is moving a CV’s position or deleting a CV. Only implement this function if there is something that must be updated in the command block when the geometry on a DAG node is transformed. An example of this is a command that creates a local copy of the constructor geometry. If the local copy is not updated when the original is, then when the command is re-executed, the correct result will not appear. This method returns 0 on success and non-zero on failure.

Note: This command, as well as dagModified(), should not rely on the geometry of the constructor being in a stable state. It is valid not to define this method.

int AlUserCommand::curveOnSurfaceModified( AlCurveOnSurface *surf )

Description

Called whenever the system modifies a curve on surface. If this command references the curve on surface parameter "surf", then it should return 1.

Arguments

< surf - the curve on surface to check

int AlUserCommand::listModifiedDagNodes( const AlNotifyDagNode *dagMod, AlObject *obj )

Description

Notifies Alias of any DAG nodes that will be modified if the given object is changed. The code fragment for the function will resemble the following:

     int myCmd::listModifiedDagNodes( dagMod, AlObject *obj )
     {
         for each dag node ’adag’ which will be affected when ’obj’ is modified
         {
             dagMod->notify( adag );
         }
     }
    

It is valid not to define this method. This method returns 0 on success and non-zero on failure.

int AlUserCommand::debug( const char *prefix )

Description

Used for debugging purposes. This method should print out any relevant debugging information for this command and would be called from the implemented methods of AlUserCommand of the construction history plug-in. For each output line, print out the string in ’prefix’ first. It will contain spacing information, and so on. It is valid not to define this method. For example,

    
     int myCmd::debug( const char *prefix )
     {
	cerr << prefix << "The command contains" << this->myValue << cend;
	cerr << prefix << "and the value " << this->myOtherValue << cend;
	return 0;
     }

This method returns 0 on success and non-zero on failure.

statusCode AlUserCommand::storeWire( AlOutput *output )

Description

Outputs the contents of the command to be stored in the output Wire file. This function returns sSuccess if it was successful. The function is passed a memory stream to write the contents of the command to. OpenAlias will use the name() method to denote the command identifier to label this data chunk with. It is valid to call the AlOutput->output() multiple times. This method must be defined for objects to save correctly. Do not write the AlUserCommand structure out directly to disk. This will also write out virtual table pointers, and so on. First create a private data class which contains the data which will be written out to the wire file. Make your derived object inherit this private data class, then write out its portion instead. For example,

     class myCmdData
     {
         this will enable us to get a pointer to the myCmdData
         section of our derived structure
         myCmdData   *cmdDataPtr()   { return this; }
     public:   .
         AlDagNode *dag1;
         double value;
     };
     class myCmd : public AlUserCommand, public myCmdData
     {
         ...
     public:   .
         double MiscData;
     }
    
     myCmd:storeWire( AlOutput *wireOut )
     {
         wireOut->output( cmdDataPtr(), sizeof( myCmdData ) );
         wireOut->declareObject( myCmdData->dag1 );
         wireOut->output( &MiscData, sizeof( MiscData );
    
         final data is written to disk when we return
     }

Arguments

< output - the output method

Return Codes

sFailure - the method did not work

sSuccess - the method worked

statusCode AlUserCommand::retrieveWire( AlInput *input )

Description

Unpacks the current command from the wire file. Returns sSuccess if the method worked. Note that the command() method may return NULL at this point in time. (It will be valid after the entire file has been loaded.) The retrieveWire routine is almost identical to the retrieve routine. For example,

     myCmd:retrieveWire( AlInput *wireIn )
     {
         wireIn->input( cmdDataPtr(), sizeof( myCmdData ) );
         wireIn->input( &MiscData, sizeof( MiscData );
        
         Note that we do not worry about AlObject pointers until later
     }

Arguments

< data - the block of data for you to unpack

< size - the size of the data block

Return Codes

sFailure - the method did not work

sSuccess - the method worked

statusCode AlUserCommand::storeSDL( ofstream &outputSDL )

Description

Outputs the command to an SDL file. This function is currently unused (it will never be called) and is present for future uses.

Arguments

< outputSDL - the output file stream for the SDL file

Return Codes

sFailure - the method did not work

sSuccess - the method worked

int AlUserCommand::type()

Description

User definable type field to be used with asDerivedPtr()

void *AlUserCommand::asDerivedPtr()

Description

Provided for safe downcasting to your derived type, so no assumptions of the location of the derived data need to be made. Use this method in conjunction with the commandType().

For example,

switch( commandType() )
     {
         case myCommandType:     .
             myCommand *cmd = (myCommand *)asDerivedPtr();
             ....
     }
    
     The pointer is declared as follows
    
     void * myDerivedCmd::asDerivedPtr() { return this; }

const char *AlUserCommand::name() const

Description

Returns the name of the command, as specified when it was created.

AlCommandRef* AlUserCommand::firstConstructorRef()

Description

Returns a wrapper to the first constructor reference.

AlCommandRef* AlUserCommand::firstTargetRef()

Description

Returns a wrapper to the first target reference.

statusCode AlUserCommand::addConstructorRef( AlDagNode *dagNode )

Description

Adds a reference to a DAG node to the constructor list. To be used by the declare method.

Arguments

< dagNode - DAG node that is referenced

Return Codes

sSuccess - the reference was added

sInvalidArgument - dagNode was invalid

sFailure - the reference was not added

sInvalidObject - the command was not valid

statusCode AlUserCommand::addConstructorRef( AlCurveOnSurface *curveOnSurface )

Description

Adds a reference to a curve on surface to the constructor list. To be used by the declare method.

Arguments

< curveOnSurface - curve on surface that is referenced

Return Codes

sSuccess - the reference was added

sInvalidArgument - curveOnSurface was invalid

sFailure - the reference was not added

sInvalidObject - the command was not valid

statusCode AlUserCommand::addConstructorContact( AlDagNode *dagNode, AlContact *contact )

Description

Add a contact constructor to the constructor list. To be used by the declare method.

Arguments

< dagNode - DAG node that is referenced

< contact - the contact

Return Codes

sSuccess - the reference was added

sInvalidArgument - dagNode or contact was invalid

sFailure - the reference was not added

sInvalidObject - the command was not valid

statusCode AlUserCommand::addTargetRef( AlDagNode *dagNode )

Description

Adds a reference to a DAG node to the target list. To be used by the declare method.

Arguments

< dagNode - DAG node that is referenced

Return Codes

sSuccess - the reference was added

sInvalidArgument - dagNode was invalid

sFailure - the reference was not added

sInvalidObject - the command was not valid

statusCode AlUserCommand::addTargetRef( AlCurveOnSurface *curveOnSurface )

Description

Adds a reference to a curve on surface to the target list. To be used by the declare method.

Arguments

< curveOnSurface - curve on surface that is referenced

Return Codes

sSuccess - the reference was added

sInvalidArgument - curveOnSurface was invalid

sFailure - the reference was not added

sInvalidObject - the command was not valid

statusCode AlUserCommand::addTargetContact( AlDagNode *dagNode, AlContact *contact )

Description

Adds a contact target to the target list. To be used by the declare method.

Arguments

< dagNode - DAG node that is referenced

< contact - the contact

Return Codes

sSuccess - the reference was added

sInvalidArgument - dagNode or contact was invalid

sFailure - the reference was not added

sInvalidObject - the command was not valid

statusCode AlUserCommand::deleteAllReferences()

Description

Deletes all reference from this command.

Return Codes

sSuccess - the command worked

sInvalidObject - the current command is not valid

boolean AlUserCommand::isDagNodeAConstructor( AlDagNode* dagNode ) const

Description

Returns TRUE if the given DAG node is a constructor of this command.

Arguments

< dagNode - the DAG node in question

boolean AlUserCommand::isDagNodeATarget( AlDagNode* dagNode, boolean includeCoS ) const

Description

Returns TRUE if the given DAG node is a target of this command.

Arguments

< dagNode - the DAG node in question

< includeCoS - if TRUE, also consider curves on surface which are children of the DAG node to be part of the DAG node

boolean AlUserCommand::isCurveOnSurfaceAConstructor( AlCurveOnSurface* curveOnSurface ) const

Description

Returns TRUE if the given curve on surface is a constructor of this command.

Arguments

< curveOnSurface - the curve on surface in question

boolean AlUserCommand::isCurveOnSurfaceATarget( AlCurveOnSurface* curveOnSurface ) const

Description

Returns TRUE if the given curve on surface is a target of this command.

Arguments

< curveOnSurface - the curve on surface in question