#include "stdafx.h"
#include <commctrl.h>
#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
HINSTANCE hInst;
HWND ghWnd = NULL;
TCHAR szTitle[MAX_LOADSTRING];
TCHAR szWindowClass[MAX_LOADSTRING];
char gszOutputFile[MAX_PATH];
int gWriteFileFormat = -1;
extern KFbxSdkManager *gSdkManager;
extern KFbxScene *gScene;
extern KString gAppPath;
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);
bool ExtExist(const char * filepath, const char * ext);
KString GetDirectoryFromFilePath(const char *pFilePath);
void ExportFile();
void AskForPlayInQuickTimePlayer(HWND pHwnd);
HTREEITEM InsertTreeViewItem(const HWND hTv, const char *txt, HTREEITEM htiParent);
void Expand_All();
void Expand_All_Recurse(HWND htv, HTREEITEM htvi);
void DisplayHierarchy(const HWND hTv);
void DisplayHierarchyRecurse(const KFbxNode* pNode, HWND hTv, HTREEITEM htiParent);
void AddTreeViewItemKFbxNodeParameters(const KFbxNode* pNode, HWND hTv, HTREEITEM htiParent);
void FillTreeView(const HWND mainHwnd);
int APIENTRY _tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow
)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
HACCEL hAccelTable;
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_UI, szWindowClass, MAX_LOADSTRING);
UIRegisterClass(hInstance);
ZeroMemory(gszOutputFile, sizeof(gszOutputFile) );
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_UI));
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
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);
}
BOOL InitInstance(
HINSTANCE hInstance,
int nCmdShow
)
{
hInst = hInstance;
ghWnd = CreateWindow(
szWindowClass,
"FBX SDK CubeCreator sample program",
WS_OVERLAPPED | WS_SYSMENU,
400,
200,
700,
800,
NULL,
NULL,
hInstance,
NULL
);
if (!ghWnd)
{
return FALSE;
}
char szFilePath[MAX_PATH];
if( GetModuleFileName(NULL, szFilePath, MAX_PATH) )
{
gAppPath = GetDirectoryFromFilePath(szFilePath);
}
ShowWindow(ghWnd, nCmdShow);
UpdateWindow(ghWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
int wmId, wmEvent;
switch (message)
{
case WM_CREATE:
{
CreateUIControls(hWnd);
}
break;
case WM_SHOWWINDOW :
{
if(gSdkManager == NULL)
{
CreateScene();
FillTreeView( hWnd );
}
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
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);
ExportFile();
AskForPlayInQuickTimePlayer(hWnd);
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 ));
CreateCube(lWithMaterial, lWithTexture, lWithAnimation);
FillTreeView( hWnd );
}
break;
case REMOVE_CUBES_BUTTON:
RemoveCubes();
FillTreeView( hWnd );
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
DestroySdkObjects(gSdkManager);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
INT_PTR CALLBACK About(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
{
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;
}
void CreateUIControls(
HWND hWndParent
)
{
DWORD dwStyle = WS_CHILD | WS_VISIBLE;
CreateWindowEx(
0,
"BUTTON",
"Save to ...",
dwStyle,
10,
10,
130,
30,
hWndParent,
(HMENU) SAVE_TO_BUTTON,
hInst,
NULL
);
CreateWindowEx(
0,
"BUTTON",
"Add cube",
dwStyle,
10,
710,
130,
30,
hWndParent,
(HMENU) ADD_CUBE_BUTTON,
hInst,
NULL
);
CreateWindowEx(
0,
"BUTTON",
"Material",
dwStyle|BS_AUTOCHECKBOX,
150,
710,
80,
30,
hWndParent,
(HMENU) MATERIAL_CHECKBOX,
hInst,
NULL
);
CreateWindowEx(
0,
"BUTTON",
"Texture",
dwStyle|BS_AUTOCHECKBOX,
240,
710,
80,
30,
hWndParent,
(HMENU) TEXTURE_CHECKBOX,
hInst,
NULL
);
CheckDlgButton(hWndParent, TEXTURE_CHECKBOX, 1);
CreateWindowEx(
0,
"BUTTON",
"Animation",
dwStyle|BS_AUTOCHECKBOX,
330,
710,
90,
30,
hWndParent,
(HMENU) ANIMATION_CHECKBOX,
hInst,
NULL
);
CheckDlgButton(hWndParent, ANIMATION_CHECKBOX, 1);
CreateWindowEx(
0,
"BUTTON",
"Remove cubes",
dwStyle,
555,
710,
130,
30,
hWndParent,
(HMENU) REMOVE_CUBES_BUTTON,
hInst,
NULL
);
CreateWindowEx(
WS_EX_STATICEDGE,
"EDIT",
" <- select a file to save",
dwStyle|ES_AUTOHSCROLL,
150,
15,
534,
20,
hWndParent,
(HMENU) SAVE_TO_EDITBOX,
hInst,
NULL
);
HFONT hf = CreateFont(
14,
6,
0,
0,
40,
0,
0,
0,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
0,
0,
"Arial"
);
SendMessage(GetDlgItem(hWndParent, SAVE_TO_EDITBOX), WM_SETFONT, (WPARAM) hf, (LPARAM) false );
dwStyle = dwStyle | TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS;
CreateWindowEx(
WS_EX_STATICEDGE,
WC_TREEVIEW,
"",
dwStyle,
10,
50,
674,
646,
hWndParent,
(HMENU) FBX_TREEVIEW,
hInst,
NULL
);
}
void GetOutputFileName(
HWND hWndParent
)
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
char szFile[MAX_PATH];
ZeroMemory(szFile, sizeof(szFile));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWndParent;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile)/ sizeof(*szFile);
ofn.nFilterIndex = 1;
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;
const char *filter = GetWriterSFNFilters();
ofn.lpstrFilter = filter;
if(GetSaveFileName(&ofn) == false)
{
ZeroMemory(gszOutputFile, sizeof(gszOutputFile) );
delete filter;
return;
}
delete filter;
gWriteFileFormat = ofn.nFilterIndex - 1;
const char * ext = GetFileFormatExt( gWriteFileFormat );
if(ExtExist(szFile, ext) == false)
{
strcat(szFile, ext);
}
delete ext;
SetWindowText( GetDlgItem(hWndParent, SAVE_TO_EDITBOX), szFile);
strcpy(gszOutputFile, szFile);
}
void ExportFile()
{
if(strlen(gszOutputFile) == 0) return;
Export(gszOutputFile, gWriteFileFormat);
}
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;
}
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 )
{
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);
}
HTREEITEM InsertTreeViewItem(
const HWND hTv,
const char *txt,
HTREEITEM htiParent
)
{
TVITEM tvi = {0};
tvi.mask = TVIF_TEXT|TVIF_PARAM;
tvi.pszText = (LPSTR)txt;
tvi.cchTextMax = static_cast<int>(strlen(txt));
TVINSERTSTRUCT tvis = {0};
tvis.item = tvi;
tvis.hInsertAfter = 0;
tvis.hParent = htiParent;
return reinterpret_cast<HTREEITEM>( SendMessage(hTv, TVM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&tvis)) );
}
void Expand_All()
{
HWND htv = GetDlgItem(ghWnd, FBX_TREEVIEW);
if(htv == NULL) return;
Expand_All_Recurse(htv, TreeView_GetRoot(htv));
TreeView_SelectSetFirstVisible(htv, TreeView_GetRoot(htv) );
}
void Expand_All_Recurse(
HWND htv,
HTREEITEM htvi
)
{
if(htvi == NULL) return;
TreeView_Expand(htv, htvi, TVE_EXPAND);
while(htvi)
{
htvi = TreeView_GetChild(htv, htvi);
Expand_All_Recurse(htv, htvi);
while(htvi)
{
htvi = TreeView_GetNextSibling(htv, htvi);
Expand_All_Recurse(htv, htvi);
}
}
}
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);
}
}
void DisplayHierarchyRecurse(
const KFbxNode* pNode,
const HWND hTv,
HTREEITEM htiParent
)
{
HTREEITEM htvi = InsertTreeViewItem(hTv, GetNodeNameAndAttributeTypeName(pNode).Buffer(), htiParent);
AddTreeViewItemKFbxNodeParameters(pNode, hTv, htvi);
for(int i = 0; i < pNode->GetChildCount(); i++)
{
DisplayHierarchyRecurse(pNode->GetChild(i), hTv, htvi);
}
}
void AddTreeViewItemKFbxNodeParameters(
const KFbxNode* pNode,
HWND hTv,
HTREEITEM htiParent
)
{
if(pNode == NULL) return;
InsertTreeViewItem(hTv, GetDefaultTranslationInfo(pNode).Buffer(), htiParent);
InsertTreeViewItem(hTv, GetNodeInfo(pNode).Buffer(), htiParent);
}
void FillTreeView(
const HWND mainHwnd
)
{
HWND htv = GetDlgItem(mainHwnd, FBX_TREEVIEW);
if(htv == NULL) return;
TreeView_DeleteAllItems(htv);
DisplayHierarchy(htv);
Expand_All();
TreeView_SelectSetFirstVisible(htv, TreeView_GetRoot(htv) );
}