/****************************************************************************
 * Copyright (c) 2024 MAK Technologies, Inc.
 * All rights reserved.
 ****************************************************************************/

/*********************************************************************/
/**
 *t  diguyGraphicsLink
 **
 *b    Link against: libdiguy
 */

#pragma once

#ifdef SWIG
%module diguyGraphicsLink
#else
#define CPLUSPLUS_ONLY
#endif

#ifdef CPLUSPLUS_ONLY
#include <diguy_constants.h>

class bdiLink;
class diguyCharacter;
class diguyGraphicsLink;
class diguyGraphicsShape;
class diguyGraphicsShaderInstance;


#endif

#include <declspec_diguy.h>

//------------------------------------------------------------------------------
/*!
 ** \brief A class that represents the unique per-character non-shared joint of a character.
 **  A diguyCharacter is a hierarchy of links and joints.  Think of the links as the bones of
 **  the characters while joints are the articulations.  Note that the links themselves do not
 **  have any geometry directly associated with them; instead geometry is associated with shapes,
 **  which in turn are associated with links.
 **
 **  Can be subclassed by filling out the diguy_graphics_set_link_create_func().
 **
 ** \ingroup diguyGraphicsAPI
 */
class BDI_DECLSPEC_diguy diguyGraphicsLink
{

public:

/*****************************************************************************/
/**
 *2  Accessor Functions
 **
 **    The functions in this section provide access to data in this object.
 **    They are designed to be called by DI-Guy programmers.
 **
 **   Unless otherwise noted all functions in this class section are callable from:
 **
 *-    - C++
 *-    - Script
 */

   /*l
    *b  Description:
    **
    **    Returns the name of the link.  This pointer will never be NULL.
    **
    *b  Returns:
    **
    **    name of the link
    */
   const char* get_name();

   /*l
    *b  Description:
    **
    **    All links are assigned a unique identifier, or uid.  This
    **    function returns this links's uid.
    **
    **    *Note*: unique identifiers will change between DI-Guy runs!
    **
    *b  Returns:
    **
    **    unique identifier of object
    */
   long get_uid();

   /*l
    *b  Returns:
    **
    **    index of the link
    */
   int get_index();

   /*l
    *b  Description:
    **
    **    Returns a pointer to the diguyCharacter to which this link belongs.
    */
   diguyCharacter* get_character();

   /*l
    *b  Returns:
    **
    **    number of shapes on this link
    */
   int get_num_shapes();

   /*l
    *b  Returns:
    **
    **    pointer of type diguyGraphicsShape; NULL if no shape at the
    **    specified index
    **
    *b  Arguments:
    **
    *a    index - index of the shape; indices start at 0
    */
   diguyGraphicsShape* get_shape_at_index(int index);

   /*l
    *b  Description:
    **
    **    This function returns a pointer to the specified shape.
    **
    *b  Arguments:
    **
    *a    name    - name of link to be found
    **
    *b  Returns:
    **
    **    pointer of type diguyGraphicsShape; NULL if not found
    */
   diguyGraphicsShape* find_shape(const char* name);

   /*l
    *b  Description:
    **
    **    This function returns a pointer to the specified shape.
    **
    *b  Arguments:
    **
    *a    name - name of shape with class_type to be found,
    *a           currently works with heads
    **
    *b  Returns:
    **
    **    pointer of type diguyGraphicsShape; NULL if not found
    */
   diguyGraphicsShape* find_shape_by_class_type(const char* name);

   /*l
   *b  Description:
   **
   **    This function overrides the motion data driving the visibility child shapes
   **
   *b  Arguments:
   **
   *a    switch_name - the name of the motion data stream that controls the visibility
   *a                  of a child shape, see also get_switch_var_name(), set to -1 to
   *a                  allow the underlying motion data to resume control
   **
   */
   void set_shape_switch_override(const char * switch_name, int value);

   /*l
    *b  Description:
    **
    **    Returns the type of joint that attaches this link to its parent.
    **
    *b  Returns:
    **
    **    joint type of the link
    */
   diguyGraphicsJointType get_joint_type();

   /*l
    *b  Description:
    **
    **    Returns in the passed variables the translation amount of the
    **    link's joint.
    **
    **    If there is a current render camera set, the position link's
    **    values will be in the local space of the camera. This is useful
    **    for rendering far from the origin.
    **
    **    The values may or may not stay constant frame to frame; see
    **    get_translation_is_static().
    **
    **    Returned values are in meters, and should be applied after the
    **    rotational offset (if any).
    **
    *b  Arguments:
    **
    *a    tx, ty, tz - pointers to floats into which result should be placed
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    */
   int get_translation(float* tx, float* ty, float* tz);

   /*l
    *b  Description:
    **
    **    Returns in the passed variables the translation amount of the
    **    link's joint.
    **
    **    The values may or may not stay constant frame to frame; see
    **    get_translation_is_static().
    **
    **    Returned values are in meters, and should be applied after the
    **    rotational offset (if any).
    **
    *b  Arguments:
    **
    *a    tx, ty, tz - pointers to doubles into which result
    *a                 should be placed
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    */
   int get_translation_double(double* tx, double* ty, double* tz);

   /*l
    *b  Description:
    **
    **    Returns whether the translation returned by get_translation() is
    **    static (unchanging) or dynamic (can change frame to frame).
    **
    **    If the translation is dynamic the translation values will come
    **    from one or more DI-Guy motion variables; the names of the
    **    variables are accessible using the functions get_var_name_tx(),
    **    etc.
    **
    **    If the translation is static it will remain so; the value returned
    **    by this function should not change frame to frame.
    **
    *b  Returns:
    **
    **    1 if translation is static, 0 if not, -1 on failure
    */
   int get_translation_is_static();


   /*l
    *b  Description:
    **
    **    Returns in the passed variables the initial translation amount of the
    **    link's joint.
    **
    **    This value is static and typically represents the offset to the parent link
    **
    **    Returned values are in meters
    **
    *b  Arguments:
    **
    *a    tx, ty, tz - pointers to floats into which result should be placed
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    */
   int get_initial_translation(float* tx, float* ty, float* tz);

   /*l
    *b  Description:
    **
    **    Returns the name of the DI-Guy motion data variable that controls
    **    translation along the X axis.
    **
    **    The returned pointer will be NULL if there is no associated variable.
    **
    *b  Returns:
    **
    **    name of the variable; NULL if there is no variable
    */
   const char* get_var_name_tx();

   /*l
    *b  Description:
    **
    **    Returns the name of the DI-Guy motion data variable that controls
    **    translation along the Y axis.
    **
    **    The returned pointer will be NULL if there is no associated variable.
    **
    *b  Returns:
    **
    **    name of the variable; NULL if there is no variable
    */
   const char* get_var_name_ty();

   /*l
    *b  Description:
    **
    **    Returns the name of the DI-Guy motion data variable that controls
    **    translation along the Z axis.
    **
    **    The returned pointer will be NULL if there is no associated variable.
    **
    *b  Returns:
    **
    **    name of the variable; NULL if there is no variable
    */
   const char* get_var_name_tz();

   /*l
    *b  Description:
    **
    **    Returns in the passed variables the rotation amount of the link's
    **    joint.
    **
    **    The values may or may not stay constant frame to frame; see
    **    get_rotation_is_static().
    **
    **    Returned values are an Euler triple in degrees, and should be
    **    applied in RZ -> RX -> RY order, after the translation.
    **
    *b  Arguments:
    **
    *a    rz, rx, ry - pointers to floats into which result
    *a                 should be placed
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    */
   int get_rotation(float* rz, float* rx, float* ry);

   /*l
    *b  Description:
    **
    **    Returns in the passed variables the rotation amount of the link's
    **    joint.
    **
    **    The values may or may not stay constant frame to frame; see
    **    get_rotation_is_static().
    **
    **    Returned values are an Euler triple in degrees, and should be
    **    applied in RZ -> RX -> RY order, after the translation.
    **
    *b  Arguments:
    **
    *a    rz, rx, ry - pointers to floats into which result
    *a                 should be placed
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    */
   int get_rotation_euler(float* rz, float* rx, float* ry);

   /*l
    *b  Description:
    **
    **    Returns in the passed variables the rotation amount of the link's
    **    joint.
    **
    **    The values may or may not stay constant frame to frame; see
    **    get_rotation_is_static().
    **
    **    Returned values are a quaternion and should be applied after
    **    the translation.
    **
    *b  Arguments:
    **
    *a    qx, qy, qz, qw - pointers to floats into which result
    *a                 should be placed
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    */
   int get_rotation_quat(float* qx, float* qy, float* qz, float* qw);

   /*l
    *b  Description:
    **
    **    Returns whether the rotation returned by get_rotation() is static
    **    (unchanging) or dynamic (can change frame to frame).
    **
    **    If the rotation is dynamic the rotation values will come from one
    **    or more DI-Guy motion variables; the names of the variables are
    **    accessible using the functions get_var_name_rz(), etc.
    **
    **    If the rotation is static it will remain so; the value returned by
    **    this function should not change frame to frame.
    **
    *b  Returns:
    **
    **    1 if rotation is static, 0 if not, -1 on failure
    */
   int get_rotation_is_static();

   /*l
    *b  Description:
    **
    **    Returns the name of the DI-Guy motion data variable that controls
    **    rotation about the Z axis.
    **
    **    The returned pointer will be NULL if there is no associated
    **    variable.
    */
   const char* get_var_name_rz();

   /*l
    *b  Description:
    **
    **    Returns the name of the DI-Guy motion data variable that controls
    **    rotation about the X axis.
    **
    **    The returned pointer will be NULL if there is no associated
    **    variable.
    */
   const char* get_var_name_rx();

   /*l
    *b  Description:
    **
    **    Returns the name of the DI-Guy motion data variable that controls
    **    rotation about the Y axis.
    **
    **    The returned pointer will be NULL if there is no associated
    **    variable.
    */
   const char* get_var_name_ry();


   /*l
    *b  Description:
    **
    **    Returns a pointer to this link's parent link.  Parent links are
    **    always links within the same character.  If a link is attached to
    **    a link in another character (i.e., it is "parented to" another
    **    link), that link pointer can be obtained by calling
    **    get_attached_to_link().
    **
    **    The returned pointer will be NULL if the link is the position link
    **    and has no parent.
    **
    *b  Returns:
    **
    **    object of type diguyGraphicsLink
    */
   diguyGraphicsLink* get_parent_link();

   /*l
    *b  Description:
    **
    **    Returns a pointer to this character's base position link.
    */
   diguyGraphicsLink* get_position_link();

   diguyGraphicsLink* get_position_link() const;

   /*l
    *b  Description:
    **
    **    Returns a pointer to this link's attached to link.  The attached
    **    to link is different than the parent link in that a parent link is
    **    always a link in the same character, while an attached to link is
    **    always a link in a different character.
    **
    **    Only position links can be attached to links of another character.
    **
    **    The returned pointer will be NULL if the link is not attached to
    **    the link of another character.
    */
   diguyGraphicsLink* get_attached_to_link();

   /*l
    *b  Description:
    **
    **    Returns 1 if this link is the position link, or 0 if not.  The
    **    position link is the root link of the DI-Guy character's link and
    **    shape hierarchy, and has no parent link.
    **
    *b  Returns:
    **
    **    1 if this link is the position link, 0 if not, -1 on error
    */
   int get_is_position_link();

   /*l
    *b  Description:
    **
    **    Returns how many child links this link has.  Child links can be
    **    accessed using the get_child_link_at_index() function.
    **
    *b  Returns:
    **
    **    number of child links
    */
   int get_num_child_links();

   /*l
    *b  Description:
    **
    **    Returns a pointer to this link's child link at the specified
    **    index.
    **
    **    The returned pointer will be NULL if there is no link at that
    **    index.
    **
    *b  Arguments:
    **
    *a    index - index of the child link; indices start at 0
    */
   diguyGraphicsLink* get_child_link_at_index(int index);

/*****************************************************************************/
/**
 *2  Matrix Retrieval Functions
 **
 **   All functions in this class section are restricted to C++.
 */

#ifdef CPLUSPLUS_ONLY

   /*l
    *b  Description:
    **
    **    This function fills out the passed float array with the
    **    world-coordinate system transformation matrix of this link.
    **    ie -> character->get_position_transformation_matrix() * link->get_cached_matrix();
    **
    *b  Arguments:
    **
    *a    matrix_array - two-dimensional array of floats into
    *a                   which the matrix should be copied
    *a    transpose    - defaults to zero, sets if the matrix should be
    *a                   treated as row-major or column-major
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    */
   int get_transformation_matrix(float matrix_array[4][4], int transpose = 0);

   /*l
    *b  Description:
    **
    **   Pointer version of get_transformation_matrix(), see for docs.
    **   Some end users might prefer this version to avoid copying data from
    **   an explicit float[4][4].
    **/
   int get_transformation_matrix_4x4_ptr(float* matrix, int transpose = 0);

   /*l
    *b  Description:
    **
    **    This function fills out the passed float array with the
    **    character-local-coordinate system transformation matrix of this
    **    link. Also known as the cached matrix.
    **
    *b  Arguments:
    **
    *a    matrix_array - two-dimensional array of floats into
    *a                   which the matrix should be copied
    *a    transpose    - defaults to 0, sets if the matrix should be treated
    *a                   as row-major or column-major
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    */
   int get_local_transformation_matrix(float matrix_array[4][4], int transpose = 0);

   /*l
    *b  Description:
    **
    **   Pointer version of get_local_transformation_matrix(), see for docs.
    *    Some end users might prefer this version to avoid copying data from
    *    an explicit float[4][4].
    **/
   int get_local_transformation_matrix_4x4_ptr(float* matrix, int transpose = 0);

   int get_local_translation(float * x, float *y, float *z);

   /*l
    *b  Description:
    **
    **    This function fills out the passed float array with the
    **    link-local-coordinate system transformation matrix of this
    **    link. This is the same value as the matrix built from
    **    get_rotation() and get_translation()
    **
    *b  Arguments:
    **
    *a    matrix_array - two-dimensional array of floats into
    *a                   which the matrix should be copied
    *a    transpose    - defaults to 0, sets if the matrix should be treated
    *a                   as row-major or column-major
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    */
   int get_link_transformation_matrix(float matrix_array[4][4], int transpose = 0);

   /*l
    *b  Description:
    **
    **   Pointer version of get_link_transformation_matrix(), see for docs.
    **   Some end users might prefer this version to avoid copying data from
    **   an explicit float[4][4].
    **/
   int get_link_transformation_matrix_4x4_ptr(float* matrix, int transpose = 0);

#endif



#ifdef CPLUSPLUS_ONLY

   /*l
    *b  Description:
    **
    **    Returns a pointer to the current motion data array.  Along with
    **    data indices returned below, motion data can be directly read from
    **    this state vector instead of making multiple calls for getting
    **    transform data.
    **
    **    The rotations in this array will be in Euler angles.  If
    **    quaternions are being used, get_quat_data_ptr() should be called
    **    instead.
    **
    **    This function may return NULL, in which case the functions
    **    get_translation(), get_rotation(), and get_scale() must be used.
    **
    **    The pointer returned by this function may change from frame to
    **    frame, and therefore should not be saved.
    **
    **    This function should not be used for the position link (when
    **    get_is_position_link() returns 1).
    **
    **    This function should not be called in a derived class's
    **    constructor; the pointer will not yet be valid.
    **
    *b  Returns:
    **
    **    pointer to floats; may return NULL if array isn't available
    **
    *b  Callable From:
    **
    *-    - C++
    */
   const float* get_data_ptr();

   /*l
    *b  Description:
    **
    **    This function is similar to get_data_ptr(), except rotations in
    **    the returned array will be in quaternions instead of Euler angles.
    **
    *b  Returns:
    **
    **    pointer to floats; may return NULL if array isn't available
    **
    *b  Callable From:
    **
    *-    - C++
    */
   const float* get_quat_data_ptr();

#endif

   /*l
    *b  Description:
    **
    **    Returns the index of this link's translation data in the float
    **    array returned by get_data_ptr() or get_quat_data_ptr().  The
    **    translation values are in (tx, ty, tz) order in the array.
    **
    **    This function may return -1, in which case this link has no
    **    translation data.
    **
    **    The index returned by this function will not change from frame to
    **    frame, and can therefore be saved once it has been obtained.
    **
    **    This function should not be used for the position link (when
    **    get_is_position_link() returns 1).  Use get_translation() instead.
    **
    **    This function should not be called in a derived class's
    **    constructor; the index will not yet be valid.
    **
    *b  Returns:
    **
    **    index into float array; -1 if no translation data for link
    */
   int get_translation_data_index();

   /*l
    *b  Description:
    **
    **    Returns the index of this link's rotation data in the float array
    **    returned by get_data_ptr().  If quaternion data is being used,
    **    call get_quat_data_ptr() instead.
    **
    **    The rotation values in the data array will be Euler angles in (rz,
    **    rx, ry) order.
    **
    **    This function may return -1, in which case this link has no
    **    rotation data.
    **
    **    This function should not be used for the position link (when
    **    get_is_position_link() returns 1).  Use get_rotation() instead.
    **
    **    This function should not be called in a derived class's
    **    constructor; the index will not yet be valid.
    **
    *b  Returns:
    **
    **    index into float array; -1 if no rotation data for link
    */
   int get_rotation_data_index();

   /*l
    *b  Description:
    **
    **    Returns the index of this link's rotation data in the float array
    **    returned by get_quat_data_ptr().  If Euler angle data is being
    **    used, call get_data_ptr() instead.
    **
    **    The rotation values in the data array will be a quaternion in (qx,
    **    qy, qz, qw) order.
    **
    **    This function may return -1, in which case this link has no
    **    rotation data.
    **
    **    The index returned by this function will not change from frame to
    **    frame, and can therefore be saved once it has been obtained.
    **
    **    This function should not be used for the position link (when
    **    get_is_position_link() returns 1).  Use get_rotation() instead.
    **
    **    This function should not be called in a derived class's
    **    constructor; the index will not yet be valid.
    **
    *b  Returns:
    **
    **    index into float array; -1 if no rotation data for link
    */
   int get_quat_data_index();


   /*l
    *b  Description:
    **
    **    Returns in the passed pointers the unique color of this link. All
    **    links in a DI-Guy appearance are assigned a unique RGB color that
    **    can be used in pick/selection operations.
    **
    **    Also see diguyScenario::map_color_to_impact().
    **
    **    See programming_examples/diguy_graphics_api/ogl_examples/intersection_test
    **    for an example of its usage.
    **
    *b  Returns:
    **
    **    0 on success, -1 on failure
    **
    ** @TODO Test with lua probably non-functional
    */
   int get_unique_color(unsigned char* r,
      unsigned char* g,
      unsigned char* b);


/*****************************************************************************/
/**
 *2  Virtual Functions
 **
 **    The functions in this section are all virtual functions that will
 **    be called by DI-Guy at various times during DI-Guy execution.
 **
 **    Because the functions are all virtual, DI-Guy programmers can create
 **    a subclass of this class and override them.  Unless otherwise stated,
 **    the base class functions do not need to be called.
 */

#ifdef CPLUSPLUS_ONLY

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when it is time for
    **    renderer-specific link objects to be created.  All information
    **    necessary to build the link should be available via the Accessor
    **    Functions above when this function is called.
    **
    **    Builds happen in depth-first traversal order, so the parent's
    **    build() function will always be called before this link's build()
    **    function.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers usually do not override this function.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers usually do override this function, to create
    **    scene graph nodes that allow for the various transformations to
    **    happen.
    **
    **    The following nodes are commonly created:
    **
    *-    - a static transform node to hold the offsets
    *-    - a dynamic transform node (or DOF) to allow motion data
    *-      to be applied
    *-    - either an LOD or switch node to allow graphics LODs to be
    *-      applied
    **
    **    LOD nodes, that automatically handle LOD switching, should be
    **    created if automatic LOD switching is desired.
    **
    **    A switch node should be created if manual setting of the graphics
    **    LOD is desired.
    **
    **    If this link is a position link (it has no parent link), the scene
    **    graph nodes should not yet be attached to the scene graph; that
    **    should be done during the call to attach().
    **
    **    Otherwise the scene graph nodes should start out attached to their
    **    attach points (a scene graph node of the parent link).
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during
    *-      the Build Stage)
    */
   virtual void build();

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when all links and shapes
    **    of a DI-Guy character have been built, providing an opportunity
    **    for final touch-ups to be made to the built hierarchy.
    **
    **    This function will be called only for the top-level position link.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers usually do not override this function.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers sometimes override this function.  They
    **    might to so to do renderer-specific optimizations to the created
    **    hierarchy.
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during
    *-      the Build Stage)
    */
   virtual void post_build();

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when it is time for the
    **    renderer-specific link objects created during the build() call to
    **    be destroyed.
    **
    **    Unbuilds happen in reverse depth-first traversal order, so this
    **    link's unbuild() function will always be called before the
    **    parent's unbuild() function.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers usually do not override this function.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers usually do override this function, to
    **    destroy the scene graph nodes created by build().
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during
    *-      the Unbuild Stage)
    */
   virtual void unbuild();

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when it is time for
    **    renderer-specific link objects created during the build() call to
    **    be attached to their attach points.
    **
    **    This function will only be called for the position link.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers usually do not override this function.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers usually do override this function, to attach
    **    the scene graph nodes created during build() to somewhere on the
    **    scene graph.
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during
    *-      the Build Stage, and sometimes during the Update Stage)
    */
   virtual void attach_to_scene();

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when it is time for
    **    renderer-specific link objects created during the build() call to
    **    be detached from their attach points.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers usually do not override this function.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers usually do override this function, to detach
    **    the scene graph nodes created during build() from the scene graph.
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during
    *-      the Build Stage, and sometimes during the Update Stage)
    */
   virtual void detach_from_scene();

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when it is time for
    **    renderer-specific link objects created during the build() call to
    **    be updated with new transformation data.
    **
    **    Updates happen in depth-first traversal order, so the parent's
    **    update() function will always be called before this link's
    **    update() function.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers usually do not override this function.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers usually do override this function, to update
    **    the scene graph nodes created during build() with new values.
    **
    **    These values should be obtained by calling get_translation(),
    **    get_rotation(), and get_scale().
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during Update Stage)
    */
   virtual void update();


   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when it is time for the
    **    transformations of this link to be applied.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers usually do override this function, to
    **    apply transformations to the transformation stack.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers usually do not override this function;
    **    transformation states are handled automatically by scene graphs.
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during Draw Stage)
    **
    *e
    *e //linear draw behavior
    *e {
    *e    // push the base transform of the character in the world
    *e    // the get_transformation_matrix() of the position link
    *e    m_position_link->begin_character_draw();
    *e    int i;
    *e    for each link in link array
    *e    {
    *e       // note the ability to skip links with nothing attached to them
    *e       if (link->get_num_shapes() > 0 || link->get_is_position_link())
    *e       {
    *e          // each link should multiply by the get_local_transformation_matrix
    *e          // which contains the precalculated concatenated matrix
    *e          link->draw();
    *e       }
    *e    }
    *e    m_position_link->end_character_draw();
    */

   virtual void draw();

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when it a shader should be
    **    bound to this link.  This is important in some scene graph
    **    environments, when the scene graph is responsible for binding the
    **    shader.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers usually do not override this function.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers can override this function but some don't
    **    need to.
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during Build Stage)
    */
   virtual void set_shader_instance(diguyGraphicsShaderInstance* shader_instance);

   /*b  Description:
    **
    **    This function will be called by DI-Guy in the update loop when the character
    **    changes instancing state. This allows additional work to be done to manage
    **    instancing. Note this hasn't been needed, for any of our sample implementations.
    */
   virtual void instancing_state_changed(int instanced);

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy while building instance groups (which occurs
    **    during diguyScenario::draw() or when manually invoked. It gives the user a chance to set
    **    the contents of the tbo on a per shape basis. tbo_data should be a 4x3 matrix.
    **    Will only be called if diguyScenario::set_instancing_position_callback_enabled() is set to true.
    */
   virtual void fill_out_tbo_position_matrix(diguyGraphicsShape * current_shape, int lod, float * tbo_data) const;

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy while building instance groups (which occurs
    **    during diguyScenario::draw() or when manually invoked. Will allow the end user to add additional
    **    data to the tbo. This is required to be in blocks of 4 floats. Will only be called if
    **    diguyScenario::set_num_extra_per_instance_data_floats(int number); is set to a reasonable number.
    */
   virtual void fill_out_tbo_additional_data(diguyGraphicsShape * current_shape, float * tbo_data);

/****************************************************************************/
/**
 *2  Experimental Functions
 **
 */
   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when the drawing of a new
    **    character is beginning.  This happens when the position link is
    **    drawn.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers can override this function.  Typically
    **    some type of transformation matrix stack push operation is
    **    performed.  This is also an appropriate place to do any
    **    per-character modifications, such as:
    **
    *-    - applying scale
    *-    - applying the base translation of the character
    *-    - picking a current LOD
    *-    - etc.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers usually do not override this function;
    **    transformation states are handled automatically by scene graphs.
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during
    *-      Draw Stage)
    */
   virtual void begin_character_draw();

   /*l
    *b  Description:
    **
    **    This function will be called by DI-Guy when the drawing traversal
    **    of the character's link hierarchy has completed.
    **
    *i  Immediate Mode:
    **
    **    Immediate mode renderers can override this function.  Typically
    **    any matrix stack push operation done in begin_character_draw()
    **    is undone here by an appropriate pop operation.
    **
    *i  Scene Graph:
    **
    **    Scene graph renderers usually do not override this function;
    **    transformation states are handled automatically by scene graphs.
    **
    *b  Callable From:
    **
    *-    - N/A (automatically called by DI-Guy Graphics API during
    *-      Draw Stage)
    */
   virtual void end_character_draw();


#endif



/****************************************************************************/
/****************************************************************************/
/**
 *2  Experimental Functions
 **
 **  The following functions are experimental and may change or
 **   disappear with no warning.
 */
/****************************************************************************/
/****************************************************************************/

   //! Gets the inverse of the rotation matrix as a 4x4 float array.
   int get_inverse_rotation_matrix(float matrix_array[4][4], int transpose = 0,
      int include_translation = 1);

   //! Gets the inverse of the rotation matrix as a 16-float array pointer.
   int get_inverse_rotation_matrix_4x4_ptr(float* matrix_array, int transpose = 0,
      int include_translation = 1);

   //! Gets an approximation of the bounding box of this bone based on it's
   //! position in the skeleton. This bounding box is in the space of the local_transformation_matrix
   //! Not always accurate.
   int get_approximate_bounding_box(float * bbox_min_x, float * bbox_min_y, float * bbox_min_z,
      float * bbox_max_x, float * bbox_max_y, float * bbox_max_z);

/****************************************************************************/
/****************************************************************************/
/**
 *2  Deprecated Functions
 **
 **  The following functions are deprecated.
 **
 **  As these functions may disappear in a future version of DI-Guy,
 **   it is recommended that you remove calls to these functions from
 **   your application.
 **
 */
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/

   /*l
    *b  Description:
    **
    **    Deprecated as of 9.1.4; use diguyGraphicsLink::get_is_position_link()
    **    instead.
    */
   int get_is_base_link();

   /*l
    *b  Description:
    **
    **    Deprecated as of 12.0.0 due to architecture change
    */
   //int get_shader_matrix_index();

   //Deprecated as of 13.2.0 due to architecture change
   /*l
   *b  Deprecated, we don't currently support scaling links
   **
   **    Returns in the passed variables the scale amount of the link's
   **    joint.
   **
   **    The values may or may not stay constant frame to frame; see
   **    get_scale_is_static().
   **
   **    Returned values unitless scale factors, and should be applied
   **    after the rotation.
   **
   *b  Arguments:
   **
   *a    sx, sy, sz - pointers to floats into which result
   *a                 should be placed
   **
   *b  Returns:
   **
   **    0 on success, -1 on failure
   */
   int get_scale(float* sz, float* sx, float* sy);

   /*l
   *b  Description:
   **
   **    Returns whether the scale returned by get_scale() is static
   **    (unchanging) or dynamic (can change frame to frame).
   **
   **    If the scale is dynamic the scale values will come from one or
   **    more DI-Guy motion variables; the names of the variables are
   **    accessible using the functions get_var_name_sx(), etc.
   **
   **    If the scale is static it will remain so; the value returned by
   **    this function should not change frame to frame.
   **
   *b  Returns:
   **
   **    1 if scale is static, 0 if not, -1 on failure
   */
   int get_scale_is_static();

   /*l
   *b  Description:
   **
   **    Returns the name of the DI-Guy motion data variable that controls
   **    scale in the Z dimension.
   **
   **    The returned pointer will be NULL if there is no associated
   **    variable.
   */
   const char* get_var_name_sx();

   /*l
   *b  Description:
   **
   **    Returns the name of the DI-Guy motion data variable that controls
   **    scale in the Y dimension.
   **
   **    The returned pointer will be NULL if there is no associated
   **    variable.
   */
   const char* get_var_name_sy();

   /*l
   *b  Description:
   **
   **    Returns the name of the DI-Guy motion data variable that controls
   **    scale in the X dimension.
   **
   **    The returned pointer will be NULL if there is no associated
   **    variable.
   */
   const char* get_var_name_sz();

   /*l
   *b  Description:
   **
   **    Returns the index of this link's scale data in the float array
   **    returned by get_data_ptr() or get_quat_data_ptr().  The scale
   **    values are in (sx, sy, sz) order in the array.
   **
   **    This function may return -1, in which case this link has no scale
   **    data.
   **
   **    The index returned by this function will not change from frame to
   **    frame, and can therefore be saved once it has been obtained.
   **
   **    This function should not be used for the position link (when
   **    get_is_position_link() returns 1).  Use get_scale() instead.
   **
   **    This function should not be called in a derived class's
   **    constructor; the index will not yet be valid.
   **
   *b  Returns:
   **
   **    index into float array; -1 if no scale data for link
   */
   int get_scale_data_index();

/****************************************************************************/
/****************************************************************************/
   void set_selected(bool value);
   bool get_selected();

   // These functions were removed since they are now always zero and their use
   // could lead to confusion. Links now only have translations and rotations,
   // those completely represent their offset from their parents
   //int get_offset_translation(float* tx, float* ty, float* tz);

   //int get_offset_rotation(float* rz, float* rx, float* ry);

/**
 *x  The functions and variables past this point are for internal use only.
 **   No external access to them is expected or necessary.
 */
#ifdef CPLUSPLUS_ONLY

   bdiLink* get_scripted_object() {return m_scripted_object;}

protected:

   /*l
    **    A protected constructor.  Constructors are called automatically
    **    by DI-Guy.
    */
   diguyGraphicsLink(void* internal_data);

   /*l
    **    A protected destructor.  Destructors are called automatically
    **    by DI-Guy.
    */
   virtual ~diguyGraphicsLink();

private:

   /*l
    **    A pointer to internal data.
    */
   bdiLink* m_scripted_object;

   friend class bdiLink;
   friend class bdiGraphicsFactory;

#endif

};
