549 lines
17 KiB
C++
Executable File
549 lines
17 KiB
C++
Executable File
/****************************************************************************************
|
|
|
|
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 <commctrl.h> // 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 <Read from> 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 <Read from> 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 <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
|
|
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 <Open file> 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<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++)
|
|
{
|
|
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);
|
|
}
|