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.
AlUserCommand::~AlUserCommand()
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.
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.
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::declareReferences()
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 )
int AlUserCommand::dagModified( AlDagNode *dag )
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.
int AlUserCommand::geometryModified( AlDagNode *dag )
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 )
int AlUserCommand::listModifiedDagNodes( const AlNotifyDagNode *dagMod, AlObject *obj )
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 )
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 )
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
}
statusCode AlUserCommand::retrieveWire( AlInput *input )
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
}
void *AlUserCommand::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().
For example,
switch( commandType() )
{
case myCommandType: .
myCommand *cmd = (myCommand *)asDerivedPtr();
....
}
The pointer is declared as follows
void * myDerivedCmd::asDerivedPtr() { return this; }
statusCode AlUserCommand::addConstructorRef( AlDagNode *dagNode )
statusCode AlUserCommand::addConstructorRef( AlCurveOnSurface *curveOnSurface )
statusCode AlUserCommand::addTargetRef( AlCurveOnSurface *curveOnSurface )