/**************************************************************************************** Copyright (C) 2015 Autodesk, Inc. All rights reserved. Use of this software is subject to the terms of the Autodesk license agreement provided at the time of installation or download, or which otherwise accompanies this software in either electronic or hard copy form. ****************************************************************************************/ // UI.cxx : Defines the entry point for the application. #include "stdafx.h" #include // for treeview control #include "UI.h" #include "SDK_Utility.h" #define MAX_LOADSTRING 100 #define READ_FROM_BUTTON 1000 #define READ_FROM_EDITBOX 1001 #define FBX_TREEVIEW 1002 // 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 gszInputFile[_MAX_PATH]; // File name to import extern FbxManager *gSdkManager; // access to the global SdkManager object extern FbxScene *gScene; // access to the global scene object // 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 GetInputFileName(HWND hWndParent); //----------------------------------------------------------- // 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 DisplayHierarchy_Recurse(const FbxNode* pNode, HWND hTv, HTREEITEM htiParent); // used to add FbxNode attributes parameters void Add_TreeViewItem_KFbxNode_Parameters(const FbxNode* pNode, HWND hTv, HTREEITEM htiParent); // used to fill the treeview with the FBX scene content void Fill_TreeView(const HWND mainHwnd); static bool gAutoQuit = false; //---------------------------------------------------------- // entry point for the application int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow ) { UNREFERENCED_PARAMETER(hPrevInstance); if( FbxString(lpCmdLine) == "-test" ) gAutoQuit = true; 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(gszInputFile, sizeof(gszInputFile) ); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_UI)); // Main message loop: while( GetMessage(&msg, NULL, 0, 0) && !gAutoQuit ) { 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 SceneTreeView 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; } 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: { CreateUIControls(hWnd); InitializeSdkManagerAndScene(); } 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 READ_FROM_BUTTON: GetInputFileName(hWnd); // ask user for a FBX file path Fill_TreeView(hWnd); // fill the treeview with the scene content break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_DESTROY: DestroySdkObjects(gSdkManager, true); 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 button CreateWindowEx( 0, // DWORD dwExStyle, "BUTTON", // LPCTSTR lpClassName "Read from ...", // control caption dwStyle, // DWORD dwStyle 10, // int x 10, // int y 130, // int nWidth 30, // int nHeight hWndParent, // HWND hWndParent (HMENU) READ_FROM_BUTTON, // HMENU hMenu or control's ID for WM_COMMAND hInst, // HINSTANCE hInstance NULL // LPVOID lpParam ); // create the edit box CreateWindowEx( WS_EX_STATICEDGE, // DWORD dwExStyle, "EDIT", // LPCTSTR lpClassName " <- select a file to read", // control caption dwStyle|ES_AUTOHSCROLL, // DWORD dwStyle 150, // int x 15, // int y 534, // int nWidth 20, // int nHeight hWndParent, // HWND hWndParent (HMENU) READ_FROM_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 READ_FROM_EDITBOX SendMessage(GetDlgItem(hWndParent, READ_FROM_EDITBOX), WM_SETFONT, (WPARAM) hf, (LPARAM) false ); // create the 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 686, // 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 dialog void GetInputFileName( 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); ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = "Select the file to read ... (use the file type filter)"; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; // get a description of all readers registered in the FBX SDK const char *filter = GetReaderOFNFilters(); ofn.lpstrFilter = filter; // Display the Open dialog box. if(GetOpenFileName(&ofn) == false) { // user cancel delete filter; return; } delete filter; // show the file name selected SetWindowText( GetDlgItem(hWndParent, READ_FROM_EDITBOX), szFile ); // Keep a copy of the file name FBXSDK_strcpy(gszInputFile, _MAX_PATH, szFile); } // 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(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( SendMessage(hTv, TVM_INSERTITEM, 0, reinterpret_cast(&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++) { DisplayHierarchy_Recurse(GetRootNode()->GetChild(i), hTv, htvi); } } // used to recursively add children nodes void DisplayHierarchy_Recurse( const FbxNode* 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 FbxNode parameters Add_TreeViewItem_KFbxNode_Parameters(pNode, hTv, htvi); for(int i = 0; i < pNode->GetChildCount(); i++) { // recursively call this DisplayHierarchy_Recurse(pNode->GetChild(i), hTv, htvi); } } // used to add FbxNode parameters void Add_TreeViewItem_KFbxNode_Parameters( const FbxNode* pNode, HWND hTv, HTREEITEM htiParent ) { if(pNode == NULL) return; // show node default translation InsertTreeViewItem(hTv, GetDefaultTranslationInfo(pNode).Buffer(), htiParent); // show node visibility InsertTreeViewItem(hTv, GetNodeVisibility(pNode).Buffer(), htiParent); } // fill the treeview with the FBX scene content void Fill_TreeView( const HWND mainHwnd ) { if(strlen(gszInputFile) == 0) return; // get the handle of the treeview HWND htv = GetDlgItem(mainHwnd, FBX_TREEVIEW); if(htv == NULL) return; // clear the treeview content TreeView_DeleteAllItems(htv); // show a wait cursor HCURSOR oldCursor = SetCursor( LoadCursor(NULL, IDC_WAIT) ); // load the FBX scene if(LoadFBXScene(gszInputFile) == false) { // reset to default cursor SetCursor(oldCursor); return; } // display scene hierarchy DisplayHierarchy(htv); // expand all items of the treeview Expand_All(); // force the root node visible TreeView_SelectSetFirstVisible(htv, TreeView_GetRoot(htv) ); // reset to default cursor SetCursor(oldCursor); }