// -------------------------------------------------------------------------
// GIZMO SKILLS
// -------------------------------------------------------------------------
#define skGizmoContainer skill1
#define skEntity skill2
#define skBoneName skill3
#define skBoneHandle skill4
#define skLocalPan skill5
#define skLocalTilt skill6
#define skLocalRoll skill7
#define skChildrenCount skill19
#define MC_CHILDREN_ARRAY_BASE 20
//#define skChildren skill20<->skill92 (max of 72 bones)
// -------------------------------------------------------------------------
// GIZMOS CONTAINER
// -------------------------------------------------------------------------
typedef struct
{
int iGizmoCount;
ENTITY **entGizmo;
} ENT_BONE_GIZMOS;
ENT_BONE_GIZMOS *gizmosCreate ( ENTITY *ent )
{
if ( !ent )
return NULL;
int iBoneCount = ent_status ( ent, 14 );
if ( !iBoneCount )
return NULL;
ENT_BONE_GIZMOS *ebg = sys_malloc ( sizeof(ENT_BONE_GIZMOS) );
ebg->iGizmoCount = iBoneCount;
ebg->entGizmo = sys_malloc ( sizeof(ENTITY*) * iBoneCount );
ent_bonereset_all ( ent );
int iBoneIndex = 0;
for ( ; iBoneIndex<iBoneCount; iBoneIndex+=1 )
{
ENTITY *entGizmo = ent_create ( "gizmo.mdl", nullvector, NULL );
*(ebg->entGizmo+iBoneIndex) = entGizmo;
STRING *strBoneName = str_create ( "" );
long hdlBone = ent_bonehandle ( ent, strBoneName, iBoneIndex+1 );
entGizmo->skGizmoContainer = (ENT_BONE_GIZMOS*)ebg;
entGizmo->skEntity = (ENTITY*)ent;
entGizmo->skBoneName = (STRING*)strBoneName;
entGizmo->skBoneHandle = (long)hdlBone;
vec_set ( &entGizmo->skLocalPan, nullvector );
entGizmo->skChildrenCount = 0;
entGizmo->flags |= ZNEAR;
vec_for_bone ( &entGizmo->x, ent, hdlBone );
ang_for_bone ( &entGizmo->pan, ent, hdlBone );
long hdlParent = ent_boneparent ( ent, NULL, hdlBone );
if ( hdlParent )
{
int iParentIndex = 0;
for ( ; iParentIndex<iBoneIndex; iParentIndex+=1 )
{
ENTITY *entParent = *(ebg->entGizmo+iParentIndex);
if ( entParent->skBoneHandle != hdlParent )
continue;
entGizmo->parent = entParent;
entParent->skill[MC_CHILDREN_ARRAY_BASE+entParent->skChildrenCount] = (ENTITY*)entGizmo;
entParent->skChildrenCount += 1;
break;
}
}
else
{
entGizmo->parent = NULL;
}
}
return ebg;
}
void gizmosRemove ( ENT_BONE_GIZMOS* ebg )
{
if ( !ebg )
return;
int iBoneIndex = 0;
for ( ; iBoneIndex<ebg->iGizmoCount; iBoneIndex+=1 )
{
ENTITY *entGizmo = *(ebg->entGizmo+iBoneIndex);
str_remove ( (STRING*)entGizmo->skBoneName );
ent_remove ( entGizmo );
}
sys_free ( ebg->entGizmo );
sys_free ( ebg );
}
// -------------------------------------------------------------------------
// GIZMOS ROTATION
// -------------------------------------------------------------------------
void gizmoChildrenUpdate ( ENTITY *entGizmo, ENTITY *ent )
{
int iChildIndex = 0;
for ( ; iChildIndex<entGizmo->skChildrenCount; iChildIndex+=1 )
{
ENTITY *entChild = (ENTITY*)entGizmo->skill[MC_CHILDREN_ARRAY_BASE+iChildIndex];
long hdlChild = (long)entChild->skBoneHandle;
vec_for_bone ( &entChild->x, ent, hdlChild );
ang_for_bone ( &entChild->pan, ent, hdlChild );
gizmoChildrenUpdate ( entChild, ent );
}
}
void gizmoRotate ( ENTITY *entGizmo, ANGLE *angRotation )
{
ang_add ( &entGizmo->pan, angRotation );
ang_add ( &entGizmo->skLocalPan, angRotation );
ENTITY *ent = (ENTITY*)entGizmo->skEntity;
long hdlBone = (long)entGizmo->skBoneHandle;
ent_bonereset ( ent, hdlBone );
ent_bonerotate ( ent, hdlBone, &entGizmo->skLocalPan );
gizmoChildrenUpdate ( entGizmo, ent );
}
// -------------------------------------------------------------------------
// MAIN
// -------------------------------------------------------------------------
void main ()
{
video_mode = 10;
mouse_mode = 4;
wait(1);
level_load ( "" );
camera->x = -200;
camera->bg = pixel_for_vec ( COLOR_BLACK, 100, 8888 );
ENTITY *entModel1 = ent_create ( "knight.mdl", nullvector, NULL );
ENT_BONE_GIZMOS *ebg1 = gizmosCreate ( entModel1 );
ENTITY* entGizmo1 = *(ebg1->entGizmo+2);
gizmoRotate ( entGizmo1, vector(0,45,0) );
while ( !key_esc )
{
gizmoRotate ( entGizmo1, vector(5*time_step,0,0) );
wait(1);
}
gizmosRemove ( ebg1 );
ent_remove ( entModel1 );
sys_exit ( NULL );
}