propshet.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "StdAfx.h"
  19. #include "priv.h"
  20. #include "shellext.h"
  21. #include "resource.h"
  22. #include <stdio.h>
  23. #include "wdump.h"
  24. #include "WdumpDoc.h"
  25. #include "W3D_File.h"
  26. #include <commctrl.h>
  27. //===============================================================
  28. // *********** G L O B A L S ************************
  29. extern UINT g_DllRefCount; // Reference count of this DLL.
  30. extern HINSTANCE g_DllInstance; // Handle to this DLL itself.
  31. //===============================================================
  32. // *********** F U N C T I O N S *********************
  33. ///////////////////////////////////////
  34. UINT CALLBACK W3DPageCallback(HWND hWnd,
  35. UINT uMessage,
  36. LPPROPSHEETPAGE ppsp){
  37. switch(uMessage){
  38. case PSPCB_CREATE:
  39. return TRUE;
  40. case PSPCB_RELEASE:{
  41. if (ppsp->lParam){
  42. ((LPCSHELLEXT)(ppsp->lParam))->Release();
  43. }
  44. return TRUE;
  45. }
  46. }
  47. return TRUE;
  48. }
  49. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50. void ShowHideControls(HWND hDlg, bool show){
  51. HWND hControl = GetWindow(hDlg, GW_CHILD);
  52. while(hControl != NULL){
  53. ShowWindow(hControl,show?SW_SHOW:SW_HIDE);
  54. hControl = GetWindow(hControl, GW_HWNDNEXT);
  55. }
  56. ShowWindow(GetDlgItem(hDlg, IDC_NODATA),show?SW_HIDE:SW_SHOW );
  57. }
  58. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  59. void GetItemName(ChunkItem *pItem, int id_of_interest, void* pInfo, int sizeof_struct, int& found ){
  60. if(pItem->ID == id_of_interest){
  61. BYTE *byte_ptr = (BYTE*) pInfo;
  62. byte_ptr += sizeof_struct* found;
  63. memcpy(byte_ptr,pItem->Data,pItem->Length);
  64. found ++;
  65. }
  66. //Get all Sibitems for this item
  67. POSITION p = pItem->Chunks.GetHeadPosition();
  68. while(p != 0) {
  69. ChunkItem *subitem = pItem->Chunks.GetNext(p);
  70. GetItemName(subitem, id_of_interest, pInfo, sizeof_struct,found);
  71. }
  72. }
  73. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74. BOOL CALLBACK AnimPageDlgProc(HWND hDlg,UINT uMessage, WPARAM wParam, LPARAM lParam){
  75. LPPROPSHEETPAGE psp=(LPPROPSHEETPAGE)GetWindowLong(hDlg, DWL_USER);
  76. UINT iIndex=0;
  77. LPCSHELLEXT lpcs;
  78. char buf[MAX_PATH];
  79. switch (uMessage){
  80. case WM_INITDIALOG:{
  81. SetWindowLong(hDlg, DWL_USER, lParam);
  82. psp = (LPPROPSHEETPAGE)lParam;
  83. lpcs = (LPCSHELLEXT)psp->lParam;
  84. if(!lpcs->m_FileInMemory){
  85. lpcs->Read_SelectedFile();
  86. }
  87. ChunkData* pData = &(lpcs->m_WdumpDocument.m_ChunkData);
  88. assert(pData);
  89. POSITION ptr = pData->Chunks.GetHeadPosition();;
  90. ASSERT(ptr);
  91. W3dAnimHeaderStruct* pAnim = lpcs->m_AnimInfos;
  92. int id_of_interest = W3D_CHUNK_ANIMATION_HEADER;
  93. int sizeof_struct = sizeof W3dAnimHeaderStruct;
  94. int found_animations(0);
  95. while(ptr){
  96. ChunkItem *pItem = pData->Chunks.GetNext(ptr);
  97. GetItemName(pItem, id_of_interest, (void*)lpcs->m_AnimInfos, sizeof_struct, found_animations );
  98. }
  99. if(found_animations){
  100. //So far assuming only one animation per file
  101. SetDlgItemText(hDlg, IDC_ANIMNAME, pAnim->Name);
  102. SetDlgItemText(hDlg, IDC_HNAME, pAnim->HierarchyName);
  103. SetDlgItemInt(hDlg, IDC_NUMFRAMES, pAnim->NumFrames,FALSE);
  104. //FrameRate
  105. sprintf(buf,"%i fps",pAnim->FrameRate,FALSE);
  106. SetDlgItemText(hDlg, IDC_FRAMERATE, buf);
  107. //SetDlgItemInt(hDlg, IDC_FRAMERATE, pAnim->FrameRate,FALSE);
  108. //version
  109. sprintf(buf,"%d.%d",W3D_GET_MAJOR_VERSION(pAnim->Version),W3D_GET_MINOR_VERSION(pAnim->Version));
  110. SetDlgItemText(hDlg, IDC_ANIMVERSION, buf);
  111. }
  112. //Hierarchies
  113. ptr = pData->Chunks.GetHeadPosition();;
  114. ASSERT(ptr);
  115. id_of_interest = W3D_CHUNK_HIERARCHY_HEADER;
  116. //So far assuming only one hierarchy per file
  117. W3dHierarchyStruct* pHInfo = lpcs->m_Hierarchies;
  118. ASSERT(pHInfo);
  119. sizeof_struct = sizeof W3dHierarchyStruct;
  120. int found_hierarchies(0);
  121. while(ptr){
  122. ChunkItem *pItem = pData->Chunks.GetNext(ptr);
  123. GetItemName(pItem, id_of_interest, (void*)pHInfo, sizeof_struct, found_hierarchies );
  124. }
  125. if(found_hierarchies){
  126. SetDlgItemText(hDlg, IDC_HIERARCHYNAME, pHInfo->Name);
  127. SetDlgItemInt(hDlg, IDC_NUMPIVOTS, pHInfo->NumPivots,FALSE);
  128. sprintf(buf,"%d.%d",W3D_GET_MAJOR_VERSION(pHInfo->Version),W3D_GET_MINOR_VERSION(pHInfo->Version));
  129. SetDlgItemText(hDlg, IDC_HIERARCHYVERSION, buf);
  130. sprintf(buf, "(%.3f, %.3f, %.3f)", pHInfo->Center.X, pHInfo->Center.Y, pHInfo->Center.Z);
  131. SetDlgItemText(hDlg, IDC_HCENTER, buf);
  132. }
  133. ShowHideControls(hDlg, (found_animations + found_hierarchies)!= 0);
  134. break;
  135. }
  136. case WM_DESTROY:{
  137. RemoveProp(hDlg, "ID");
  138. break;
  139. }
  140. case WM_COMMAND:
  141. switch (LOWORD(wParam)){
  142. case IDC_TOP3D:
  143. //SetProp(hDlg, "ID", (HANDLE)lParam);
  144. break;
  145. default:
  146. break;
  147. }
  148. break;
  149. case WM_NOTIFY:
  150. switch (((NMHDR FAR *)lParam)->code){
  151. case PSN_SETACTIVE:
  152. break;
  153. case PSN_APPLY:
  154. //User has clicked the OK or Apply button so we'll
  155. //update the icon information in the .W3D file
  156. lpcs = (LPCSHELLEXT)psp->lParam;
  157. //Ask the shell to refresh the icon list...
  158. //SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, 0, 0);
  159. break;
  160. default:
  161. break;
  162. }
  163. break;
  164. default:
  165. return FALSE;
  166. }
  167. return TRUE;
  168. }
  169. //=====================================================================================================
  170. void SetDlgMeshParams(HWND hDlg, W3dMeshHeader3Struct*pInfo){
  171. SetDlgItemText(hDlg,IDC_MESHNAME,pInfo->MeshName);
  172. SetDlgItemText(hDlg,IDC_CONTAINER,pInfo->ContainerName);
  173. SetDlgItemInt(hDlg,IDC_NUM_MATERIALS, pInfo->NumMaterials,FALSE);
  174. SetDlgItemInt(hDlg,IDC_NUM_POLYS, pInfo->NumTris,FALSE);
  175. SetDlgItemInt(hDlg,IDC_NUM_VERTICES, pInfo->NumVertices, FALSE);
  176. SetDlgItemInt(hDlg,IDC_NUM_MATERIALS, pInfo->NumMaterials,FALSE);
  177. char msg[MAX_PATH];
  178. sprintf(msg, "%.3f", pInfo->SphRadius);
  179. SetDlgItemText(hDlg,IDC_SPHERERADIUS,msg);
  180. //3D Coords
  181. //Center
  182. sprintf(msg, "(%.3f, %.3f, %.3f)", pInfo->SphCenter.X, pInfo->SphCenter.Y, pInfo->SphCenter.Z);
  183. SetDlgItemText(hDlg, IDC_SPHERECENTER, msg);
  184. //Min
  185. sprintf(msg, "(%.3f, %.3f, %.3f)", pInfo->Min.X, pInfo->Min.Y, pInfo->Min.Z);
  186. SetDlgItemText(hDlg, IDC_MINDIM, msg);
  187. //Max
  188. sprintf(msg, "(%.3f, %.3f, %.3f)", pInfo->Max.X, pInfo->Max.Y, pInfo->Max.Z);
  189. SetDlgItemText(hDlg, IDC_MAXDIM, msg);
  190. sprintf(msg,"%d.%d",W3D_GET_MAJOR_VERSION(pInfo->Version),W3D_GET_MINOR_VERSION(pInfo->Version));
  191. SetDlgItemText(hDlg, IDC_VERSION, msg);
  192. }
  193. //==========================================================================================================
  194. BOOL CALLBACK MeshPageDlgProc(HWND hDlg,UINT uMessage, WPARAM wParam, LPARAM lParam){
  195. LPPROPSHEETPAGE psp=(LPPROPSHEETPAGE)GetWindowLong(hDlg, DWL_USER);
  196. UINT iIndex=0;
  197. LPCSHELLEXT lpcs;
  198. switch (uMessage){
  199. case WM_INITDIALOG:{
  200. SetWindowLong(hDlg, DWL_USER, lParam);
  201. psp = (LPPROPSHEETPAGE)lParam;
  202. lpcs = (LPCSHELLEXT)psp->lParam;
  203. if(!lpcs->m_FileInMemory){
  204. lpcs->Read_SelectedFile();
  205. }
  206. ChunkData* pData = &(lpcs->m_WdumpDocument.m_ChunkData);
  207. assert(pData);
  208. POSITION ptr = pData->Chunks.GetHeadPosition();
  209. ASSERT(ptr);
  210. //Look for mesh headers
  211. W3dMeshHeader3Struct* pInfo = lpcs->m_Meshes;
  212. int id_of_interest = W3D_CHUNK_MESH_HEADER3;
  213. int sizeof_struct = sizeof W3dMeshHeader3Struct;
  214. while(ptr){
  215. ChunkItem *pItem = pData->Chunks.GetNext(ptr);
  216. ASSERT(lpcs->m_FoundMeshes < MAX_MESH);
  217. GetItemName(pItem, id_of_interest, (void*)(pInfo),sizeof_struct, lpcs->m_FoundMeshes );
  218. }
  219. if(lpcs->m_FoundMeshes){
  220. SetDlgItemInt(hDlg,IDC_MESHNUMBER, 0,FALSE);
  221. //Look for Textures
  222. char pTextureInfo[MAX_TEXUTRE_NAME_LEN * MAX_MESH];
  223. id_of_interest = W3D_CHUNK_TEXTURE_NAME;
  224. int found_textures(0);
  225. int sizeof_struct = MAX_TEXUTRE_NAME_LEN;
  226. ptr = pData->Chunks.GetHeadPosition();
  227. while(ptr){
  228. ChunkItem *pItem = pData->Chunks.GetNext(ptr);
  229. GetItemName(pItem, id_of_interest, (void*)pTextureInfo, sizeof_struct, found_textures );
  230. }
  231. for(int t_count(0); t_count < found_textures; t_count ++){
  232. if(lpcs->NotAdded(&(pTextureInfo[t_count*MAX_TEXUTRE_NAME_LEN]))){
  233. char* text = lpcs->m_Textures[lpcs->m_NumAdded-1].LockBuffer();
  234. SendDlgItemMessage(hDlg, IDC_TEXTURELIST, LB_ADDSTRING,(WPARAM) 0L, (LPARAM)text);//(pTextureInfo[t_count].name)) ;
  235. lpcs->m_Textures[lpcs->m_NumAdded-1].ReleaseBuffer();
  236. }
  237. }
  238. SetDlgItemInt(hDlg,IDC_NUM_MESHES, lpcs->m_FoundMeshes,FALSE);
  239. SetDlgMeshParams(hDlg, pInfo);
  240. //Set Spin range
  241. SendDlgItemMessage(hDlg, IDC_MESHSPIN, UDM_SETRANGE, (WPARAM)0L, (LPARAM)MAKELONG(lpcs->m_FoundMeshes-1,0));
  242. }
  243. ShowHideControls(hDlg, lpcs->m_FoundMeshes != 0);
  244. break;
  245. }
  246. case WM_DESTROY:
  247. RemoveProp(hDlg, "ID");
  248. break;
  249. case WM_COMMAND:
  250. switch (LOWORD(wParam)){
  251. case IDC_TOP3D:
  252. //SetProp(hDlg, "ID", (HANDLE)lParam);
  253. break;
  254. default:
  255. break;
  256. }
  257. break;
  258. case WM_NOTIFY:
  259. lpcs = (LPCSHELLEXT)psp->lParam;
  260. switch (((NMHDR FAR *)lParam)->code){
  261. case PSN_SETACTIVE:
  262. break;
  263. case PSN_APPLY:
  264. //Ask the shell to refresh the icon list...
  265. SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, 0, 0);
  266. break;
  267. case UDN_DELTAPOS:{
  268. lpcs = (LPCSHELLEXT)psp->lParam;
  269. W3dMeshHeader3Struct* pInfo = lpcs->m_Meshes;
  270. LPNMUPDOWN lpUD = (LPNMUPDOWN) lParam;
  271. int mesh_num = lpUD->iDelta + lpUD->iPos;
  272. if(mesh_num >= 0 && mesh_num < lpcs->m_FoundMeshes){
  273. SetDlgMeshParams(hDlg, pInfo+mesh_num);
  274. }
  275. break;
  276. }
  277. default:
  278. break;
  279. }
  280. break;
  281. default:
  282. return FALSE;
  283. }
  284. return TRUE;
  285. }
  286. /////////////////////////////////////////////////////////////
  287. BOOL CALLBACK PreviewPageDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam){
  288. LPPROPSHEETPAGE psp=(LPPROPSHEETPAGE)GetWindowLong(hDlg, DWL_USER);
  289. UINT iIndex(0);
  290. LPCSHELLEXT lpcs;
  291. switch (uMessage){
  292. case WM_INITDIALOG:{
  293. SetWindowLong(hDlg, DWL_USER, lParam);
  294. psp = (LPPROPSHEETPAGE)lParam;
  295. lpcs = (LPCSHELLEXT)psp->lParam;
  296. if(!lpcs->m_FileInMemory){
  297. lpcs->Read_SelectedFile();
  298. }
  299. break;
  300. }
  301. case WM_DESTROY:{
  302. RemoveProp(hDlg, "ID");
  303. break;
  304. }
  305. case WM_COMMAND:
  306. switch (LOWORD(wParam)){
  307. case IDC_TOP3D:
  308. //SetProp(hDlg, "ID", (HANDLE)lParam);
  309. break;
  310. default:
  311. break;
  312. }
  313. break;
  314. case WM_NOTIFY:
  315. switch (((NMHDR FAR *)lParam)->code){
  316. case PSN_SETACTIVE:
  317. break;
  318. case PSN_APPLY:
  319. //User has clicked the OK or Apply button so we'll
  320. //update the icon information in the .W3D file
  321. lpcs = (LPCSHELLEXT)psp->lParam;
  322. //Ask the shell to refresh the icon list...
  323. SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, 0, 0);
  324. break;
  325. default:
  326. break;
  327. }
  328. break;
  329. default:
  330. return FALSE;
  331. }
  332. return TRUE;
  333. }
  334. // PURPOSE: Called by the shell just before the property sheet is displayed.
  335. STDMETHODIMP CShellExt::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, //Pointer to the Shell's AddPage function
  336. LPARAM lParam){ //Passed as second parameter to lpfnAddPage
  337. m_FileInMemory = false;
  338. PROPSHEETPAGE psp;
  339. HPROPSHEETPAGE hpage;
  340. FORMATETC fmte = {CF_HDROP,(DVTARGETDEVICE FAR *)NULL,DVASPECT_CONTENT,-1, TYMED_HGLOBAL };
  341. STGMEDIUM medium;
  342. HRESULT hres = 0;
  343. // char buf[MAX_PATH];
  344. if (m_pDataObj){ //Paranoid check, m_pDataObj should have something by now...
  345. hres = m_pDataObj->GetData(&fmte, &medium);
  346. }
  347. if (SUCCEEDED(hres)){
  348. //Find out how many files the user has selected...
  349. UINT cbFiles = 0;
  350. LPCSHELLEXT lpcsext = this;
  351. if (medium.hGlobal){
  352. cbFiles = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, 0, 0);
  353. }
  354. if (cbFiles < 2){
  355. if (cbFiles){
  356. DragQueryFile((HDROP)medium.hGlobal,0, m_SelectedFile, sizeof(m_SelectedFile));
  357. }
  358. psp.dwSize = sizeof(psp); // no extra data.
  359. psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_USECALLBACK;
  360. psp.hInstance = g_DllInstance;
  361. psp.pszTemplate = MAKEINTRESOURCE(IDD_MESH);
  362. psp.hIcon = 0;
  363. psp.pszTitle = " Meshes ";
  364. psp.pfnDlgProc = MeshPageDlgProc;
  365. psp.pcRefParent = &g_DllRefCount;
  366. psp.pfnCallback = W3DPageCallback;
  367. psp.lParam = (LPARAM)lpcsext;
  368. AddRef();
  369. hpage = CreatePropertySheetPage(&psp);
  370. if(hpage){
  371. if (!lpfnAddPage(hpage, lParam)){
  372. DestroyPropertySheetPage(hpage);
  373. Release();
  374. }
  375. }
  376. //Animation Page
  377. psp.pszTemplate = MAKEINTRESOURCE(IDD_ANIMPAGE);
  378. psp.pszTitle = "Animations";
  379. psp.pfnDlgProc = AnimPageDlgProc;
  380. AddRef();
  381. hpage = CreatePropertySheetPage(&psp);
  382. if(hpage){
  383. if (!lpfnAddPage(hpage, lParam)){
  384. DestroyPropertySheetPage(hpage);
  385. Release();
  386. }
  387. }
  388. //Preview Page
  389. psp.pszTemplate = MAKEINTRESOURCE(IDD_PREVIEW);
  390. psp.pszTitle = " Preview ";
  391. psp.pfnDlgProc = PreviewPageDlgProc;
  392. AddRef();
  393. hpage = CreatePropertySheetPage(&psp);
  394. if(hpage){
  395. if (!lpfnAddPage(hpage, lParam)){
  396. DestroyPropertySheetPage(hpage);
  397. Release();
  398. }
  399. }
  400. }
  401. }
  402. return NOERROR;
  403. }
  404. // PURPOSE: Called by the shell only for Control Panel property sheet
  405. STDMETHODIMP CShellExt::ReplacePage(UINT uPageID, //ID of page to be replaced
  406. LPFNADDPROPSHEETPAGE lpfnReplaceWith, //Pointer to the Shell's Replace function
  407. LPARAM lParam){ //Passed as second parameter to lpfnReplaceWith
  408. return E_FAIL;//we don't support this function. It should never be
  409. }