Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

630 lines
18 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: ss3dfo.c
  3. *
  4. * Dispatcher and dialog box for the OpenGL-based 3D Flying Objects screen
  5. * saver.
  6. *
  7. * Created: 18-May-1994 14:54:59
  8. *
  9. * Copyright (c) 1994 Microsoft Corporation
  10. \**************************************************************************/
  11. #include <windows.h>
  12. #include <scrnsave.h>
  13. #include <GL\gl.h>
  14. #include <math.h>
  15. #include <memory.h>
  16. #include <string.h>
  17. #include <stdarg.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <malloc.h>
  21. #include <sys\timeb.h>
  22. #include <time.h>
  23. #include <commdlg.h>
  24. #include <commctrl.h>
  25. #include "ss3dfo.h"
  26. //#define SS_DEBUG 1
  27. // Global strings.
  28. #define GEN_STRING_SIZE 64
  29. static SSContext gssc;
  30. BOOL gbBounce = FALSE; // floating window bounce off side
  31. // Global message loop variables.
  32. MATERIAL Material[16];
  33. #ifdef MEMDEBUG
  34. ULONG totalMem = 0;
  35. #endif
  36. // Global screen saver settings.
  37. void (*updateSceneFunc)(int); // current screen saver update function
  38. void (*delSceneFunc)(void); // current screen saver deletion function
  39. BOOL bColorCycle = FALSE; // color cycling flag
  40. BOOL bSmoothShading = TRUE; // smooth shading flag
  41. UINT uSize = 100; // object size
  42. float fTesselFact = 1.0f; // object tessalation
  43. int UpdateFlags = 0; // extra data sent to update function
  44. int Type = 0; // screen saver index (into function arrays)
  45. // Texture file information
  46. TEXFILE gTexFile = {0};
  47. // Lighting properties.
  48. static const RGBA lightAmbient = {0.21f, 0.21f, 0.21f, 1.0f};
  49. static const RGBA light0Ambient = {0.0f, 0.0f, 0.0f, 1.0f};
  50. static const RGBA light0Diffuse = {0.7f, 0.7f, 0.7f, 1.0f};
  51. static const RGBA light0Specular = {1.0f, 1.0f, 1.0f, 1.0f};
  52. static const GLfloat light0Pos[] = {100.0f, 100.0f, 100.0f, 0.0f};
  53. // Material properties.
  54. static RGBA matlColors[7] = {{1.0f, 0.0f, 0.0f, 1.0f},
  55. {0.0f, 1.0f, 0.0f, 1.0f},
  56. {0.0f, 0.0f, 1.0f, 1.0f},
  57. {1.0f, 1.0f, 0.0f, 1.0f},
  58. {0.0f, 1.0f, 1.0f, 1.0f},
  59. {1.0f, 0.0f, 1.0f, 1.0f},
  60. {0.235f, 0.0f, 0.78f, 1.0f},
  61. };
  62. extern void updateStripScene(int);
  63. extern void updateDropScene(int);
  64. extern void updateLemScene(int);
  65. extern void updateExplodeScene(int);
  66. extern void updateWinScene(int);
  67. extern void updateTexScene(int);
  68. extern void initStripScene(void);
  69. extern void initDropScene(void);
  70. extern void initLemScene(void);
  71. extern void initExplodeScene(void);
  72. extern void initWinScene(void);
  73. extern void initTexScene(void);
  74. extern void delStripScene(void);
  75. extern void delDropScene(void);
  76. extern void delLemScene(void);
  77. extern void delExplodeScene(void);
  78. extern void delWinScene(void);
  79. extern void delTexScene(void);
  80. typedef void (*PTRUPDATE)(int);
  81. typedef void (*ptrdel)();
  82. typedef void (*ptrinit)();
  83. // Each screen saver style puts its hook functions into the function
  84. // arrays below. A consistent ordering of the functions is required.
  85. static PTRUPDATE updateFuncs[] =
  86. {updateWinScene, updateExplodeScene,updateStripScene, updateStripScene,
  87. updateDropScene, updateLemScene, updateTexScene};
  88. static ptrdel delFuncs[] =
  89. {delWinScene, delExplodeScene, delStripScene, delStripScene,
  90. delDropScene, delLemScene, delTexScene};
  91. static ptrinit initFuncs[] =
  92. {initWinScene, initExplodeScene, initStripScene, initStripScene,
  93. initDropScene, initLemScene, initTexScene};
  94. static int idsStyles[] =
  95. {IDS_LOGO, IDS_EXPLODE, IDS_RIBBON, IDS_2RIBBON,
  96. IDS_SPLASH, IDS_TWIST, IDS_FLAG};
  97. #define MAX_TYPE ( sizeof(initFuncs) / sizeof(ptrinit) - 1 )
  98. // Each screen saver style can choose which dialog box controls it wants
  99. // to use. These flags enable each of the controls. Controls not choosen
  100. // will be disabled.
  101. #define OPT_COLOR_CYCLE 0x00000001
  102. #define OPT_SMOOTH_SHADE 0x00000002
  103. #define OPT_TESSEL 0x00000008
  104. #define OPT_SIZE 0x00000010
  105. #define OPT_TEXTURE 0x00000020
  106. #define OPT_STD ( OPT_COLOR_CYCLE | OPT_SMOOTH_SHADE | OPT_TESSEL | OPT_SIZE )
  107. static ULONG gflConfigOpt[] = {
  108. OPT_STD, // Windows logo
  109. OPT_STD, // Explode
  110. OPT_STD, // Strip
  111. OPT_STD, // Strip
  112. OPT_STD, // Drop
  113. OPT_STD, // Twist (lemniscate)
  114. OPT_SMOOTH_SHADE | OPT_TESSEL | OPT_SIZE | OPT_TEXTURE // Texture mapped flag
  115. };
  116. static void updateDialogControls(HWND hDlg);
  117. #ifdef MEMDEBUG
  118. void xprintf(char *str, ...)
  119. {
  120. va_list ap;
  121. char buffer[256];
  122. va_start(ap, str);
  123. vsprintf(buffer, str, ap);
  124. OutputDebugString(buffer);
  125. va_end(ap);
  126. }
  127. #endif
  128. void *SaverAlloc(ULONG size)
  129. {
  130. void *mPtr;
  131. mPtr = malloc(size);
  132. #ifdef MEMDEBUG
  133. totalMem += size;
  134. xprintf("malloc'd %x, size %d\n", mPtr, size);
  135. #endif
  136. return mPtr;
  137. }
  138. void SaverFree(void *pMem)
  139. {
  140. #ifdef MEMDEBUG
  141. totalMem -= _msize(pMem);
  142. xprintf("free %x, size = %d, total = %d\n", pMem, _msize(pMem), totalMem);
  143. #endif
  144. free(pMem);
  145. }
  146. /******************************Public*Routine******************************\
  147. * getIniSettings
  148. *
  149. * Get the screen saver configuration options from .INI file/registry.
  150. *
  151. * History:
  152. * 10-May-1994 -by- Gilman Wong [gilmanw]
  153. * Wrote it.
  154. \**************************************************************************/
  155. static void getIniSettings()
  156. {
  157. int options;
  158. int optMask = 1;
  159. TCHAR szDefaultBitmap[MAX_PATH];
  160. int tessel=0;
  161. LPTSTR psz;
  162. LoadString(hMainInstance, IDS_GENNAME, szScreenSaver, sizeof(szScreenSaver) / sizeof(TCHAR));
  163. if( ss_RegistrySetup( hMainInstance, IDS_SAVERNAME, IDS_INIFILE ) )
  164. {
  165. options = ss_GetRegistryInt( IDS_OPTIONS, -1 );
  166. if (options >= 0)
  167. {
  168. bSmoothShading = ((options & optMask) != 0);
  169. optMask <<= 1;
  170. bColorCycle = ((options & optMask) != 0);
  171. UpdateFlags = (bColorCycle << 1);
  172. }
  173. Type = ss_GetRegistryInt( IDS_OBJTYPE, 0 );
  174. // Sanity check Type. Don't want to index into function arrays
  175. // with a bad index!
  176. Type = min(Type, MAX_TYPE);
  177. // Set flag so that updateStripScene will do two strips instead
  178. // of one.
  179. if (Type == 3)
  180. UpdateFlags |= 0x4;
  181. tessel = ss_GetRegistryInt( IDS_TESSELATION, 100 );
  182. SS_CLAMP_TO_RANGE2( tessel, 0, 200 );
  183. if (tessel <= 100)
  184. fTesselFact = (float)tessel / 100.0f;
  185. else
  186. fTesselFact = 1.0f + (((float)tessel - 100.0f) / 100.0f);
  187. uSize = ss_GetRegistryInt( IDS_SIZE, 50 );
  188. if (uSize > 100)
  189. uSize = 100;
  190. // SS_CLAMP_TO_RANGE2( uSize, 0, 100 ); /* can't be less than zero since it is a UINT */
  191. // Determine the default .bmp file
  192. ss_GetDefaultBmpFile( szDefaultBitmap );
  193. // Is there a texture specified in the registry that overrides the
  194. // default?
  195. ss_GetRegistryString( IDS_TEXTURE, szDefaultBitmap, gTexFile.szPathName,
  196. MAX_PATH);
  197. gTexFile.nOffset = ss_GetRegistryInt( IDS_TEXTURE_FILE_OFFSET, 0 );
  198. }
  199. }
  200. /******************************Public*Routine******************************\
  201. * saveIniSettings
  202. *
  203. * Save the screen saver configuration option to the .INI file/registry.
  204. *
  205. * History:
  206. * 10-May-1994 -by- Gilman Wong [gilmanw]
  207. * Wrote it.
  208. \**************************************************************************/
  209. static void saveIniSettings(HWND hDlg)
  210. {
  211. if( ss_RegistrySetup( hMainInstance, IDS_SAVERNAME, IDS_INIFILE ) )
  212. {
  213. int pos, options;
  214. int optMask = 1;
  215. bSmoothShading = IsDlgButtonChecked(hDlg, DLG_SETUP_SMOOTH);
  216. bColorCycle = IsDlgButtonChecked(hDlg, DLG_SETUP_CYCLE);
  217. options = bColorCycle;
  218. options <<= 1;
  219. options |= bSmoothShading;
  220. ss_WriteRegistryInt( IDS_OPTIONS, options );
  221. Type = (int)SendDlgItemMessage(hDlg, DLG_SETUP_TYPES, CB_GETCURSEL,
  222. 0, 0);
  223. ss_WriteRegistryInt( IDS_OBJTYPE, Type );
  224. pos = ss_GetTrackbarPos( hDlg, DLG_SETUP_TESSEL );
  225. ss_WriteRegistryInt( IDS_TESSELATION, pos );
  226. pos = ss_GetTrackbarPos( hDlg, DLG_SETUP_SIZE );
  227. ss_WriteRegistryInt( IDS_SIZE, pos );
  228. ss_WriteRegistryString( IDS_TEXTURE, gTexFile.szPathName );
  229. ss_WriteRegistryInt( IDS_TEXTURE_FILE_OFFSET, gTexFile.nOffset );
  230. }
  231. }
  232. /******************************Public*Routine******************************\
  233. * setupDialogControls
  234. *
  235. * Setup the dialog controls initially.
  236. *
  237. \**************************************************************************/
  238. static void
  239. setupDialogControls(HWND hDlg)
  240. {
  241. int pos;
  242. InitCommonControls();
  243. if ( gflConfigOpt[Type] & OPT_TESSEL )
  244. {
  245. if (fTesselFact <= 1.0f)
  246. pos = (int)(fTesselFact * 100.0f);
  247. else
  248. pos = 100 + (int) ((fTesselFact - 1.0f) * 100.0f);
  249. ss_SetupTrackbar( hDlg, DLG_SETUP_TESSEL, 0, 200, 1, 10, pos );
  250. }
  251. if ( gflConfigOpt[Type] & OPT_SIZE )
  252. {
  253. ss_SetupTrackbar( hDlg, DLG_SETUP_SIZE, 0, 100, 1, 10, uSize );
  254. }
  255. updateDialogControls( hDlg );
  256. }
  257. /******************************Public*Routine******************************\
  258. * updateDialogControls
  259. *
  260. * Update the dialog controls based on the current global state.
  261. *
  262. \**************************************************************************/
  263. static void
  264. updateDialogControls(HWND hDlg)
  265. {
  266. CheckDlgButton(hDlg, DLG_SETUP_SMOOTH, bSmoothShading);
  267. CheckDlgButton(hDlg, DLG_SETUP_CYCLE, bColorCycle);
  268. EnableWindow(GetDlgItem(hDlg, DLG_SETUP_SMOOTH),
  269. gflConfigOpt[Type] & OPT_SMOOTH_SHADE );
  270. EnableWindow(GetDlgItem(hDlg, DLG_SETUP_CYCLE),
  271. gflConfigOpt[Type] & OPT_COLOR_CYCLE );
  272. EnableWindow(GetDlgItem(hDlg, DLG_SETUP_TESSEL),
  273. gflConfigOpt[Type] & OPT_TESSEL);
  274. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_TESS),
  275. gflConfigOpt[Type] & OPT_TESSEL);
  276. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_TESS_MIN),
  277. gflConfigOpt[Type] & OPT_TESSEL);
  278. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_TESS_MAX),
  279. gflConfigOpt[Type] & OPT_TESSEL);
  280. EnableWindow(GetDlgItem(hDlg, DLG_SETUP_SIZE),
  281. gflConfigOpt[Type] & OPT_SIZE);
  282. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_SIZE),
  283. gflConfigOpt[Type] & OPT_SIZE);
  284. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_SIZE_MIN),
  285. gflConfigOpt[Type] & OPT_SIZE);
  286. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_SIZE_MAX),
  287. gflConfigOpt[Type] & OPT_SIZE);
  288. EnableWindow(GetDlgItem(hDlg, DLG_SETUP_TEXTURE),
  289. gflConfigOpt[Type] & OPT_TEXTURE);
  290. }
  291. BOOL WINAPI RegisterDialogClasses(HANDLE hinst)
  292. {
  293. return TRUE;
  294. }
  295. /******************************Public*Routine******************************\
  296. * ScreenSaverConfigureDialog
  297. *
  298. * Processes messages for the configuration dialog box.
  299. *
  300. \**************************************************************************/
  301. BOOL ScreenSaverConfigureDialog(HWND hDlg, UINT message,
  302. WPARAM wParam, LPARAM lParam)
  303. {
  304. int wTmp;
  305. TCHAR szString[GEN_STRING_SIZE];
  306. switch (message) {
  307. case WM_INITDIALOG:
  308. getIniSettings();
  309. setupDialogControls(hDlg);
  310. for (wTmp = 0; wTmp <= MAX_TYPE; wTmp++) {
  311. LoadString(hMainInstance, idsStyles[wTmp], szString, GEN_STRING_SIZE);
  312. SendDlgItemMessage(hDlg, DLG_SETUP_TYPES, CB_ADDSTRING, 0,
  313. (LPARAM) szString);
  314. }
  315. SendDlgItemMessage(hDlg, DLG_SETUP_TYPES, CB_SETCURSEL, Type, 0);
  316. return TRUE;
  317. case WM_COMMAND:
  318. switch (LOWORD(wParam)) {
  319. case DLG_SETUP_TYPES:
  320. switch (HIWORD(wParam))
  321. {
  322. case CBN_EDITCHANGE:
  323. case CBN_SELCHANGE:
  324. Type = (int)SendDlgItemMessage(hDlg, DLG_SETUP_TYPES,
  325. CB_GETCURSEL, 0, 0);
  326. updateDialogControls(hDlg);
  327. break;
  328. default:
  329. break;
  330. }
  331. return FALSE;
  332. case DLG_SETUP_TEXTURE:
  333. ss_SelectTextureFile( hDlg, &gTexFile );
  334. break;
  335. case IDOK:
  336. saveIniSettings(hDlg);
  337. EndDialog(hDlg, TRUE);
  338. break;
  339. case IDCANCEL:
  340. EndDialog(hDlg, FALSE);
  341. break;
  342. case DLG_SETUP_SMOOTH:
  343. case DLG_SETUP_CYCLE:
  344. default:
  345. break;
  346. }
  347. return TRUE;
  348. break;
  349. default:
  350. return 0;
  351. }
  352. return 0;
  353. }
  354. /******************************Public*Routine******************************\
  355. * SetFloaterInfo
  356. *
  357. * Set the size and motion of the floating window
  358. * It stays square in shape
  359. *
  360. \**************************************************************************/
  361. static void
  362. SetFloaterInfo( ISIZE *pParentSize, CHILD_INFO *pChild )
  363. {
  364. float sizeFact;
  365. float sizeScale;
  366. int size;
  367. ISIZE *pChildSize = &pChild->size;
  368. MOTION_INFO *pMotion = &pChild->motionInfo;
  369. sizeScale = (float)uSize / 100.0f; // 0..1
  370. sizeFact = 0.25f + (0.30f * sizeScale);
  371. size = (int) (sizeFact * ( ((float)(pParentSize->width + pParentSize->height)) / 2.0f ));
  372. SS_CLAMP_TO_RANGE2( size, 0, pParentSize->width );
  373. SS_CLAMP_TO_RANGE2( size, 0, pParentSize->height );
  374. pChildSize->width = pChildSize->height = size;
  375. // Floater motion
  376. pMotion->posInc.x = .01f * (float) size;
  377. if( pMotion->posInc.x < 1.0f )
  378. pMotion->posInc.x = 1.0f;
  379. pMotion->posInc.y = pMotion->posInc.x;
  380. pMotion->posIncVary.x = .4f * pMotion->posInc.x;
  381. pMotion->posIncVary.y = pMotion->posIncVary.x;
  382. }
  383. /******************************Public*Routine******************************\
  384. * initMaterial
  385. *
  386. * Initialize the material properties.
  387. *
  388. \**************************************************************************/
  389. void initMaterial(int id, float r, float g, float b, float a)
  390. {
  391. Material[id].ka.r = r;
  392. Material[id].ka.g = g;
  393. Material[id].ka.b = b;
  394. Material[id].ka.a = a;
  395. Material[id].kd.r = r;
  396. Material[id].kd.g = g;
  397. Material[id].kd.b = b;
  398. Material[id].kd.a = a;
  399. Material[id].ks.r = 1.0f;
  400. Material[id].ks.g = 1.0f;
  401. Material[id].ks.b = 1.0f;
  402. Material[id].ks.a = 1.0f;
  403. Material[id].specExp = 128.0f;
  404. }
  405. /******************************Public*Routine******************************\
  406. * _3dfo_Init
  407. *
  408. \**************************************************************************/
  409. static void
  410. _3dfo_Init(void *data)
  411. {
  412. int i;
  413. for (i = 0; i < 7; i++)
  414. initMaterial(i, matlColors[i].r, matlColors[i].g,
  415. matlColors[i].b, matlColors[i].a);
  416. // Set the OpenGL clear color to black.
  417. glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  418. #ifdef SS_DEBUG
  419. glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
  420. #endif
  421. // Enable the z-buffer.
  422. glEnable(GL_DEPTH_TEST);
  423. // Select the shading model.
  424. if (bSmoothShading)
  425. glShadeModel(GL_SMOOTH);
  426. else
  427. glShadeModel(GL_FLAT);
  428. // Setup the OpenGL matrices.
  429. glMatrixMode(GL_PROJECTION);
  430. glLoadIdentity();
  431. glMatrixMode(GL_MODELVIEW);
  432. glLoadIdentity();
  433. // Setup the lighting.
  434. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (GLfloat *) &lightAmbient);
  435. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  436. glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
  437. glLightfv(GL_LIGHT0, GL_AMBIENT, (GLfloat *) &light0Ambient);
  438. glLightfv(GL_LIGHT0, GL_DIFFUSE, (GLfloat *) &light0Diffuse);
  439. glLightfv(GL_LIGHT0, GL_SPECULAR, (GLfloat *) &light0Specular);
  440. glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
  441. glEnable(GL_LIGHTING);
  442. glEnable(GL_LIGHT0);
  443. // Setup the material properties.
  444. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (GLfloat *) &Material[0].ks);
  445. glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, (GLfloat *) &Material[0].specExp);
  446. // call specific objects init func
  447. (*initFuncs[Type])();
  448. updateSceneFunc = updateFuncs[Type];
  449. }
  450. /******************************Public*Routine******************************\
  451. * _3dfo_Draw
  452. *
  453. \**************************************************************************/
  454. static void
  455. _3dfo_Draw(void *data)
  456. {
  457. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  458. (*updateSceneFunc)(UpdateFlags);
  459. }
  460. /******************************Public*Routine******************************\
  461. * _3dfo_FloaterBounce
  462. *
  463. \**************************************************************************/
  464. static void
  465. _3dfo_FloaterBounce(void *data)
  466. {
  467. gbBounce = TRUE;
  468. }
  469. /******************************Public*Routine******************************\
  470. * ss_Init
  471. *
  472. * Screen saver entry point. Pre-GL initialization
  473. *
  474. \**************************************************************************/
  475. SSContext *
  476. ss_Init(void)
  477. {
  478. getIniSettings();
  479. // Make sure the selected texture file is OK.
  480. if ( gflConfigOpt[Type] & OPT_TEXTURE )
  481. {
  482. // Verify texture file
  483. ss_DisableTextureErrorMsgs();
  484. ss_VerifyTextureFile( &gTexFile );
  485. }
  486. // set callbacks
  487. ss_InitFunc( _3dfo_Init );
  488. ss_UpdateFunc( _3dfo_Draw );
  489. // set configuration info to return
  490. gssc.bDoubleBuf = TRUE;
  491. gssc.depthType = SS_DEPTH16;
  492. gssc.bFloater = TRUE;
  493. gssc.floaterInfo.bMotion = TRUE;
  494. gssc.floaterInfo.ChildSizeFunc = SetFloaterInfo;
  495. ss_FloaterBounceFunc( _3dfo_FloaterBounce );
  496. return &gssc;
  497. }
  498. /**************************************************************************\
  499. * ConfigInit
  500. *
  501. * Dialog box version of ss_Init. Used for setting up any gl drawing on the
  502. * dialog.
  503. *
  504. \**************************************************************************/
  505. BOOL
  506. ss_ConfigInit( HWND hDlg )
  507. {
  508. return TRUE;
  509. }