/*
Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/
/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include "ProToolkit.h"
#include "ProMenu.h"
#include "ProSelection.h"
#include "ProModelitem.h"
#include "ProMdl.h"
#include "ProArray.h"
#include "ProUtil.h"
#include "ProAnimate.h"
#include "ProTKRunTime.h"
/*--------------------------------------------------------------------*\
Pro/DEVELOP includes
\*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*\
C System includes
\*--------------------------------------------------------------------*/
#include <math.h>
/*--------------------------------------------------------------------*\
Application includes
\*--------------------------------------------------------------------*/
#include "TestError.h"
#include "TestAnimation.h"
#include "UtilMessage.h"
#include "UtilString.h"
#include "UtilCollect.h"
/*--------------------------------------------------------------------*\
Macros
\*--------------------------------------------------------------------*/
#define ANI_OBJECT( i, f ) (ani_obj_seq[i].anims[f])
#define PI (3.1451)
#define MAX_FRAMES_NUM 30
/*--------------------------------------------------------------------*\
Data types
\*--------------------------------------------------------------------*/
/*---------------------------------------------------------------*\
This structure contains information about animation objects
associated with the model. Macro ANI_OBJECT(i,f) is used to
get animation object handle (ProAnimObj) of the model i in
the frame f.
\*---------------------------------------------------------------*/
typedef struct tag_AniObjectInstance
{
ProMdl model; /* Handle to the animated model */
ProAsmcomppath comp_path; /* Component path of the object */
ProAnimObj anims[ MAX_FRAMES_NUM ]; /* Array of the ani objs */
} AniObjectInstance;
/*--------------------------------------------------------------------*\
Application global/external data
\*--------------------------------------------------------------------*/
static AniObjectInstance* ani_obj_seq = NULL; /* Array of of ani objs */
static int n_objects = 0; /* Current number of ani objs */
#if 0
static ProAnimFrame frames[ MAX_FRAMES_NUM ]; /* Animation frames */
#endif
static ProAnimFrame *frames; /* Animation frames */
static int n_frames; /* Current number of frames */
/*---------------------------------------------------------------------*\
Functions declaration
\*---------------------------------------------------------------------*/
ProError ProUtilSelectedMdlGet( ProSelection* , ProMdl* );
ProError ProUtilAniObjectSelect( char option[], ProSelection**,
AniObjectInstance* );
ProBoolean ProUtilMdlEqual( ProMdl, ProMdl );
int ProUtilAniObjectFind( ProArray, AniObjectInstance );
ProError ProUtilAniObjectInstanceInit( ProSelection**, AniObjectInstance* );
ProError ProTestBatchAnimAct( ProAnimFrame, int, ProAppData );
void ProUtilRotX( double angle, ProMatrix mx );
/*---------------------------------------------------------------------*\
Function: ProTestAnimation()
Purpose: Top-level function. Initialize some data,
create and run ANIMATION menu, then free used resources.
Returns: 0 - success; -1 - error. Now ignored.
\*---------------------------------------------------------------------*/
int ProTestAnimation( void* p_dummy, int int_dummy )
{
ProError status;
int menu_id; /* The identifier of the created menu */
int action;
/* Init the array of animation objects */
n_objects = 0;
status = ProArrayAlloc( 0, sizeof(AniObjectInstance), 1, (ProArray *)&ani_obj_seq );
TEST_CALL_REPORT( "ProArrayAlloc()", "ProTestAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
/* Init the array of animation frames */
n_frames = 0;
status = ProArrayAlloc( 0, sizeof(ProAnimFrame), 1, (ProArray *)&frames );
TEST_CALL_REPORT( "ProArrayAlloc()", "ProTestAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
status = ProArraySizeSet( (ProArray *)&frames, MAX_FRAMES_NUM );
TEST_CALL_REPORT( "ProArraySizeSet()", "ProTestAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
/*-----------------------------*\
Create new menu ANIMATION
\*-----------------------------*/
/* Load base menu from file */
status = ProMenuFileRegister((char *)"Animation", (char *)"tkanim.mnu",
&menu_id );
TEST_CALL_REPORT( "ProMenuFileRegister()", "ProTestAnimation()",
status, status != PRO_TK_NO_ERROR );
/* Define menu buttons */
ProMenubuttonActionSet((char *)"Animation", (char *)"Create",
(ProMenubuttonAction)ProTestAnimframeCreate, NULL, 0 );
ProMenubuttonActionSet((char *)"Animation", (char *)"Delete",
(ProMenubuttonAction)ProTestAnimframeDelete, NULL, 0 );
ProMenubuttonActionSet((char *)"Animation", (char *)"AddObject",
(ProMenubuttonAction)ProTestAniObjectAdd, NULL, 0 );
ProMenubuttonActionSet((char *)"Animation", (char *)"DeleteObject",
(ProMenubuttonAction)ProTestSelAniObjectDelete, NULL, 0 );
ProMenubuttonActionSet((char *)"Animation", (char *)"PlaySingle",
(ProMenubuttonAction)ProTestSingleAnimation, NULL, 0 );
ProMenubuttonActionSet((char *)"Animation", (char *)"PlayBatch",
(ProMenubuttonAction)ProTestBatchAnimation, NULL, 0 );
ProMenubuttonActionSet((char *)"Animation", (char *)"Animation",
(ProMenubuttonAction)ProMenuDelete, NULL, 0 );
/*-----------------------*\
Run menu ANIMATION
\*-----------------------*/
status = ProMenuCreate( PROMENUTYPE_MAIN, (char *)"Animation", &menu_id );
TEST_CALL_REPORT( "ProMenuCreate()", "ProTestAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status == PRO_TK_NO_ERROR )
{
status = ProMenuProcess( (char *)"Animation", &action );
TEST_CALL_REPORT( "ProMenuProcess()", "ProTestAnimation()",
status, status != PRO_TK_NO_ERROR );
}
status = ProArrayFree( (ProArray *)&ani_obj_seq );
TEST_CALL_REPORT( "ProArrayFree()", "ProTestAnimation()",
status, status != PRO_TK_NO_ERROR );
n_objects = 0;
status = ProArrayFree( (ProArray *)&frames );
TEST_CALL_REPORT( "ProArrayFree()", "ProTestAnimation()",
status, status != PRO_TK_NO_ERROR );
n_frames = 0;
return 0;
}
/*---------------------------------------------------------------------*\
Function: ProTestAnimframeCreate()
Purpose: On-button function. Initialize frames sequence structure.
Returns: 0 - success; -1 - error. Now ignored.
\*---------------------------------------------------------------------*/
int ProTestAnimframeCreate( void* p_dummy, int int_dummy )
{
ProError status;
int i;
ProMatrix m_frame_view = {
{1.0, 0.0, 0.0, 0.0},
{0.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 1.0, 0.0},
{0.0, 0.0, 0.0, 1.0}
};
ProVector v_x = {1.0, 0.0, 0.0};
ProVector v_y = {0.0, 1.0, 0.0};
ProVector v_z = {0.0, 0.0, 1.0};
ProPoint3d origin = {0.0, 0.0, 1.0};
/* Check animation frames */
if( n_frames > 0 )
{
ProUtilMsgPrint( "gen", "TEST %0s", "Animation already exists" );
return -1;
}
/* Get a number of frames */
ProUtilMsgPrint( "gen", "TEST %0s", "Enter a number of frames: " );
if( !ProUtilIntGet( NULL, NULL, &n_frames ) )
n_frames = MAX_FRAMES_NUM;
if( n_frames > MAX_FRAMES_NUM )
n_frames = MAX_FRAMES_NUM;
/* Init the frame view matrix */
status = ProMatrixInit( v_x, v_y, v_z, origin, m_frame_view );
TEST_CALL_REPORT( "ProMatrixInit()", "ProTestAnimframeCreate()",
status, status != PRO_TK_NO_ERROR );
/* Initialize the frames */
for( i=0; i<n_frames; i++ )
{
status = ProAnimframeCreate( m_frame_view, &(frames[i]) );
TEST_CALL_REPORT( "ProAnimframeCreate()", "ProTestAnimframeCreate()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
}
return 0; /* Upon success */
}
/*---------------------------------------------------------------------*\
Function: ProTestAnimframeDelete()
Purpose: On-button function. Remove animation objects from the frames,
delete animation frames and free an array of the handles of
the frames.
Returns: 0 - success; -1 - error. Now ignored.
Note: Arguments are ignored.
\*---------------------------------------------------------------------*/
int ProTestAnimframeDelete( void* p_dummy, int int_dummy )
{
ProError status;
int i;
/* Check animation frames */
if( n_frames < 1 )
return -1;
/* Delete the animation objects */
for( i=n_objects-1; i>=0; i-- )
ProTestAniObjectDelete( i );
/* Delete animation frames */
for( i=0; i<n_frames; i++ )
{
status = ProAnimframeDelete( frames[i] );
TEST_CALL_REPORT( "ProAnimframeDelete()", "ProTestAnimframeDelete()",
status, status != PRO_TK_NO_ERROR );
}
n_frames = 0;
return 0;
}
/*---------------------------------------------------------------------*\
Function: ProTestAniObjectAdd()
Purpose: On-button function. Select an animation object and add it
to the animation frames.
Returns: 0 - success; -1 - error. Now ignored.
Note: Arguments are ignored.
\*---------------------------------------------------------------------*/
int ProTestAniObjectAdd( void* p_dummy, int int_dummy )
{
ProError status;
ProSelection* p_selection;
AniObjectInstance ani_object; /* Created animation object */
int i_frame;
double angle;
double add_angle;
ProMode mode;
ProMatrix m_transform = {
{1.0, 0.0, 0.0, 0.0},
{0.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 1.0, 0.0},
{0.0, 0.0, 0.0, 1.0}
};
/* Check animation frames */
if( n_frames < 1 )
{
ProUtilMsgPrint( "gen", "TEST %0s", "First, create an animation" );
return -1;
}
/* Select ONE element to animate */
status = ProUtilAniObjectSelect( (char *)"prt_or_asm", &p_selection, &ani_object );
if( status == PRO_TK_USER_ABORT )
return -1;
if( status != PRO_TK_E_NOT_FOUND )
{
/* User have selected already animated object */
ProUtilMsgPrint( "gen", "TEST %0s", "The item is already animated" );
return -1;
}
/* Insert object to the array of the animated elements */
status = ProArrayObjectAdd( (ProArray *)&ani_obj_seq, 0, 1, (void*)&ani_object );
TEST_CALL_REPORT( "ProArrayObjectAdd()", "ProTestAniObjectAdd()",
status, status != PRO_TK_NO_ERROR );
if( status == PRO_TK_NO_ERROR )
n_objects++;
else
return -1;
status = ProModeCurrentGet(&mode);
TEST_CALL_REPORT( "ProModeCurrentGet()", "ProTestAniObjectAdd()",
status, status != PRO_TK_NO_ERROR );
if (mode == PRO_MODE_ASSEMBLY)
{
/* Retrieve the transformation matrix */
status = ProAsmcomppathTrfGet( &ani_obj_seq[0].comp_path,
PRO_B_TRUE, m_transform );
TEST_CALL_REPORT( "ProAsmcomppathTrfGet()", "ProTestAniObjectAdd()",
status, status != PRO_TK_NO_ERROR );
/* Assign the transformation matrix. Used for test only */
status = ProAsmcomppathTrfSet( &ani_obj_seq[0].comp_path,
PRO_B_TRUE, m_transform );
TEST_CALL_REPORT( "ProAsmcomppathTrfSet()", "ProTestAniObjectAdd()",
status, status != PRO_TK_NO_ERROR );
}
/* Init rotate angle */
angle = 0.0;
add_angle = 360.0 / (double)n_frames;
/* Create animation objects and add it to the frames */
for( i_frame=0; i_frame<n_frames; i_frame++ )
{
/* Add rotation to the transformation matrix */
angle += add_angle;
ProUtilRotX( angle, m_transform );
/* Create an animation object... */
status = ProAnimobjectCreate( *p_selection, m_transform,
&ANI_OBJECT(0, i_frame) );
TEST_CALL_REPORT( "ProAnimobjectCreate()", "ProTestAniObjectAdd()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
/* ...and add it to the frame */
status = ProAnimframeObjAdd( frames[i_frame], ANI_OBJECT(0, i_frame) );
TEST_CALL_REPORT( "ProAnimframeObjAdd()", "ProTestAniObjectAdd()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
}
return 0;
}
/*---------------------------------------------------------------------*\
Function: ProTestSelAniObjectDelete()
Purpose: On-button function. Select ani object and delete it.
Returns: 0 - success; -1 - error. Now ignored.
Note: Arguments are ignored.
\*---------------------------------------------------------------------*/
int ProTestSelAniObjectDelete( void* p_dummy, int int_dummy )
{
ProSelection* p_selection;
int i_obj;
/* Select an animation object */
i_obj = ProUtilAniObjectSelect( (char *)"prt_or_asm", &p_selection, NULL );
if( i_obj < PRO_TK_NO_ERROR )
{
ProUtilMsgPrint( "gen", "TEST %0s", "Invalid selection" );
return -1;
}
/* Delete specified animation object */
if( ProTestAniObjectDelete( i_obj ) != PRO_TK_NO_ERROR )
return -1;
else
return 0;
}
/*---------------------------------------------------------------------*\
Function: ProTestAniObjectDelete()
Purpose: Delete specified animation object
and removes it from the array..
Returns: 0 - success; -1 - error. Now ignored.
Note: Arguments are ignored.
\*---------------------------------------------------------------------*/
int ProTestAniObjectDelete(
int i_obj ) /* (In) The object index in the sequence of the ani
objects */
{
ProError status;
int i_frame;
/* Check index */
if( (i_obj < 0) || (i_obj >= n_objects) )
return -1;
/* Delete the animation objects */
for( i_frame=0; i_frame<n_frames; i_frame++ )
{
/* Remove the animation object from the frame */
status = ProAnimframeObjRemove( frames[i_frame],
ANI_OBJECT(i_obj, i_frame) );
TEST_CALL_REPORT( "ProAnimframeObjRemove()",
"ProTestAniObjectDelete()",
status, status != PRO_TK_NO_ERROR );
/* Delete the animation object */
status = ProAnimobjectDelete( ANI_OBJECT(i_obj, i_frame) );
TEST_CALL_REPORT( "ProAnimobjectDelete()", "ProTestAniObjectDelete()",
status, status != PRO_TK_NO_ERROR );
}
/* Remove the animation object from the array */
status = ProArrayObjectRemove( (ProArray *)&ani_obj_seq, i_obj, 1 );
TEST_CALL_REPORT( "ProArrayObjectRemove()", "ProTestAniObjectDelete()",
status, status != PRO_TK_NO_ERROR );
if( status == PRO_TK_NO_ERROR )
n_objects--;
else
return -1;
return 0;
}
/*---------------------------------------------------------------------*\
Function: ProTestSingleAnimationAct()
Purpose: This is the generic function for visiting animation objects.
Returns: 1 - success;
Note: I also use this function as a filter one.
\*---------------------------------------------------------------------*/
ProError ProTestSingleAnimAct(
ProAnimObj ani_object, /* (In) The handle to the animation object */
ProAppData app_data ) /* (In) The pointer to the frame number */
{
TEST_CALL_REPORT ("ProAnimObjAct()","ProTestSingleAnimAct()", PRO_TK_NO_ERROR, 0);
if( app_data != NULL )
{
ProTKPrintf( "Single frame %d, object %X\n", *(int*)app_data, ani_object );
}
return PRO_TK_NO_ERROR;
}
/*---------------------------------------------------------------------*\
Function: ProTestSingleAnimation()
Purpose: On-button function.
Returns: 0 - success; -1 - error. Now ignored.
Note: Arguments are ignored.
\*---------------------------------------------------------------------*/
int ProTestSingleAnimation( void* p_dummy, int int_dummy )
{
ProError status;
ProSingleAnim single_animation;
int i_frame;
int i_obj;
ProAnimObj *anim_objects;
int anim_obj_num, i;
/* Check animation frames */
if( n_frames < 1 )
{
ProUtilMsgPrint( "gen", "TEST %0s", "First, create an animation" );
return -1;
}
/* At least one animation object must exist */
if( n_objects < 1 )
{
ProUtilMsgPrint( "gen", "TEST %0s", "First, add objects to animate" );
return -1;
}
/* Initialize an animation in single mode. */
status = ProSingleAnimationInit( ani_obj_seq[0].model,
frames[0], &single_animation );
TEST_CALL_REPORT( "ProSingleAnimationInit()", "ProTestSingleAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
/* Play back the animation frame by frame */
for( i_frame=0; i_frame<n_frames; i_frame++ )
{
/* Play back the frame */
status = ProSingleAnimationPlay( single_animation, frames[i_frame] );
TEST_CALL_REPORT( "ProSingleAnimationPlay()",
"ProTestSingleAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
}
/* Visit objects in the frames */
puts( "Visit objects in the frames:" );
for( i_frame=0; i_frame<n_frames; i_frame++ )
for( i_obj=0; i_obj<n_objects; i_obj++ )
{
status = ProUtilCollectAnimObjects (frames[i_frame], &anim_objects);
if (status == PRO_TK_NO_ERROR)
{
status = ProArraySizeGet ((ProArray)anim_objects, &anim_obj_num);
TEST_CALL_REPORT( "ProArraySizeGet()", "ProTestSingleAnimation()",
status, status != PRO_TK_NO_ERROR );
for (i = 0; i < anim_obj_num; i++)
{
status = ProTestSingleAnimAct (anim_objects[i],
(ProAppData)&i_frame);
}
status = ProArrayFree ((ProArray*)&anim_objects);
TEST_CALL_REPORT( "ProArrayFree()", "ProTestSingleAnimation()",
status, status != PRO_TK_NO_ERROR );
}
}
/* Clear the data generated for single mode animation.*/
status = ProSingleAnimationClear( single_animation );
TEST_CALL_REPORT( "ProSingleAnimationClear()",
"ProTestSingleAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
return 0;
}
/*---------------------------------------------------------------------*\
Function: ProTestAnimFrameAct()
Purpose: This is the generic function for visiting animation objects.
Returns: 1 - success;
\*---------------------------------------------------------------------*/
ProError ProTestAnimFrameAct(
ProAnimFrame ani_frame, /* (In) The handle to the animation frame */
ProAppData app_data ) /* (In) The pointer to the frame number */
{
TEST_CALL_REPORT ("ProAnimFrameAct()", "ProTestAnimFrameAct()",
PRO_TK_NO_ERROR, 0);
if( app_data != NULL )
{
ProTKPrintf( "Movie frame %d: %X\n", *(int*)app_data, ani_frame );
}
return PRO_TK_NO_ERROR;
}
/*---------------------------------------------------------------------*\
Function: ProTestBatchAnimAct()
Purpose: This is the generic function for callbacks in the
middle of a batch animation.
Returns: PRO_TK_NO_ERROR - success;
Note:
\*---------------------------------------------------------------------*/
ProError ProTestBatchAnimAct( ProAnimFrame animation_frame, int frame_no,
ProAppData app_data )
{
TEST_CALL_REPORT ("ProBatchAnimAct()", "ProTestBatchAnimAct()",
PRO_TK_NO_ERROR, 0);
ProTKPrintf( "Batch frame %d\n", frame_no );
return PRO_TK_NO_ERROR;
}
/*---------------------------------------------------------------------*\
Function: ProTestBatchAnimation()
Purpose: On-button function.
Returns: 0 - success; -1 - error. Now ignored.
Note: Arguments are ignored.
\*---------------------------------------------------------------------*/
int ProTestBatchAnimation( void* p_dummy, int int_dummy )
{
ProError status;
ProAnimMovie animation_movie;
int i_frame;
ProAnimFrame *anim_frames;
int anim_frm_num;
int i;
/* Check animation frames */
if( n_frames < 1 )
{
ProUtilMsgPrint( "gen", "TEST %0s", "First, create an animation" );
return -1;
}
/* Check the number of the objects to be abimated */
if( n_objects < 1 )
{
ProUtilMsgPrint( "gen", "TEST %0s", "First, add objects to animate" );
return -1;
}
/* Create an animation movie */
status = ProAnimmovieCreate( ani_obj_seq[0].model, &animation_movie );
TEST_CALL_REPORT( "ProAnimmovieCreate()", "ProTestBatchAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
/* Add frames to the movie */
for( i_frame=0; i_frame<n_frames; i_frame++ )
{
status = ProAnimmovieFrameAdd( animation_movie, frames[i_frame] );
TEST_CALL_REPORT( "ProAnimmovieFrameAdd()", "ProTestBatchAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
}
/* Visit animation frames in the movie */
/* status = ProAnimmovieFrameVisit( animation_movie,
(ProAnimFrameAct)ProTestAnimFrameAct,
(ProAnimFrameAct)ProTestAnimFrameFilter,
NULL );
TEST_CALL_REPORT( "ProAnimmovieFrameVisit()",
"ProTestBatchAnimation()",
status, status != PRO_TK_NO_ERROR );*/
status = ProUtilCollectAnimFrames (animation_movie, &anim_frames);
if (status == PRO_TK_NO_ERROR)
{
status = ProArraySizeGet ((ProArray)anim_frames, &anim_frm_num);
TEST_CALL_REPORT( "ProArraySizeGet()", "ProTestBatchAnimation()",
status, status != PRO_TK_NO_ERROR );
for (i = 0; i < anim_frm_num; i++)
{
status = ProTestAnimFrameAct (anim_frames[i],
(ProAppData)NULL);
}
status = ProArrayFree ((ProArray*)&anim_frames);
TEST_CALL_REPORT( "ProArrayFree()", "ProTestBatchAnimation()",
status, status != PRO_TK_NO_ERROR );
}
/* Allow spinning */
ProAnimmovieSpinflagSet(animation_movie, PRO_B_TRUE);
/* Start a batch animation process */
status = ProBatchAnimationStart( animation_movie,
(ProBatchAnimAct)ProTestBatchAnimAct, NULL );
TEST_CALL_REPORT( "ProBatchAnimationStart()", "ProTestBatchAnimation()",
status, status != PRO_TK_NO_ERROR &&
status != PRO_TK_GENERAL_ERROR);
/* Remove frames from the movie */
for( i_frame=0; i_frame<n_frames; i_frame++ )
{
status = ProAnimmovieFrameRemove( animation_movie, frames[i_frame] );
TEST_CALL_REPORT( "ProAnimmovieFrameRemove()", "ProTestBatchAnimation()",
status, status != PRO_TK_NO_ERROR );
}
/* remove movie */
status = ProAnimmovieDelete( animation_movie );
TEST_CALL_REPORT( "ProAnimmovieDelete()", "ProTestBatchAnimation()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return -1;
return 0;
}
/*---------------------------------------------------------------------*\
Function: ProUtilSelectedMdlGet()
Purpose: Retrieves a handle of the model from the selection object.
Returns: PRO_TK_NO_ERROR - The function successfully get
the model name.
PRO_TK_GENERAL_ERROR - Error.
Note:
\*---------------------------------------------------------------------*/
ProError ProUtilSelectedMdlGet( ProSelection* p_selection, ProMdl* p_model )
{
ProError status;
ProModelitem model_item;
/* Check out the input parameters */
if( !p_selection || !p_model )
return PRO_TK_GENERAL_ERROR;
/* Get the model item from a selection object. */
status = ProSelectionModelitemGet( *p_selection, &model_item );
TEST_CALL_REPORT( "ProSelectionModelitemGet()", "ProUtilSelectedMdlGet()",
status, status != PRO_TK_NO_ERROR );
if( status == PRO_TK_NO_ERROR )
{
/* Retrieve the model the owns the specified item. */
status = ProModelitemMdlGet( &model_item, p_model );
TEST_CALL_REPORT( "ProModelitemMdlGet()", "ProUtilSelectedMdlGet()",
status, status != PRO_TK_NO_ERROR );
if( status == PRO_TK_NO_ERROR )
return PRO_TK_NO_ERROR;
}
return PRO_TK_GENERAL_ERROR;
}
/*---------------------------------------------------------------------*\
Function: ProUtilMdlEqual()
Purpose: Compares two models.
Returns: PRO_B_TRUE - The models are equal.
PRO_B_FALSE - The models are different.
Note: Here I compare models names, types and ids although
possibly it's enough to use only the types and ids.
\*---------------------------------------------------------------------*/
ProBoolean ProUtilMdlEqual( ProMdl model1, ProMdl model2 )
{
ProError status;
ProMdlName name1;
ProMdlName name2;
ProType type1;
ProType type2;
int id1;
int id2;
/* Get and compare types of the models. */
status = ProMdlTypeGet( model1, (ProMdlType *)&type1 );
TEST_CALL_REPORT( "ProMdlTypeGet()", "ProUtilMdlEqual()",
status, status != PRO_TK_NO_ERROR );
status = ProMdlTypeGet( model2, (ProMdlType *)&type2 );
TEST_CALL_REPORT( "ProMdlTypeGet()", "ProUtilMdlEqual()",
status, status != PRO_TK_NO_ERROR );
if( type1 != type2 )
return PRO_B_FALSE;
/* Get and compare ids of the models. */
status = ProMdlIdGet( model1, &id1 );
TEST_CALL_REPORT( "ProMdlIdGet()", "ProUtilMdlEqual()",
status, status != PRO_TK_NO_ERROR );
status = ProMdlIdGet( model2, &id2 );
TEST_CALL_REPORT( "ProMdlIdGet()", "ProUtilMdlEqual()",
status, status != PRO_TK_NO_ERROR );
if( id1 != id2 )
return PRO_B_FALSE;
/* Get and compare names of the models. */
status = ProMdlMdlnameGet( model1, name1 );
TEST_CALL_REPORT( "ProMdlMdlnameGet()", "ProUtilMdlEqual()",
status, status != PRO_TK_NO_ERROR );
status = ProMdlMdlnameGet( model2, name2 );
TEST_CALL_REPORT( "ProMdlMdlnameGet()", "ProUtilMdlEqual()",
status, status != PRO_TK_NO_ERROR );
if( ProUtilWstrCmp( name1, name2 ) != 0 )
return PRO_B_FALSE;
return PRO_B_TRUE;
}
/*---------------------------------------------------------------------*\
Function: ProUtilAsmcomppathEqual()
Purpose: Compares two component pathes.
Returns: PRO_B_TRUE - The pathes are equal.
PRO_B_FALSE - The pathes are different.
Note:
\*---------------------------------------------------------------------*/
ProBoolean ProUtilAsmcomppathEqual( ProAsmcomppath path1, ProAsmcomppath path2 )
{
int i;
/* Compare owners handles and number of the component ids */
if( (path1.owner != path2.owner) || (path1.table_num != path2.table_num) )
return PRO_B_FALSE;
/* Compare path ids */
for( i=0; i<path1.table_num; i++ )
if( path1.comp_id_table[i] != path2.comp_id_table[i] )
return PRO_B_FALSE;
return PRO_B_TRUE;
}
/*---------------------------------------------------------------------*\
Function: ProUtilAniObjectSelect()
Purpose: Select an animation object.
Returns: If the element is successfuly selected and found
in the array index is returned.
PRO_TK_E_NOT_FOUND - The selected element is not
an animation object.
PRO_TK_USER_ABORT - Selection was interrupted by a user.
Note: When I used ProSelection* p_selection calling ProSelect
with &p_selection...
\*---------------------------------------------------------------------*/
ProError ProUtilAniObjectSelect(
char option[], /* (In) The selection filter. */
ProSelection** p_selection, /* (Out) The pointer to selected item */
AniObjectInstance* p_ani_object ) /* (Out) Animation object to
initialize. Can be NULL */
{
ProError status;
int n_selected = 0; /* Actual number of sections made. */
AniObjectInstance ani_object;
/* Check arguments */
if( !p_selection )
return PRO_TK_USER_ABORT;
ProUtilMsgPrint( "gen", "TEST %0s", "Select an object" );
/* Select ONE object. */
status = ProSelect( option, 1,
NULL, NULL, NULL, NULL, p_selection, &n_selected );
TEST_CALL_REPORT( "ProSelect()", "ProUtilAniObjectSelect()",
status, status != PRO_TK_NO_ERROR );
if( (status != PRO_TK_NO_ERROR) || (n_selected != 1) )
return PRO_TK_USER_ABORT;
if( p_ani_object == NULL )
p_ani_object = &ani_object;
/* Use ProSelection data to init the animation object */
if( ProUtilAniObjectInstanceInit( p_selection, p_ani_object )
!= PRO_TK_NO_ERROR )
return PRO_TK_USER_ABORT;
/* Try to find out the selected object among array of the
animation objects */
return (ProError) ProUtilAniObjectFind( ani_obj_seq, *p_ani_object );
}
/*---------------------------------------------------------------------*\
Function: ProUtilAniObjectFind()
Purpose: Find specified animation object (AniObjectInstance) in
the array.
Returns:
Note: Animation objects are compared using ProMdl data and
ProAsmcomppath data. Animation object handles (ProAnimObj)
are not used.
\*---------------------------------------------------------------------*/
int ProUtilAniObjectFind(
ProArray array, /* (In) An array of the animation objects */
AniObjectInstance ani_object ) /* (In) The animation objects
to looking for */
{
ProError status;
int n_ani_objects = 0; /* Variable to get the size of the
array of the animation objects */
int i;
/* Get the current size of the array. */
status = ProArraySizeGet( array, &n_ani_objects );
TEST_CALL_REPORT( "ProArraySizeGet()", "ProUtilAniObjectFind()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return PRO_TK_E_NOT_FOUND;
/* Try to find out the name of the selected object among array of the
animation objects */
for( i=0; i<n_ani_objects; i++ )
if( (ProUtilMdlEqual( ((AniObjectInstance*)array)[i].model,
ani_object.model ) == PRO_B_TRUE ) &&
(ProUtilAsmcomppathEqual( ((AniObjectInstance*)array)[i].comp_path,
ani_object.comp_path ) == PRO_B_TRUE ) )
return i;
/* The specified object is not found */
return PRO_TK_E_NOT_FOUND;
}
/*---------------------------------------------------------------------*\
Function: ProUtilAniObjectInstanceInit()
Purpose: Initialize the AniObjectInstance structure using
ProSelection object.
Returns: PRO_TK_NO_ERROR - success; PRO_TK_GENERAL_ERROR - error
Note:
\*---------------------------------------------------------------------*/
ProError ProUtilAniObjectInstanceInit(
ProSelection** p_selection, /* (In) The pointer to selected item */
AniObjectInstance* p_ani_object ) /* (Out) Animation object to init */
{
ProError status;
/* Get a model from the selection */
if( ProUtilSelectedMdlGet( *p_selection, &(p_ani_object->model) )
!= PRO_TK_NO_ERROR )
return PRO_TK_GENERAL_ERROR;
/* Get a component path of the model */
status = ProSelectionAsmcomppathGet( **p_selection,
&(p_ani_object->comp_path) );
TEST_CALL_REPORT( "ProSelectionAsmcomppathGet()",
"ProUtilAniObjectInstanceInit()",
status, status != PRO_TK_NO_ERROR );
if( status != PRO_TK_NO_ERROR )
return PRO_TK_GENERAL_ERROR;
return PRO_TK_NO_ERROR;
}
/*---------------------------------------------------------------------*\
Function: ProUtilRotX()
Purpose: Add x rotation values to the transformation matrix.
Returns: None
Note: Only the rotation components of the matrix are modified.
\*---------------------------------------------------------------------*/
void ProUtilRotX(
double angle, /* (In) The rotation angle */
ProMatrix mx ) /* (Out) The transformation matrix */
{
mx[0][0] = 1.0;
mx[0][1] = mx[0][2] = mx[1][0] = mx[2][0] = 0.0;
mx[1][1] = mx[2][2] = cos( angle * PI / 180.0);
mx[1][2] = sin( angle * PI / 180.0);
mx[2][1] = - mx[1][2];
}