UIExamples/CubeCreator/UI.cxx

/**************************************************************************************

 Copyright (C) 2001 - 2010 Autodesk, Inc. and/or its licensors.
 All Rights Reserved.

 The coded instructions, statements, computer programs, and/or related material 
 (collectively the "Data") in these files contain unpublished information 
 proprietary to Autodesk, Inc. and/or its licensors, which is protected by 
 Canada and United States of America federal copyright law and by international 
 treaties. 
 
 The Data may not be disclosed or distributed to third parties, in whole or in
 part, without the prior written consent of Autodesk, Inc. ("Autodesk").

 THE DATA IS PROVIDED "AS IS" AND WITHOUT WARRANTY.
 ALL WARRANTIES ARE EXPRESSLY EXCLUDED AND DISCLAIMED. AUTODESK MAKES NO
 WARRANTY OF ANY KIND WITH RESPECT TO THE DATA, EXPRESS, IMPLIED OR ARISING
 BY CUSTOM OR TRADE USAGE, AND DISCLAIMS ANY IMPLIED WARRANTIES OF TITLE, 
 NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR USE. 
 WITHOUT LIMITING THE FOREGOING, AUTODESK DOES NOT WARRANT THAT THE OPERATION
 OF THE DATA WILL BE UNINTERRUPTED OR ERROR FREE. 
 
 IN NO EVENT SHALL AUTODESK, ITS AFFILIATES, PARENT COMPANIES, LICENSORS
 OR SUPPLIERS ("AUTODESK GROUP") BE LIABLE FOR ANY LOSSES, DAMAGES OR EXPENSES
 OF ANY KIND (INCLUDING WITHOUT LIMITATION PUNITIVE OR MULTIPLE DAMAGES OR OTHER
 SPECIAL, DIRECT, INDIRECT, EXEMPLARY, INCIDENTAL, LOSS OF PROFITS, REVENUE
 OR DATA, COST OF COVER OR CONSEQUENTIAL LOSSES OR DAMAGES OF ANY KIND),
 HOWEVER CAUSED, AND REGARDLESS OF THE THEORY OF LIABILITY, WHETHER DERIVED
 FROM CONTRACT, TORT (INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE), OR OTHERWISE,
 ARISING OUT OF OR RELATING TO THE DATA OR ITS USE OR ANY OTHER PERFORMANCE,
 WHETHER OR NOT AUTODESK HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS
 OR DAMAGE. 

**************************************************************************************/
// UI.cxx : Defines the entry point for the application.

#include "stdafx.h"
#include <commctrl.h> // for treeview control

#include "UI.h"
#include "SDK_Utility.h"

#define MAX_LOADSTRING 100

#define SAVE_TO_BUTTON          1000
#define SAVE_TO_EDITBOX         1001
#define ADD_CUBE_BUTTON         1002
#define REMOVE_CUBES_BUTTON     1003
#define FBX_TREEVIEW            1004
#define MATERIAL_CHECKBOX       1005
#define TEXTURE_CHECKBOX        1006
#define ANIMATION_CHECKBOX      1007

// Global Variables:
HINSTANCE hInst;                        // current instance
HWND      ghWnd = NULL;                 // main window

TCHAR szTitle[MAX_LOADSTRING];          // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];    // the main window class name

char gszOutputFile[MAX_PATH];           // File name to export
int  gWriteFileFormat = -1;             // Write file format

extern KFbxSdkManager *gSdkManager;     // access to the global SdkManager object
extern KFbxScene      *gScene;          // access to the global scene object

extern KString gAppPath;                // application path

// Forward declarations of functions included in this code module:
ATOM                UIRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

void CreateUIControls(HWND hWndParent);
void GetOutputFileName(HWND hWndParent);

// used to check if in the filepath the file extention exist
bool ExtExist(const char * filepath, const char * ext);

// used to get the directory part of a filepath
KString GetDirectoryFromFilePath(const char *pFilePath);

// to save the file selected
void ExportFile();

// to offer playing FBX file in QuickTime player
void AskForPlayInQuickTimePlayer(HWND pHwnd);

//-----------------------------------------------------------
// treview utility
// used to add a new treeview item
HTREEITEM InsertTreeViewItem(const HWND hTv, const char *txt, HTREEITEM htiParent);

// used to expand all treeview items
void Expand_All();
void Expand_All_Recurse(HWND htv, HTREEITEM htvi);

//-----------------------------------------------------------
// scene nodes utility
// used to display the nodes hierarchy
void DisplayHierarchy(const HWND hTv);
void DisplayHierarchyRecurse(const KFbxNode* pNode, HWND hTv, HTREEITEM htiParent);

// used to add KFbxNode attributes parameters
void AddTreeViewItemKFbxNodeParameters(const KFbxNode* pNode, HWND hTv, HTREEITEM htiParent);

// used to fill the treeview with the FBX scene content
void FillTreeView(const HWND mainHwnd);


//----------------------------------------------------------
// entry point for the application
int APIENTRY _tWinMain(
                       HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPTSTR    lpCmdLine,
                       int       nCmdShow
                       )
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MSG msg;
    HACCEL hAccelTable;

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_UI, szWindowClass, MAX_LOADSTRING);
    UIRegisterClass(hInstance);

    // empty our global file name buffer
    ZeroMemory(gszOutputFile,  sizeof(gszOutputFile)  ); 

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_UI));

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

//
//  FUNCTION: UIRegisterClass()
//
//  PURPOSE: Registers the window class.
//
ATOM UIRegisterClass(
                     HINSTANCE hInstance
                     )
{
    WNDCLASSEX wcex;

    wcex.cbSize         = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_UI));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = CreateSolidBrush( GetSysColor(COLOR_3DFACE) );
    wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_UI);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_UI)); 

    return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//   In this function, we save the instance handle in a global variable,
//   create and display the main program window.
//
BOOL InitInstance(
                  HINSTANCE hInstance, 
                  int nCmdShow
                  )
{
    hInst = hInstance; // Store instance handle in our global variable

    ghWnd = CreateWindow(
        szWindowClass,                          // LPCTSTR lpClassName
        "FBX SDK CubeCreator sample program",   // LPCTSTR lpWindowName 
        WS_OVERLAPPED | WS_SYSMENU,             // DWORD dwStyle
        400,                                    // int x
        200,                                    // int Y
        700,                                    // int nWidth
        800,                                    // int nHeight
        NULL,                                   // HWND hWndParent
        NULL,                                   // HMENU hMenu
        hInstance,                              // HINSTANCE hInstance
        NULL                                    // LPVOID lpParam
        );

    if (!ghWnd)
    {
        return FALSE;
    }

    // Get the path of the application (.exe module)
    char szFilePath[MAX_PATH];
    if( GetModuleFileName(NULL, szFilePath, MAX_PATH) )
    {
        // extract the directory only
        gAppPath = GetDirectoryFromFilePath(szFilePath);
    }

    ShowWindow(ghWnd, nCmdShow);
    UpdateWindow(ghWnd);

    return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
LRESULT CALLBACK WndProc(
                         HWND hWnd, 
                         UINT message, 
                         WPARAM wParam, 
                         LPARAM lParam
                         )
{
    int wmId, wmEvent;

    switch (message)
    {

    case WM_CREATE:
        {
            // Create GUI controls
            CreateUIControls(hWnd);
        }
        break;

    case WM_SHOWWINDOW :
        {
            if(gSdkManager == NULL)
            {
                // create a basic scene
                CreateScene();

                // show the scene content in the treeview
                FillTreeView( hWnd );
            }
        }
        break;

    case WM_COMMAND:

        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);

        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;

        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;

        case SAVE_TO_BUTTON:
            GetOutputFileName(hWnd);            // ask for file name
            ExportFile();                       // save the file
            AskForPlayInQuickTimePlayer(hWnd);  // ask to play the file in QuickTime player
            break;

        case ADD_CUBE_BUTTON:
            {
                bool lWithMaterial  = (1 == IsDlgButtonChecked( hWnd, MATERIAL_CHECKBOX   ));
                bool lWithTexture   = (1 == IsDlgButtonChecked( hWnd, TEXTURE_CHECKBOX    ));
                bool lWithAnimation = (1 == IsDlgButtonChecked( hWnd, ANIMATION_CHECKBOX  ));

                // create a new cube with option selected
                CreateCube(lWithMaterial, lWithTexture, lWithAnimation);

                // show scene content
                FillTreeView( hWnd );
            }
            break;

        case REMOVE_CUBES_BUTTON:

            // remove all cubes
            RemoveCubes();

            // show scene content
            FillTreeView( hWnd );
            break;

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;

    case WM_DESTROY:

        // dont forget to delete the SdkManager 
        // and all objects created by the SDK manager
        DestroySdkObjects(gSdkManager);

        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(
                       HWND hDlg, 
                       UINT message, 
                       WPARAM wParam, 
                       LPARAM lParam
                       )
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        {
            // set the FBX app. icon
            HINSTANCE hinst = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hDlg, GWLP_HINSTANCE); 


            HICON hIconFBX = (HICON) LoadImage( hinst, MAKEINTRESOURCE(IDI_UI), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE); 
            ::SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIconFBX); 
        }
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

// Create the UI children controls
void CreateUIControls(
                      HWND hWndParent
                      )
{
    DWORD dwStyle = WS_CHILD | WS_VISIBLE;

    // create the <Save to> button
    CreateWindowEx( 
        0,                              // DWORD dwExStyle,
        "BUTTON",                       // LPCTSTR lpClassName
        "Save to ...",                  // control caption
        dwStyle,                        // DWORD dwStyle
        10,                             // int x
        10,                             // int y
        130,                            // int nWidth
        30,                             // int nHeight    
        hWndParent,                     // HWND hWndParent
        (HMENU) SAVE_TO_BUTTON,         // HMENU hMenu or control's ID for WM_COMMAND 
        hInst,                          // HINSTANCE hInstance
        NULL                            // LPVOID lpParam
        );

    // create the <Add cube> button
    CreateWindowEx( 
        0,                              // DWORD dwExStyle,
        "BUTTON",                       // LPCTSTR lpClassName
        "Add cube",                     // control caption
        dwStyle,                        // DWORD dwStyle
        10,                             // int x
        710,                            // int y
        130,                            // int nWidth
        30,                             // int nHeight    
        hWndParent,                     // HWND hWndParent
        (HMENU) ADD_CUBE_BUTTON,        // HMENU hMenu or control's ID for WM_COMMAND 
        hInst,                          // HINSTANCE hInstance
        NULL                            // LPVOID lpParam
        );

    // create the <Material> checkbox
    CreateWindowEx( 
        0,                              // DWORD dwExStyle,
        "BUTTON",                       // LPCTSTR lpClassName
        "Material",                     // control caption
        dwStyle|BS_AUTOCHECKBOX,        // DWORD dwStyle
        150,                            // int x
        710,                            // int y
        80,                             // int nWidth
        30,                             // int nHeight    
        hWndParent,                     // HWND hWndParent
        (HMENU) MATERIAL_CHECKBOX,      // HMENU hMenu or control's ID for WM_COMMAND 
        hInst,                          // HINSTANCE hInstance
        NULL                            // LPVOID lpParam
        );

    // create the <Texture> checkbox
    CreateWindowEx( 
        0,                              // DWORD dwExStyle,
        "BUTTON",                       // LPCTSTR lpClassName
        "Texture",                      // control caption
        dwStyle|BS_AUTOCHECKBOX,        // DWORD dwStyle
        240,                            // int x
        710,                            // int y
        80,                             // int nWidth
        30,                             // int nHeight    
        hWndParent,                     // HWND hWndParent
        (HMENU) TEXTURE_CHECKBOX,       // HMENU hMenu or control's ID for WM_COMMAND 
        hInst,                          // HINSTANCE hInstance
        NULL                            // LPVOID lpParam
        );

    // set <Texture> checked by default
    CheckDlgButton(hWndParent, TEXTURE_CHECKBOX, 1);

    // create the <Animation> checkbox
    CreateWindowEx( 
        0,                              // DWORD dwExStyle,
        "BUTTON",                       // LPCTSTR lpClassName
        "Animation",                    // control caption
        dwStyle|BS_AUTOCHECKBOX,        // DWORD dwStyle
        330,                            // int x
        710,                            // int y
        90,                             // int nWidth
        30,                             // int nHeight    
        hWndParent,                     // HWND hWndParent
        (HMENU) ANIMATION_CHECKBOX,     // HMENU hMenu or control's ID for WM_COMMAND 
        hInst,                          // HINSTANCE hInstance
        NULL                            // LPVOID lpParam
        );

    // set <Animation> checked by default
    CheckDlgButton(hWndParent, ANIMATION_CHECKBOX, 1);


    // create the <Remove cube> button
    CreateWindowEx( 
        0,                              // DWORD dwExStyle,
        "BUTTON",                       // LPCTSTR lpClassName
        "Remove cubes",                 // control caption
        dwStyle,                        // DWORD dwStyle
        555,                            // int x
        710,                            // int y
        130,                            // int nWidth
        30,                             // int nHeight    
        hWndParent,                     // HWND hWndParent
        (HMENU) REMOVE_CUBES_BUTTON,    // HMENU hMenu or control's ID for WM_COMMAND 
        hInst,                          // HINSTANCE hInstance
        NULL                            // LPVOID lpParam
        );

    // create the <Save to> edit box
    CreateWindowEx( 
        WS_EX_STATICEDGE,               // DWORD dwExStyle,
        "EDIT",                         // LPCTSTR lpClassName
        " <- select a file to save",    // control caption
        dwStyle|ES_AUTOHSCROLL,         // DWORD dwStyle
        150,                            // int x
        15,                             // int y
        534,                            // int nWidth
        20,                             // int nHeight    
        hWndParent,                     // HWND hWndParent
        (HMENU) SAVE_TO_EDITBOX,        // HMENU hMenu or control's ID for WM_COMMAND 
        hInst,                          // HINSTANCE hInstance
        NULL                            // LPVOID lpParam
        );

    // create a small font 
    HFONT hf = CreateFont(
        14,                 // height of font
        6,                  // average character width
        0,                  // angle of escapement
        0,                  // base-line orientation angle
        40,                 // font weight
        0,                  // italic attribute option
        0,                  // underline attribute option
        0,                  // strikeout attribute option
        ANSI_CHARSET,       // character set identifier
        OUT_DEFAULT_PRECIS, // output precision
        CLIP_DEFAULT_PRECIS,// clipping precision
        0,              // output quality
        0,                  // pitch and family
        "Arial"             // typeface name
        );

    // set the font for the SAVE_TO_EDITBOX
    SendMessage(GetDlgItem(hWndParent, SAVE_TO_EDITBOX), WM_SETFONT, (WPARAM) hf, (LPARAM) false );  

    // create the <Tree view> control
    dwStyle = dwStyle | TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS;

    CreateWindowEx( 
        WS_EX_STATICEDGE,               // DWORD dwExStyle,
        WC_TREEVIEW,                    // LPCTSTR lpClassName
        "",                             // control caption
        dwStyle,                        // DWORD dwStyle
        10,                             // int x
        50,                             // int y
        674,                            // int nWidth
        646,                            // int nHeight    
        hWndParent,                     // HWND hWndParent
        (HMENU) FBX_TREEVIEW,           // HMENU hMenu or control's ID for WM_COMMAND 
        hInst,                          // HINSTANCE hInstance
        NULL                            // LPVOID lpParam
        );
}

// show the <Save file> dialog
void GetOutputFileName(
                       HWND hWndParent
                       )
{
    OPENFILENAME ofn;
    ZeroMemory(&ofn, sizeof(ofn));

    char szFile[MAX_PATH];  // buffer for file name
    ZeroMemory(szFile, sizeof(szFile));

    // Initialize OPENFILENAME
    ofn.lStructSize     = sizeof(ofn);
    ofn.hwndOwner       = hWndParent;
    ofn.lpstrFile       = szFile;
    ofn.nMaxFile        = sizeof(szFile)/ sizeof(*szFile); 
    ofn.nFilterIndex    = 1;      // *.fbx binairy by default
    ofn.lpstrFileTitle  = NULL;
    ofn.nMaxFileTitle   = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.lpstrTitle      = "Select the file to export to ... (use the file type filter)";
    ofn.Flags           = OFN_EXPLORER | OFN_OVERWRITEPROMPT;

    // get a description of all writers registered in the FBX SDK
    const char *filter  = GetWriterSFNFilters();
    ofn.lpstrFilter     = filter;

    // Display the save as dialog box. 
    if(GetSaveFileName(&ofn) == false)
    {
        ZeroMemory(gszOutputFile,  sizeof(gszOutputFile)  ); 

        // User cancel ...
        delete filter;
        return;
    }

    delete filter;

    // keep the selected file format writer
    // ofn.nFilterIndex is not 0 based but start at 1, the FBX SDK file format enum start at 0
    gWriteFileFormat = ofn.nFilterIndex - 1; 

    // get the extention string from the file format selected by the user
    const char * ext = GetFileFormatExt( gWriteFileFormat );

    // check for file extention
    if(ExtExist(szFile, ext) == false)
    {
        // add the selected file extention
        strcat(szFile, ext);
    }

    delete ext;

    // show the file name selected with the extention
    SetWindowText( GetDlgItem(hWndParent, SAVE_TO_EDITBOX), szFile);

    // Keep a copy of the file name
    strcpy(gszOutputFile, szFile);
}

// to save the file selected
void ExportFile()
{
    if(strlen(gszOutputFile) == 0) return;

    Export(gszOutputFile, gWriteFileFormat);
}

// check if in the filepath the file extention exist
bool ExtExist(
              const char * filepath, 
              const char * ext
              )
{
    int iExtLen = (int)strlen(ext);
    int ifpLen  = (int)strlen(filepath);

    if( ifpLen < iExtLen) return false;

    int x = ifpLen - iExtLen;

    for(int i=0; i < iExtLen; i++)
    {
        if(filepath[x] != ext[i] ) return false;
        x++;
    }

    return true;
}

// extract the directory from a file path
KString GetDirectoryFromFilePath( const char *pFilePath )
{
    char   PathName[1024];
    char*  PathNamePtr;

    K_ASSERT( pFilePath );
    K_ASSERT( strlen( pFilePath ) < 1024 );

    strcpy(PathName,pFilePath);
    PathNamePtr=strrchr(PathName,'/');

    if (!PathNamePtr) {
        PathNamePtr=strrchr(PathName,'\\');
    }

    if (PathNamePtr) {
        (*PathNamePtr) = '\0';
    }
    else
    {
        PathName[0] = 0;
    }

    return KString(PathName);
}

void AskForPlayInQuickTimePlayer(HWND pHwnd )
{
    // check if we have a valid file name
    if( strlen(gszOutputFile) == 0) return;

    if(MessageBox(pHwnd, "Play saved file in QuickTime player?\n\n(The FBX QuickTime plug-in must be installed.)", "QuickTime player", MB_YESNO) == IDNO) return;
    ShellExecute(NULL, "open", "QuickTimePlayer.exe", gszOutputFile, NULL, SW_SHOWNORMAL);
}

// used to add a new treeview item
HTREEITEM InsertTreeViewItem(
                             const HWND hTv, 
                             const char *txt, 
                             HTREEITEM htiParent
                             )
{
    TVITEM tvi      = {0};
    tvi.mask        = TVIF_TEXT|TVIF_PARAM;           // text + param only
    tvi.pszText     = (LPSTR)txt;                     // caption
    tvi.cchTextMax  = static_cast<int>(strlen(txt));  // length of item label

    TVINSERTSTRUCT tvis = {0};
    tvis.item           = tvi; 
    tvis.hInsertAfter   = 0;
    tvis.hParent        = htiParent;                  // parent item of item to be inserted

    return reinterpret_cast<HTREEITEM>( SendMessage(hTv, TVM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&tvis)) );
}

// used to expand all treeview nodes
void Expand_All()
{
    // get the handle of the treeview
    HWND htv = GetDlgItem(ghWnd, FBX_TREEVIEW);
    if(htv == NULL) return;

    Expand_All_Recurse(htv, TreeView_GetRoot(htv));

    // force the root node visible on expand
    TreeView_SelectSetFirstVisible(htv, TreeView_GetRoot(htv) );
}

// used to expand all treeview items recursively
void Expand_All_Recurse(
                        HWND htv, 
                        HTREEITEM htvi
                        )
{
    if(htvi == NULL) return;

    TreeView_Expand(htv, htvi, TVE_EXPAND);

    while(htvi)
    {
        // expand all children
        htvi = TreeView_GetChild(htv, htvi);
        Expand_All_Recurse(htv, htvi);

        // expand all siblings
        while(htvi)
        {
            htvi = TreeView_GetNextSibling(htv, htvi);
            Expand_All_Recurse(htv, htvi);
        }
    }
}

// used to add the rootNode name and start to add children nodes
void DisplayHierarchy(
                      const HWND hTv
                      )
{
    HTREEITEM htvi = InsertTreeViewItem(hTv, GetRootNodeName(), TVI_ROOT);

    for(int i = 0; i < GetRootNode()->GetChildCount(); i++)
    {
        DisplayHierarchyRecurse(GetRootNode()->GetChild(i), hTv, htvi);
    }
}

// used to recursively add children nodes
void DisplayHierarchyRecurse(
                             const KFbxNode* pNode, 
                             const HWND hTv, 
                             HTREEITEM htiParent
                             )
{
    // create a new Treeview item with node name and Attribute type name
    HTREEITEM htvi = InsertTreeViewItem(hTv, GetNodeNameAndAttributeTypeName(pNode).Buffer(), htiParent);

    // show some KFbxNode parameters
    AddTreeViewItemKFbxNodeParameters(pNode, hTv, htvi);

    for(int i = 0; i < pNode->GetChildCount(); i++)
    {
        // recursively call this
        DisplayHierarchyRecurse(pNode->GetChild(i), hTv, htvi);
    }
}

// used to add KFbxNode parameters
void AddTreeViewItemKFbxNodeParameters( 
                                       const KFbxNode* pNode,
                                       HWND hTv, 
                                       HTREEITEM htiParent 
                                       )
{
    if(pNode == NULL) return;

    // show node default translation
    InsertTreeViewItem(hTv, GetDefaultTranslationInfo(pNode).Buffer(),  htiParent);

    // show if a material, texture or animation is in the node
    InsertTreeViewItem(hTv, GetNodeInfo(pNode).Buffer(),  htiParent);
}


// fill the treeview with the FBX scene content
void FillTreeView(
                  const HWND mainHwnd
                  )
{
    // get the handle of the treeview
    HWND htv = GetDlgItem(mainHwnd, FBX_TREEVIEW);
    if(htv == NULL) return;

    // clear the treeview content
    TreeView_DeleteAllItems(htv);

    // display scene hierarchy
    DisplayHierarchy(htv);

    // expand all items of the treeview
    Expand_All();

    // force the root node visible
    TreeView_SelectSetFirstVisible(htv,  TreeView_GetRoot(htv) );
}