Encapsulates the user defined interface to command history.
#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;
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.
Used by the AlUserCommand::storeWire method to output the final data to the wire file. This method serves as a callback to output data.
< data - a pointer to the data to output
< size - the size of the data to output
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.
< objectPtr - the pointer that is referenced
Used by the AlUserCommand::retrieveWire method to input the command data from the wire file. This method serves as a callback to input data. Use the 'totalSize' argument of the retrieveWire method to determine the total size of the input data. This method is only valid during the 'retrieveWire' method. It will always fail during the resolveWire method.
> data - a pointer where to place the data
< size - the size of the data to retrieve
sSuccess - the data was retrieved
sFailure - there was no more data to retrieve
Returns the amount of data that has not been read. If this information is not available, then -1 will be returned.
Used by the AlUserCommand::resolveWire routine to resolve pointers to AlObjects. After a retrieve, pointers to data are not valid. This routine will give you a new pointer to replace the old one with. If the Alias object is no longer valid, then this routine will return NULL.
< objectPtr - the pointer that is referenced
Returns the parent command object. This may not be possible when the command is being initialized.
Default constructor for the user data for a command.
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 geomtery 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.
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 (e.g. 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.
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.
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.
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.
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.
< oldDag - the old DAG node to look for
< newDag - the new DAG node to replace it with
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 clalled 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.
< dag - the DAG node to update
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.
Called whenever the system modifies a curve on surface. If this command references the curve on surface parameter "surf", then it should return 1.
< surf - the curve on surface to check
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.
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, etc. 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.
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, etc. 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
}
sFailure - the method did not work
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
}
< data - the block of data for you to unpack
< size - the size of the data block
sFailure - the method did not work
After the wire file has been loaded, pointers to objects must be relocated to their new position in memory. For each pointer in your data structure, use the relocation methods to translate the pointers back into AlObjects. If you have forgotten to declare a reference when the file was saved, the resolved pointer will be NULL. For example,
myCmd:resolveWire( AlInput *wireIn )
{
replace the old pointer with the new one
myCmdData.AlDagNode = wireIn->resolveObject( myCmdData.AlDagNode );
}
sSuccess - the relocation worked
sFailure - the relocation failed
Outputs the command to an SDL file. This function is currently unused (it will never be called) and is present for future uses.
< outputSDL - the output file stream for the SDL file
sFailure - the method did not work
User definable type field to be used with asDerivedPtr()
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().
switch( commandType() )
{
case myCommandType: .
myCommand *cmd = (myCommand *)asDerivedPtr();
....
}
The pointer is declared as follows
void * myDerivedCmd::asDerivedPtr() { return this; }
Returns the name of the command, as specified when it was created.
Returns a wrapper to the first constructor reference.
Returns a wrapper to the first target reference.
Adds a reference to a DAG node to the constructor list. To be used by the declare method.
< dagNode - DAG node that is referenced
sSuccess - the reference was added
sInvalidArgument - dagNode was invalid
sFailure - the reference was not added
sInvalidObject - the command was not valid
Adds a reference to a curve on surface to the constructor list. To be used by the declare method.
< curveOnSurface - curve on surface that is referenced
sSuccess - the reference was added
sInvalidArgument - curveOnSurface was invalid
sFailure - the reference was not added
sInvalidObject - the command was not valid
Add a contact constructor to the constructor list. To be used by the declare method.
< dagNode - DAG node that is referenced
sSuccess - the reference was added
sInvalidArgument - dagNode or contact was invalid
sFailure - the reference was not added
sInvalidObject - the command was not valid
Adds a reference to a DAG node to the target list. To be used by the declare method.
< dagNode - DAG node that is referenced
sSuccess - the reference was added
sInvalidArgument - dagNode was invalid
sFailure - the reference was not added
sInvalidObject - the command was not valid
Adds a reference to a curve on surface to the target list. To be used by the declare method.
< curveOnSurface - curve on surface that is referenced
sSuccess - the reference was added
sInvalidArgument - curveOnSurface was invalid
sFailure - the reference was not added
sInvalidObject - the command was not valid
Adds a contact target to the target list. To be used by the declare method.
< dagNode - DAG node that is referenced
sSuccess - the reference was added
sInvalidArgument - dagNode or contact was invalid
sFailure - the reference was not added
sInvalidObject - the command was not valid
Deletes all reference from this command.
sInvalidObject - the current command is not valid
Returns TRUE if the given DAG node is a constructor of this command.
< dagNode - the DAG node in question
Returns TRUE if the given DAG node is a target of this command.
< 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
Returns TRUE if the given curve on surface is a constructor of this command.
< curveOnSurface - the curve on surface in question
Returns TRUE if the given curve on surface is a target of this command.
< curveOnSurface - the curve on surface in question