home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwwin / rwshop.c_ / rwshop.bin
Text File  |  1995-11-14  |  44KB  |  1,435 lines

  1. /**********************************************************************
  2.  *
  3.  * File :     rwshop.c
  4.  *
  5.  * Abstract : RenderWare Shop demo. Main module
  6.  *
  7.  **********************************************************************
  8.  *
  9.  * This file is a product of Criterion Software Ltd.
  10.  *
  11.  * This file is provided as is with no warranties of any kind and is
  12.  * provided without any obligation on Criterion Software Ltd. or
  13.  * Canon Inc. to assist in its use or modification.
  14.  *
  15.  * Criterion Software Ltd. will not, under any
  16.  * circumstances, be liable for any lost revenue or other damages arising
  17.  * from the use of this file.
  18.  *
  19.  * Copyright (c) 1995 Criterion Software Ltd.
  20.  * All Rights Reserved.
  21.  *
  22.  * RenderWare is a trademark of Canon Inc.
  23.  *
  24.  ************************************************************************/
  25.  
  26. /**********************************************************************
  27.  *
  28.  * Header files.
  29.  *
  30.  **********************************************************************/
  31.  
  32. #define INCLUDE_SHELLAPI_H
  33.  
  34. #include <windows.h>
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <string.h>
  38.  
  39. #include "common.h"
  40. #include "resource.h"
  41. #include "gdi3d.h"
  42. #include "rwlib.h"
  43. #include "rwwin.h"
  44.  
  45. /**********************************************************************
  46.  *
  47.  * Application constants.
  48.  *
  49.  **********************************************************************/
  50.  
  51. #if !defined(__WINDOWS_386__)
  52. #define MK_FP32(x) (x)
  53. #endif
  54.  
  55. #define RWSHOP_CLASS_NAME               "RwTeleShopClass"
  56. #define RWWINDOW_CLASS_NAME             "RwWindowClass"
  57. #define RWMOVEBUTTON_CLASS_NAME         "RwMoveButtonClass"
  58.  
  59. #define ERROR_DIALOG_TITLE              "RenderWare TeleShopping Error"
  60.  
  61. #define DEFAULT_WINDOW_WIDTH            400
  62. #define DEFAULT_WINDOW_HEIGHT           400
  63.  
  64. #define MAXIMUM_WINDOW_WIDTH            512
  65. #define MAXIMUM_WINDOW_HEIGHT           512
  66.  
  67. #define DEFAULT_WORLD_MIN_X             CREAL(-1.7)
  68. #define DEFAULT_WORLD_MIN_Z             CREAL(-1.7)
  69. #define DEFAULT_WORLD_MAX_X             CREAL(1.7)
  70. #define DEFAULT_WORLD_MAX_Z             CREAL(1.7)
  71.  
  72. #define DEFAULT_CAMERA_X                CREAL(0.0)
  73. #define DEFAULT_CAMERA_Y                CREAL(0.75)
  74. #define DEFAULT_CAMERA_Z                DEFAULT_WORLD_MAX_Z
  75.  
  76. #define DEFAULT_CAMERA_FORWARD_DELTA    CREAL(0.1)
  77. #define DEFAULT_CAMERA_RIGHT_DELTA      CREAL(0.1)
  78. #define DEFAULT_CAMERA_TURN_DELTA       CREAL(5.0)
  79.  
  80. #define MAX_OBJECT_NAME                 30
  81. #define DEFAULT_STATUS_MESSAGE          "Right Button - Price an object"
  82.  
  83. /**********************************************************************
  84.  *
  85.  * Forward functions.
  86.  *
  87.  **********************************************************************/
  88.  
  89. extern long far PASCAL
  90. WindowProc(HWND, WORD, WPARAM, LPARAM);
  91.  
  92. extern long far PASCAL
  93. RenderWareWindowProc(HWND, WORD, WPARAM, LPARAM);
  94.  
  95. extern long far PASCAL
  96. MoveButtonWindowProc(HWND, WORD, WPARAM, LPARAM);
  97.  
  98.  
  99. /**********************************************************************
  100.  *
  101.  * Type definitions.
  102.  *
  103.  **********************************************************************/
  104.  
  105. typedef enum
  106. {
  107.   SHOP_NONE,
  108.   SHOP_ART    
  109. } ShopType;
  110.  
  111. typedef enum
  112. {
  113.     MMNoAction,
  114.     MMSpinClump,
  115. } MMMode;
  116.  
  117. typedef enum
  118. {
  119.     ANoAction,
  120.     ASpinClump
  121. } AMode;
  122.  
  123. typedef enum
  124. {
  125.     NoMove,
  126.     MoveForward,
  127.     MoveBackward,
  128.     MoveLeft,
  129.     MoveRight,
  130.     TurnLeft,
  131.     TurnRight
  132. } MAction;
  133.  
  134. typedef struct
  135. {
  136.     char   i_name[MAX_OBJECT_NAME];
  137.     RwReal i_price;
  138.     int    spin_flag;
  139.     RwReal spin_delta;
  140. } ObjectInfo;
  141.  
  142. /**********************************************************************
  143.  *
  144.  * Application global variables.
  145.  *
  146.  **********************************************************************/
  147.  
  148. static RwInt32        UsingDib = FALSE;
  149. static HANDLE      AppInstance;
  150.  
  151. static RwScene    *Scene  = NULL;
  152. static RwCamera   *Camera = NULL;
  153. static RwLight    *Light  = NULL;
  154. static RwClump    *ShopClump = NULL;
  155. static RwClump    *MallClump = NULL;
  156.  
  157. static RwClump    *PickedClump = NULL;
  158.  
  159. static RwMatrix4d *SpinMatrix = NULL;
  160.  
  161. #if defined(USE_USERDRAW)
  162. static RwUserDraw *UserDraw = NULL;
  163. #endif
  164.  
  165. static MMMode      MouseMoveMode = MMNoAction;
  166. static ShopType    Shop = SHOP_NONE;
  167.  
  168. static int         LastX;
  169. static int         LastY;
  170.  
  171. static RwReal      CameraTilt = CREAL(0.0);
  172.  
  173. static HFONT       Font = (HFONT)0;
  174.  
  175. static MAction     MoveAction = NoMove;
  176. static BOOL        RenderFlag = TRUE;
  177.  
  178. static RwReal      CameraForwardDelta = DEFAULT_CAMERA_FORWARD_DELTA;
  179. static RwReal      CameraRightDelta   = DEFAULT_CAMERA_RIGHT_DELTA;
  180. static RwReal      CameraTurnDelta    = DEFAULT_CAMERA_TURN_DELTA;
  181.  
  182. static BOOL        ThreeDInitialized = FALSE;
  183.  
  184. static HWND        Window;
  185.  
  186. /**********************************************************************
  187.  *
  188.  * Functions.
  189.  *
  190.  **********************************************************************/
  191.  
  192. /**********************************************************************/
  193.  
  194. static void
  195. SetStatusMessage(char *message)
  196. {
  197.     if (Window)
  198.         SetDlgItemText(Window, STATUS_BAR_CONTROL_ID, message);
  199. }
  200.  
  201. /**********************************************************************/
  202.  
  203. static ObjectInfo *
  204. CreateObjectInfo(char *name, RwReal price, int spin)
  205. {
  206.     ObjectInfo *objectInfo;
  207.  
  208.      if (objectInfo = (ObjectInfo*)malloc(sizeof(ObjectInfo)))
  209.     {
  210.         strcpy(objectInfo->i_name, name);
  211.         objectInfo->i_price = price;
  212.         objectInfo->spin_flag = spin;
  213.         objectInfo->spin_delta = CREAL(0.0);
  214.     }
  215.     return objectInfo;
  216. }
  217.  
  218. /**********************************************************************/
  219.  
  220. static RwClump *
  221. DestroyObjectInfo(RwClump *clump)
  222. {
  223.     if (RwGetClumpData(clump))
  224.         free(RwGetClumpData(clump));
  225.     return(clump);
  226. }
  227.  
  228. /**********************************************************************/
  229.  
  230. static BOOL
  231. InitApplication(HANDLE instance)
  232. {
  233.     WNDCLASS windowClass;
  234.  
  235.     windowClass.style         = CS_HREDRAW | CS_VREDRAW;
  236.     windowClass.lpfnWndProc   = (WNDPROC)WindowProc;
  237.     windowClass.cbClsExtra    = 0; 
  238.     windowClass.cbWndExtra    = DLGWINDOWEXTRA;
  239.     windowClass.hInstance     = instance; 
  240.     windowClass.hIcon         = LoadIcon(instance, MAKEINTRESOURCE(RW_ICON));
  241.     windowClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  242.     windowClass.hbrBackground = NULL; 
  243.     windowClass.lpszMenuName  = "MAIN_MENU"; 
  244.     windowClass.lpszClassName = RWSHOP_CLASS_NAME;
  245.  
  246.     if (!RegisterClass(&windowClass))
  247.     {
  248.         return FALSE;
  249.     }
  250.  
  251.     windowClass.style         = CS_HREDRAW | CS_VREDRAW;
  252.     windowClass.lpfnWndProc   = (WNDPROC)MoveButtonWindowProc;
  253.     windowClass.cbClsExtra    = 0; 
  254.     windowClass.cbWndExtra    = 0;
  255.     windowClass.hInstance     = instance; 
  256.      windowClass.hIcon         = NULL;
  257.     windowClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  258.     windowClass.hbrBackground = NULL; 
  259.     windowClass.lpszMenuName  = NULL; 
  260.     windowClass.lpszClassName = RWMOVEBUTTON_CLASS_NAME;
  261.  
  262.     if (!RegisterClass(&windowClass))
  263.     {
  264.         return FALSE;
  265.     }
  266.  
  267.     windowClass.style         = CS_HREDRAW | CS_VREDRAW;
  268.     windowClass.lpfnWndProc   = (WNDPROC)RenderWareWindowProc;
  269.     windowClass.cbClsExtra    = 0; 
  270.     windowClass.cbWndExtra    = 0;
  271.     windowClass.hInstance     = instance; 
  272.     windowClass.hIcon         = NULL;
  273.     windowClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  274.     windowClass.hbrBackground = NULL; 
  275.     windowClass.lpszMenuName  = NULL; 
  276.     windowClass.lpszClassName = RWWINDOW_CLASS_NAME;
  277.  
  278.     return RegisterClass(&windowClass);
  279. }
  280.  
  281. /**********************************************************************/
  282.  
  283. static HWND
  284. InitInstance(HANDLE instance)
  285. {
  286.     return CreateDialog(instance, "TeleshoppingDialog", 0, NULL);
  287. }
  288.  
  289. /**********************************************************************/
  290.  
  291. #if defined(USE_USERDRAW)
  292. static RwUserDraw *
  293. UserDrawCallBack(RwUserDraw *userDraw, void *camImage, RwRect *rect,
  294.                       void *data)
  295. {
  296.      HDC         devContext;
  297.      HFONT       oldFont;
  298.      int         oldMode;
  299.      COLORREF    oldColor;
  300.     SIZE       extent;
  301.     ObjectInfo *objectInfo;
  302.     char        buffer[30];
  303.  
  304.     if (!data)
  305.           return(userDraw);
  306.  
  307.     objectInfo = (ObjectInfo*)data;
  308.     sprintf(buffer, "%s $%0.2lf", objectInfo->i_name, REAL2FL(objectInfo->i_price));
  309.  
  310.     if (!UsingDib)
  311.     {
  312.         devContext = (HDC)camImage;
  313.  
  314.         if (Font)
  315.             oldFont = SelectObject(devContext, Font);
  316.  
  317.         GetTextExtentPoint(devContext, buffer, strlen(buffer), &extent);
  318.           oldMode = SetBkMode(devContext, TRANSPARENT);
  319.         oldColor = SetTextColor(devContext, RGB(0, 0, 0));
  320.           TextOut(devContext, (int)(rect->x + ((rect->w / 2) - (extent.cx / 2))),
  321.                                      (int)(rect->y + ((rect->h / 2) - (extent.cy / 2))),
  322.                                      buffer, strlen(buffer));
  323.           SetTextColor(devContext, RGB(255, 255, 255));
  324.           TextOut(devContext, (int)(rect->x + ((rect->w / 2) - (extent.cx / 2)) - 2),
  325.                                      (int)(rect->y + ((rect->h / 2) - (extent.cy / 2)) - 2),
  326.                             buffer, strlen(buffer));
  327.         SetBkMode(devContext, oldMode);
  328.         SetTextColor(devContext, oldColor);
  329.  
  330.         if (Font)
  331.             SelectObject(devContext, oldFont);
  332.     }
  333.     else
  334.     {
  335.         SetStatusMessage(buffer);
  336.     }
  337.     return(userDraw);
  338. }
  339. #endif
  340. /**********************************************************************/
  341.  
  342. static RwClump *
  343. LoadClump(char *fileName)
  344. {
  345.     RwClump    *clump;
  346.     char        buffer[128];
  347.  
  348.     clump = RwReadShape(fileName);
  349.     if (!clump)
  350.     {
  351.         switch (RwGetError())
  352.         {
  353.                 case E_RW_NOMEM:
  354.                 sprintf(buffer, "Insufficient memory to load script %s",
  355.                         fileName);
  356.                 MessageBox(NULL, buffer, ERROR_DIALOG_TITLE,
  357.                            MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  358.                 return NULL;
  359.  
  360.             default:
  361.                 sprintf(buffer,
  362.                         "Error reading the script file %s",
  363.                         fileName);
  364.                 MessageBox(NULL, buffer, ERROR_DIALOG_TITLE,
  365.                            MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  366.                 return NULL;
  367.         }
  368.     }
  369.  
  370.     return clump;
  371. }   
  372.  
  373. /**********************************************************************/
  374.  
  375. static BOOL
  376. Init3D(HANDLE instance)
  377. {
  378.     char        buffer[128];
  379.     LOGFONT     logFont;
  380.     DWORD       extent;
  381.     RwClump    *clump;
  382.     ObjectInfo *objectInfo;
  383.     int i;
  384.  
  385.     if (!RwOpen("MSWindows", NULL))
  386.     {
  387.         if (RwGetError() == E_RW_NOMEM)
  388.         {
  389.         MessageBox(NULL,
  390.                        "Insufficient memory to open the RenderWare library",
  391.                        ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  392.         }
  393.         else
  394.         {
  395.         MessageBox(NULL, "Error opening the RenderWare library",
  396.                        ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  397.         }
  398.     return FALSE;
  399.     }
  400.  
  401.      /*
  402.      * Determine if userdraw functinality is available and set the global flag
  403.      * accordingly
  404.     */
  405.     RwGetDeviceInfo(rwWINIMAGEISDIB, &UsingDib, sizeof(RwInt32));
  406.  
  407.     /*---    Set the shape path to enable texture loading     ---*/
  408.  
  409.     GetModuleFileName(instance, buffer, sizeof(buffer));
  410.     i = strlen(buffer);
  411.     while(buffer[i] != '\\')
  412.         i--;
  413.     buffer[i+1] = 0;
  414.     strcat(buffer, "TEXTURES");
  415.     RwSetShapePath(buffer, rwREPLACE); 
  416.  
  417.     buffer[i+1] = 0;
  418.     strcat(buffer, "SCRIPTS");
  419.     RwSetShapePath(buffer, rwPOSTCONCAT); 
  420.     
  421.     buffer[i+1] = 0;
  422.     strcat(buffer, ".");
  423.     RwSetShapePath(buffer, rwPOSTCONCAT); 
  424.  
  425.      Camera = RwCreateCamera(MAXIMUM_WINDOW_WIDTH, MAXIMUM_WINDOW_HEIGHT, NULL);
  426.     if (!Camera)
  427.     {
  428.         if (RwGetError() == E_RW_NOMEM)
  429.         {
  430.         MessageBox(NULL,
  431.                        "Insufficient memory to create the RenderWare camera",
  432.                        ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  433.         }
  434.         else
  435.         {
  436.         MessageBox(NULL, "Error creating the RenderWare camera",
  437.                        ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  438.         }
  439.         RwClose();
  440.  
  441.     return FALSE;
  442.     }
  443.  
  444.     RwSetCameraBackColor(Camera, CREAL(0.5), CREAL(0.5), CREAL(1.0));
  445.  
  446.     RwTiltCamera(Camera, CameraTilt);
  447.     RwSetCameraPosition(Camera, DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y, DEFAULT_CAMERA_Z);
  448.  
  449.      RwSetCameraViewwindow(Camera, CREAL(0.4), CREAL(0.4));
  450.  
  451.     Scene = RwCreateScene();
  452.     if (!Scene)
  453.     {
  454.         RwDestroyCamera(Camera);
  455.         RwClose();
  456.     MessageBox(NULL, "Error creating the RenderWare scene",
  457.                    ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  458.     return FALSE;
  459.     }
  460.  
  461.     Light = RwCreateLight(rwPOINT, CREAL(0.5), CREAL(1.2), CREAL(0.0),
  462.                           CREAL(1.0));
  463.     if (!Light)
  464.     {
  465.         RwDestroyScene(Scene);
  466.         RwDestroyCamera(Camera);
  467.         RwClose();
  468.     MessageBox(NULL, "Error creating the RenderWare light",
  469.            ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  470.     return FALSE;
  471.     }
  472.  
  473.      RwAddLightToScene(Scene, Light);
  474.  
  475.     SpinMatrix = RwCreateMatrix();
  476.     if (!SpinMatrix)
  477.     {
  478.         RwDestroyScene(Scene);
  479.         RwDestroyCamera(Camera);
  480.         RwClose();
  481.         MessageBox(NULL, "Error creating the RenderWare matrix",
  482.                    ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  483.         return FALSE;
  484.     }
  485.  
  486.     MallClump = LoadClump("mall.rwx");
  487.     if (!MallClump)
  488.     {
  489.         RwDestroyScene(Scene);
  490.         RwDestroyCamera(Camera);
  491.         RwClose();
  492.         return FALSE;
  493.     }
  494.     RwAddHintToClump(MallClump, rwCONTAINER);
  495.  
  496.     RwTranslateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(0.0), DEFAULT_WORLD_MIN_Z, rwREPLACE);
  497.      RwTransformClump(MallClump, RwScratchMatrix(), rwREPLACE);
  498.  
  499.     RwAddClumpToScene(Scene, MallClump);
  500.     ShopClump = LoadClump("shop.rwx");
  501.     if (!ShopClump)
  502.     {
  503.         RwDestroyScene(Scene);
  504.         RwDestroyCamera(Camera);
  505.         RwClose();
  506.         return FALSE;
  507.     }
  508. /*    RwAddClumpToScene(Scene, ShopClump); */
  509.     if (clump = RwFindTaggedClump(ShopClump, 1))
  510.     {
  511.         objectInfo = CreateObjectInfo("Wooden Bowl", CREAL(75.95), TRUE);
  512.         if (objectInfo)
  513.             RwSetClumpData(clump, objectInfo);
  514.     }
  515.     if (clump = RwFindTaggedClump(ShopClump, 2))
  516.     {
  517.         objectInfo = CreateObjectInfo("Glass Vase", CREAL(299.99), TRUE);
  518.         if (objectInfo)
  519.             RwSetClumpData(clump, objectInfo);
  520.     }
  521.      if (clump = RwFindTaggedClump(ShopClump, 3))
  522.     {
  523.         objectInfo = CreateObjectInfo("Ornament", CREAL(1000.00), TRUE);
  524.         if (objectInfo)
  525.             RwSetClumpData(clump, objectInfo);
  526.     }
  527.     if (clump = RwFindTaggedClump(ShopClump, 4))
  528.     {
  529.         objectInfo = CreateObjectInfo("Le Printemps", CREAL(30000.00), FALSE);
  530.         if (objectInfo)
  531.             RwSetClumpData(clump, objectInfo);
  532.     }
  533.     if (clump = RwFindTaggedClump(ShopClump, 5))
  534.     {
  535.         objectInfo = CreateObjectInfo("Landscape", CREAL(9.50), FALSE);
  536.         if (objectInfo)
  537.             RwSetClumpData(clump, objectInfo);
  538.     }
  539.  
  540.     memset(&logFont, 0, sizeof(LOGFONT));
  541.     logFont.lfHeight = 28;
  542.     strcpy(logFont.lfFaceName, "Arial Italic");
  543.     Font = CreateFontIndirect(&logFont);
  544.  
  545.      extent = MAKELONG(400, 32);
  546.  
  547. #if defined(USE_USERDRAW)
  548.      UserDraw = RwCreateUserDraw(rwBBOXALIGN, rwALIGNBOTTOM, 0, 5,
  549.                                           LOWORD(extent) + 5, HIWORD(extent) + 5,
  550.                                           UserDrawCallBack);
  551.      if (!UserDraw)
  552.      {
  553.           RwDestroyScene(Scene);
  554.           RwDestroyCamera(Camera);
  555.           RwClose();
  556.           MessageBox(NULL, "Error creating the RenderWare user-draw",
  557.                          ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  558.           return FALSE;
  559.      }
  560.      RwSetUserDrawParentAlignment(UserDraw, rwALIGNBOTTOM);
  561. #endif
  562.      ThreeDInitialized = TRUE;
  563.  
  564.      return TRUE;
  565. }
  566.  
  567. /**********************************************************************/
  568.  
  569. static void
  570. TidyUp3D()
  571. {
  572. #if defined(USE_USERDRAW)
  573.      RwDestroyUserDraw(UserDraw);
  574. #endif
  575.     if (Font)
  576.         DeleteObject(Font);
  577.  
  578.     RwForAllClumpsInScene(Scene, DestroyObjectInfo);
  579.  
  580.     RwDestroyMatrix(SpinMatrix);
  581.    
  582.     RwDestroyScene(Scene);
  583.  
  584.     RwDestroyCamera(Camera);
  585.  
  586.     RwClose();
  587. }
  588.  
  589. /**********************************************************************/
  590.  
  591. static void
  592. HandleSizeRw(HWND window, int width, int height)
  593. {
  594.     RwSetCameraViewport(Camera, 2, 2, width - 4, height - 4);
  595.     InvalidateRect(window, NULL, FALSE);
  596. }
  597.  
  598. /**********************************************************************/
  599.  
  600. static void
  601. HandleLeftButtonDownRw(HWND window, int x, int y)
  602. {
  603.     RwPickRecord pick;
  604.     POINT        pos;
  605.     ObjectInfo   *info;
  606.  
  607.     if (RwPickScene(Scene, x, y, Camera, &pick))
  608.     {
  609.         PickedClump   = NULL;
  610.         switch (pick.type)
  611.     {
  612.         case rwNAPICKOBJECT:
  613.                 MouseMoveMode = MMNoAction;
  614.             break;
  615.  
  616.         case rwPICKCLUMP:
  617.                 info = RwGetClumpData(pick.object.clump.clump);
  618.                 if (info && info->spin_flag)
  619.                 {
  620.                     PickedClump = pick.object.clump.clump;
  621.                           MouseMoveMode = MMSpinClump;
  622.                     SetStatusMessage("Spin Object");
  623.                 }
  624.                 else
  625.                     MouseMoveMode = MMNoAction;
  626.         break;
  627.     }
  628.     }
  629.  
  630.     if (MouseMoveMode != MMNoAction)
  631.     {
  632.         SetCapture(window);
  633.         pos.x = x;
  634.         pos.y = y;
  635.         ClientToScreen(window, &pos);
  636.     LastX = pos.x;
  637.     LastY = pos.y;
  638.         RenderFlag = TRUE;
  639.     }
  640. }
  641.  
  642. /**********************************************************************/
  643.  
  644. static void
  645. HandleRightButtonDownRw(HWND window, int x, int y)
  646. {
  647.     RwPickRecord pick;
  648.  
  649.     if (RwPickScene(Scene, x, y, Camera, &pick) && (pick.type == rwPICKCLUMP))
  650.     {
  651.         if (RwGetClumpData(pick.object.clump.clump))
  652.         {
  653.             PickedClump = pick.object.clump.clump;
  654. #if defined(USE_USERDRAW)
  655.                 RwAddUserDrawToClump(PickedClump, UserDraw);
  656.                 RwSetUserDrawData(UserDraw, RwGetClumpData(PickedClump));
  657. #endif
  658.             RenderFlag = TRUE;
  659.             if (!UsingDib)
  660.                 SetStatusMessage("Display Object Price");
  661.         }
  662.         else
  663.             PickedClump = NULL;
  664.     }
  665.     SetCapture(window);
  666. }
  667.  
  668. /**********************************************************************/
  669.  
  670. static void
  671. HandleMouseMoveRw(HWND window, int x, int y)
  672. {
  673.     POINT       pos;
  674.     RwReal      xDelta;
  675.     ObjectInfo  *info;
  676.  
  677.     pos.x = x;
  678.     pos.y = y;
  679.     ClientToScreen(window, &pos);
  680.     
  681.     switch (MouseMoveMode)
  682.     {
  683.         case MMNoAction:
  684.             break;
  685.  
  686.         case MMSpinClump:
  687.         xDelta = INT2REAL(pos.x - LastX);
  688.             info = RwGetClumpData(PickedClump);
  689.             info->spin_delta = RAdd(info->spin_delta, xDelta);
  690.             if (info->spin_delta > CREAL(360.0))
  691.                 info->spin_delta = RSub(info->spin_delta, CREAL(360.0));
  692.             if (info->spin_delta < CREAL(-360.0))
  693.                 info->spin_delta = RAdd(info->spin_delta, CREAL(360.0));
  694.  
  695.                 RwRotateMatrix(SpinMatrix, CREAL(0.0), CREAL(1.0), CREAL(0.0), info->spin_delta, rwREPLACE);
  696.             RwTransformClumpJoint(PickedClump, SpinMatrix, rwREPLACE);
  697.             RenderFlag = TRUE;
  698.             break;
  699.     }
  700.  
  701.     /* Remember the current X and Y for next time. */
  702.  
  703.     LastX = pos.x;
  704.     LastY = pos.y;
  705. }
  706.  
  707. /**********************************************************************/
  708.  
  709. static void
  710. HandleLeftButtonUpRw()
  711. {
  712.     if (MouseMoveMode != MMNoAction)
  713.     {
  714.         MouseMoveMode = MMNoAction;
  715.         ReleaseCapture();
  716.         SetStatusMessage(DEFAULT_STATUS_MESSAGE);
  717.     }
  718. }
  719.  
  720. /**********************************************************************/
  721.  
  722. static void
  723. HandleRightButtonUpRw()
  724. {
  725. #if defined(USE_USERDRAW)
  726.      if (RwGetUserDrawOwner(UserDraw))
  727.      {
  728.           RwRemoveUserDrawFromClump(UserDraw);
  729.           RenderFlag = TRUE;
  730.           SetStatusMessage(DEFAULT_STATUS_MESSAGE);
  731.      }
  732. #endif
  733.     ReleaseCapture();
  734. }
  735.  
  736. /**********************************************************************/
  737.  
  738. static void
  739. HandlePaintRw(HWND window)
  740. {
  741.     HDC      devContext;
  742.     PAINTSTRUCT  ps;
  743.     RECT         rect;
  744.  
  745.      devContext = BeginPaint(window, &ps);
  746.     GetClientRect(window, &rect);
  747.     FrameRect3D(devContext, rect.left, rect.top, rect.right, rect.bottom, FALSE);
  748.     FrameRect3D(devContext, rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1, FALSE);
  749.  
  750.     RwInvalidateCameraViewport(Camera);
  751.     RwBeginCameraUpdate(Camera, (void *)(DWORD)window);
  752.     RwClearCameraViewport(Camera);
  753.     RwRenderScene(Scene);
  754.     RwEndCameraUpdate(Camera);
  755.     RenderFlag = FALSE;
  756.     RwShowCameraImage(Camera, (void*)(DWORD)devContext);
  757.     EndPaint(window, &ps);
  758. }
  759.  
  760.  
  761.  
  762.  
  763. /**********************************************************************/
  764. RwClump *ScaleDoors(RwClump *clump)
  765. {
  766.     RwInt32 tag;
  767.     tag = RwGetClumpTag(clump);
  768.  
  769.      if ((tag == 7L) || (tag == 8L))
  770.     {
  771.         RwTransformClumpJoint(clump, RwScratchMatrix(), rwREPLACE);
  772.     }
  773.     return(clump);
  774. }
  775.  
  776. /**********************************************************************/
  777. static int ChangeShop(RwV3d *pos)
  778. {
  779.     RwReal delta;
  780.  
  781.     switch(Shop)
  782.     {
  783.     case SHOP_NONE:
  784.         if ((pos->x < CREAL(0.5)) &&
  785.             (pos->x > CREAL(-0.5)))
  786.         {
  787.             delta = RSub(pos->z, DEFAULT_WORLD_MIN_Z);
  788.             RwScaleMatrix(RwScratchMatrix(), RAdd(CREAL(0.5), RDiv(delta, CREAL(6.8))), CREAL(1.0), CREAL(1.0), rwREPLACE);
  789.             RwForAllClumpsInHierarchy(MallClump, ScaleDoors);
  790.             if (pos->z < (RAdd(DEFAULT_WORLD_MIN_Z, CREAL(0.3))))
  791.             {
  792.                 RwSetCameraPosition(Camera, pos->x, pos->y, RSub(DEFAULT_WORLD_MAX_Z, CREAL(0.3)));
  793.                      RwRemoveClumpFromScene(MallClump);
  794.                 RwAddClumpToScene(Scene, ShopClump);
  795.                 Shop = SHOP_ART;
  796.                 return(1);
  797.             }
  798.         }
  799.         else
  800.         {
  801.             RwScaleMatrix(RwScratchMatrix(), CREAL(1.0), CREAL(1.0), CREAL(1.0), rwREPLACE);
  802.             RwForAllClumpsInHierarchy(MallClump, ScaleDoors);
  803.         }
  804.         break;
  805.     case SHOP_ART:
  806.         if ((pos->x < CREAL(0.5)) &&
  807.             (pos->x > CREAL(-0.5)))
  808.         {
  809.             delta = RSub(DEFAULT_WORLD_MAX_Z, pos->z);
  810.             RwScaleMatrix(RwScratchMatrix(), RAdd(CREAL(0.5), RDiv(delta, CREAL(6.8))), CREAL(1.0), CREAL(1.0), rwREPLACE);
  811.             RwForAllClumpsInHierarchy(ShopClump, ScaleDoors);
  812.             if (pos->z > RSub(DEFAULT_WORLD_MAX_Z, CREAL(0.3)))
  813.             {
  814.                 RwSetCameraPosition(Camera, pos->x, pos->y, RAdd(DEFAULT_WORLD_MIN_Z, CREAL(0.3)));
  815.                 RwRemoveClumpFromScene(ShopClump);
  816.                 RwAddClumpToScene(Scene, MallClump);
  817.                      Shop = SHOP_NONE;
  818.                 return(1);
  819.             }
  820.         }
  821.         else
  822.         {
  823.             RwScaleMatrix(RwScratchMatrix(), CREAL(1.0), CREAL(1.0), CREAL(1.0), rwREPLACE);
  824.             RwForAllClumpsInHierarchy(ShopClump, ScaleDoors);
  825.         }
  826.         break;
  827.     }
  828.     return(0);
  829. }
  830.  
  831. /**********************************************************************/
  832.  
  833. static void
  834. HandleTimerRw(HWND window)
  835. {
  836.     HDC   devContext;
  837.     RwV3d pos, v, posdelta;
  838.     int moveflag = FALSE;
  839.  
  840.     if (MoveAction != NoMove)
  841.      {
  842.         /* get flattened look at without moving camera */
  843.         RwGetCameraLookAt(Camera, &v);
  844.         v.y = CREAL(0.0);
  845.         RwNormalize(&v);
  846.  
  847.         switch (MoveAction)
  848.         {
  849.             case MoveForward:
  850.                 posdelta.x = RMul(CameraForwardDelta, v.x);                
  851.                 posdelta.z = RMul(CameraForwardDelta, v.z);                
  852.                 moveflag = TRUE;
  853.                 break;
  854.             case MoveBackward:
  855.                 posdelta.x = RMul(-CameraForwardDelta, v.x);                
  856.                 posdelta.z = RMul(-CameraForwardDelta, v.z);                
  857.                 moveflag = TRUE;
  858.                 break;
  859.             case MoveLeft:
  860.                 RwGetCameraLookRight(Camera, &v);
  861.                 posdelta.x = RMul(-CameraRightDelta, v.x);                
  862.                 posdelta.z = RMul(-CameraRightDelta, v.z);                
  863.                 moveflag = TRUE;
  864.                 break;
  865.                 case MoveRight:
  866.                 RwGetCameraLookRight(Camera, &v);
  867.                 posdelta.x = RMul(CameraRightDelta, v.x);                
  868.                 posdelta.z = RMul(CameraRightDelta, v.z);                
  869.                 moveflag = TRUE;
  870.                 break;
  871.             case TurnLeft:
  872.                 RwTiltCamera(Camera, -CameraTilt);
  873.                 RwPanCamera(Camera, CameraTurnDelta);
  874.                 RwTiltCamera(Camera, CameraTilt);
  875.                 break;
  876.             case TurnRight:
  877.                 RwTiltCamera(Camera, -CameraTilt);
  878.                 RwPanCamera(Camera, -CameraTurnDelta);
  879.                 RwTiltCamera(Camera, CameraTilt);
  880.                 break;
  881.         }
  882.         if (moveflag)
  883.         {
  884.             RwGetCameraPosition(Camera, &pos);
  885.             pos.x = RAdd(pos.x, posdelta.x);
  886.             pos.z = RAdd(pos.z, posdelta.z);
  887.  
  888.         
  889.                 if (!ChangeShop(&pos))
  890.             {
  891.                 if ((pos.x >= DEFAULT_WORLD_MIN_X) &&
  892.                     (pos.z >= DEFAULT_WORLD_MIN_Z) &&
  893.                     (pos.x <= DEFAULT_WORLD_MAX_X) &&
  894.                     (pos.z <= DEFAULT_WORLD_MAX_Z))
  895.                 {            
  896.                     RwSetCameraPosition(Camera, pos.x, pos.y, pos.z);
  897.                 }
  898.                 else
  899.                 {
  900.                     SetStatusMessage("Against the wall");
  901.                 }
  902.             }
  903.         }
  904.         RenderFlag = TRUE;
  905.     }
  906.     if (RenderFlag)
  907.     {
  908.         RwBeginCameraUpdate(Camera, (void *)(DWORD)window);
  909.         RwClearCameraViewport(Camera);
  910.         RwRenderScene(Scene);
  911.         RwEndCameraUpdate(Camera);
  912.         devContext = GetDC(window);
  913.           RwShowCameraImage(Camera, (void*)(DWORD)devContext);
  914.         ReleaseDC(window, devContext);
  915.         RenderFlag = FALSE;
  916.     }
  917. }
  918.  
  919. /**********************************************************************/
  920.  
  921. long far PASCAL
  922. RenderWareWindowProc(HWND window, WORD message, WPARAM wParam, LPARAM lParam)
  923. {
  924.     switch (message)
  925.     {
  926.     case WM_CREATE:
  927.             SetTimer(window, 1, 20, NULL);
  928.             return 0L;
  929.  
  930.     case WM_SIZE:
  931.             if (ThreeDInitialized)
  932.             HandleSizeRw(window, LOWORD(lParam), HIWORD(lParam));
  933.             return 0L;
  934.  
  935.     case WM_LBUTTONDOWN:
  936.             if (ThreeDInitialized)
  937.               HandleLeftButtonDownRw(window, LOWORD(lParam), HIWORD(lParam));
  938.             return 0L;
  939.  
  940.     case WM_RBUTTONDOWN:
  941.             if (ThreeDInitialized)
  942.             HandleRightButtonDownRw(window, LOWORD(lParam), HIWORD(lParam));
  943.             return 0L;
  944.  
  945.     case WM_MOUSEMOVE:
  946.             if (ThreeDInitialized)
  947.             {
  948.             if (MouseMoveMode != MMNoAction)
  949.                 HandleMouseMoveRw(window, LOWORD(lParam), HIWORD(lParam));
  950.             }
  951.             return 0L;
  952.  
  953.     case WM_LBUTTONUP:
  954.             if (ThreeDInitialized)
  955.             HandleLeftButtonUpRw();
  956.             return 0L;
  957.  
  958.     case WM_RBUTTONUP:
  959.             if (ThreeDInitialized)
  960.             HandleRightButtonUpRw();
  961.                 return 0L;
  962.  
  963.     case WM_PAINT:
  964.             if (ThreeDInitialized)
  965.             HandlePaintRw(window);
  966.             return 0L;
  967.  
  968.     case WM_TIMER:
  969.             if (ThreeDInitialized)
  970.             HandleTimerRw(window);
  971.             return 0L;
  972.  
  973.     case WM_DESTROY:
  974.         KillTimer(window, 1);
  975.             return 0L;
  976.     }
  977.     return DefWindowProc(window, message, wParam, lParam);
  978. }
  979.  
  980. /**********************************************************************/
  981.  
  982. long far PASCAL
  983. MoveButtonWindowProc(HWND window, WORD message, WPARAM wParam, LPARAM lParam)
  984. {
  985.      int         x;
  986.     int         y;
  987.     int         width;
  988.     int         height;
  989.     RECT        rect;
  990.     BOOL        selected;
  991.     HBITMAP     bitmap;
  992.     HBITMAP     oldBitmap;
  993.     BITMAP      bitmapInfo;
  994.     HDC         devContext;
  995.     HDC         bitmapDevContext;
  996.     PAINTSTRUCT paintStruct;
  997.  
  998.     switch (message)
  999.     {
  1000.     case WM_CREATE:
  1001.             return 0L;
  1002.  
  1003.     case WM_LBUTTONDOWN:
  1004. #ifdef WIN32
  1005.             switch (GetWindowLong(window, GWL_ID))
  1006. #else
  1007.             switch (GetWindowWord(window, GWW_ID))
  1008. #endif
  1009.                 {
  1010.                 case FORWARD_BUTTON_ID:
  1011.                     MoveAction = MoveForward;
  1012.                     SetStatusMessage("Move forward");
  1013.                     break;
  1014.                 case BACKWARD_BUTTON_ID:
  1015.                     MoveAction = MoveBackward;
  1016.                     SetStatusMessage("Move backward");
  1017.                     break;
  1018.                 case LEFT_BUTTON_ID:
  1019.                     MoveAction = MoveLeft;
  1020.                     SetStatusMessage("Move left");
  1021.                     break;
  1022.                 case RIGHT_BUTTON_ID:
  1023.                     MoveAction = MoveRight;
  1024.                     SetStatusMessage("Move right");
  1025.                     break;
  1026.                 case TURN_LEFT_BUTTON_ID:
  1027.                     MoveAction = TurnLeft;
  1028.                     SetStatusMessage("Turn left");
  1029.                     break;
  1030.                 case TURN_RIGHT_BUTTON_ID:
  1031.                     MoveAction = TurnRight;
  1032.                     SetStatusMessage("Turn right");
  1033.                           break;
  1034.             }
  1035.             if (MoveAction != NoMove)
  1036.             {
  1037.                 SetCapture(window);
  1038.                 InvalidateRect(window, NULL, FALSE);
  1039.             }
  1040.             return 0L;
  1041.  
  1042.     case WM_MOUSEMOVE:
  1043.             return 0L;
  1044.  
  1045.     case WM_LBUTTONUP:
  1046.             if (MoveAction != NoMove)
  1047.             {
  1048.                 ReleaseCapture();
  1049.                 MoveAction = NoMove;
  1050.                 SetStatusMessage(DEFAULT_STATUS_MESSAGE);
  1051.                 InvalidateRect(window, NULL, FALSE);
  1052.             }
  1053.             return 0L;
  1054.  
  1055.     case WM_PAINT:
  1056.             devContext = BeginPaint(window, &paintStruct);
  1057.                 GetClientRect(window, &rect);
  1058.     #ifdef WIN32
  1059.             switch (GetWindowLong(window, GWL_ID))
  1060.     #else
  1061.             switch (GetWindowWord(window, GWW_ID))
  1062.     #endif
  1063.             {
  1064.                 case FORWARD_BUTTON_ID:
  1065.                     bitmap = LoadBitmap(AppInstance, MAKEINTRESOURCE(FORWARD_BITMAP_ID));
  1066.                     selected = (MoveAction == MoveForward);
  1067.                     break;
  1068.                 case BACKWARD_BUTTON_ID:
  1069.                     bitmap = LoadBitmap(AppInstance, MAKEINTRESOURCE(BACKWARD_BITMAP_ID));
  1070.                     selected = (MoveAction == MoveBackward);
  1071.                     break;
  1072.                 case LEFT_BUTTON_ID:
  1073.                     bitmap = LoadBitmap(AppInstance, MAKEINTRESOURCE(LEFT_BITMAP_ID));
  1074.                     selected = (MoveAction == MoveLeft);
  1075.                     break;
  1076.                 case RIGHT_BUTTON_ID:
  1077.                     bitmap = LoadBitmap(AppInstance, MAKEINTRESOURCE(RIGHT_BITMAP_ID));
  1078.                     selected = (MoveAction == MoveRight);
  1079.                     break;
  1080.                 case TURN_LEFT_BUTTON_ID:
  1081.                           bitmap = LoadBitmap(AppInstance, MAKEINTRESOURCE(TURN_LEFT_BITMAP_ID));
  1082.                     selected = (MoveAction == TurnLeft);
  1083.                     break;
  1084.                 case TURN_RIGHT_BUTTON_ID:
  1085.                     bitmap = LoadBitmap(AppInstance, MAKEINTRESOURCE(TURN_RIGHT_BITMAP_ID));
  1086.                     selected = (MoveAction == TurnRight);
  1087.                     break;
  1088.             }
  1089.  
  1090.             FrameRect(devContext, &rect, GetStockObject(BLACK_BRUSH));
  1091.             FrameRect3D(devContext, rect.left + 1,
  1092.                                     rect.top + 1,
  1093.                                     rect.right - 1,
  1094.                                     rect.bottom - 1,
  1095.                                     !selected);
  1096.             Rectangle3D(devContext, rect.left + 2,
  1097.                                     rect.top + 2,
  1098.                                     rect.right - 2,
  1099.                                     rect.bottom - 2,
  1100.                                     !selected);
  1101.  
  1102.             if (bitmap)
  1103.             {
  1104.                 GetObject(bitmap, sizeof(BITMAP), &bitmapInfo);
  1105.                      width  = bitmapInfo.bmWidth;
  1106.                 height = bitmapInfo.bmHeight;
  1107.                 x = rect.left + (((rect.right  - rect.left) - width) >> 1);
  1108.                 y = rect.top  + (((rect.bottom - rect.top)  - height) >> 1);
  1109.                 bitmapDevContext = CreateCompatibleDC(devContext);
  1110.                 oldBitmap = SelectObject(bitmapDevContext, bitmap);
  1111.                 BitBlt(devContext, x, y, width, height, bitmapDevContext, 0, 0, SRCCOPY);
  1112.                 SelectObject(bitmapDevContext, oldBitmap);
  1113.                 DeleteObject(bitmap);
  1114.                 DeleteDC(bitmapDevContext);
  1115.             }
  1116.             EndPaint(window, &paintStruct);
  1117.             return 0L;
  1118.  
  1119.     case WM_DESTROY:
  1120.             return 0L;
  1121.     }
  1122.  
  1123.     return DefWindowProc(window, message, wParam, lParam);
  1124. }
  1125.  
  1126. /**********************************************************************/
  1127.  
  1128. static void
  1129. HandleDrawItem(UINT controlID, DRAWITEMSTRUCT FAR *drawItem)
  1130. {
  1131.     HFONT       oldFont;
  1132.     char        buffer[256];
  1133.     int         oldMode;
  1134.     int         x;
  1135.     int         y;
  1136.     SIZE       extent;
  1137.     int         width;
  1138.     int         height;
  1139.     BOOL        selected;
  1140.     HBITMAP     bitmap;
  1141.     HBITMAP     oldBitmap;
  1142.     BITMAP      bitmapInfo;
  1143.     HDC         bitmapDevContext;
  1144.     RECT        rect;
  1145.     
  1146.     switch (controlID)
  1147.     {
  1148.         case STATUS_BAR_CONTROL_ID:
  1149.             oldFont = SelectObject(drawItem->hDC, GetStockObject(ANSI_VAR_FONT));
  1150.             GetWindowText(drawItem->hwndItem, buffer, sizeof(buffer));
  1151.             GetTextExtentPoint(drawItem->hDC, buffer, strlen(buffer), &extent);            
  1152.             Rectangle3D(drawItem->hDC, drawItem->rcItem.left,
  1153.                                                     drawItem->rcItem.top,
  1154.                                        drawItem->rcItem.right,
  1155.                                        drawItem->rcItem.bottom,
  1156.                                        FALSE);
  1157.             x = drawItem->rcItem.left + 6;
  1158.             y = drawItem->rcItem.top + (((drawItem->rcItem.bottom - drawItem->rcItem.top) - extent.cy) >> 1);
  1159.             oldMode = SetBkMode(drawItem->hDC, TRANSPARENT);
  1160.             TextOut(drawItem->hDC, x, y, buffer, strlen(buffer));
  1161.             SetBkMode(drawItem->hDC, oldMode);
  1162.             SelectObject(drawItem->hDC, oldFont);
  1163.             break;
  1164.         case LOOK_UP_BUTTON_ID:
  1165.         case LOOK_AHEAD_BUTTON_ID:
  1166.         case LOOK_DOWN_BUTTON_ID:
  1167.             switch (controlID)
  1168.             {
  1169.                 case LOOK_UP_BUTTON_ID:
  1170.                     bitmap = LoadBitmap(AppInstance, MAKEINTRESOURCE(LOOK_UP_BITMAP_ID));
  1171.                     break;
  1172.                 case LOOK_AHEAD_BUTTON_ID:
  1173.                     bitmap = LoadBitmap(AppInstance, MAKEINTRESOURCE(LOOK_AHEAD_BITMAP_ID));
  1174.                     break;
  1175.                 case LOOK_DOWN_BUTTON_ID:
  1176.                     bitmap = LoadBitmap(AppInstance, MAKEINTRESOURCE(LOOK_DOWN_BITMAP_ID));
  1177.                           break;
  1178.             }
  1179.             selected = ((drawItem->itemState & ODS_SELECTED) == ODS_SELECTED);
  1180.  
  1181.             rect = drawItem->rcItem;
  1182.             FrameRect(drawItem->hDC, &rect, GetStockObject(BLACK_BRUSH));
  1183.             FrameRect3D(drawItem->hDC, drawItem->rcItem.left + 1,
  1184.                                        drawItem->rcItem.top + 1,
  1185.                                        drawItem->rcItem.right - 1,
  1186.                                        drawItem->rcItem.bottom - 1,
  1187.                                        !selected);
  1188.             Rectangle3D(drawItem->hDC, drawItem->rcItem.left + 2,
  1189.                                        drawItem->rcItem.top + 2,
  1190.                                        drawItem->rcItem.right - 2,
  1191.                                        drawItem->rcItem.bottom - 2,
  1192.                                        !selected);
  1193.  
  1194.             if (bitmap)
  1195.             {
  1196.                 GetObject(bitmap, sizeof(BITMAP), &bitmapInfo);
  1197.                 width  = bitmapInfo.bmWidth;
  1198.                 height = bitmapInfo.bmHeight;
  1199.                 x = drawItem->rcItem.left + (((drawItem->rcItem.right  - drawItem->rcItem.left) - width) >> 1);
  1200.                 y = drawItem->rcItem.top  + (((drawItem->rcItem.bottom - drawItem->rcItem.top)  - height) >> 1);
  1201.                      bitmapDevContext = CreateCompatibleDC(drawItem->hDC);
  1202.                 oldBitmap = SelectObject(bitmapDevContext, bitmap);
  1203.                 BitBlt(drawItem->hDC, x, y, width, height, bitmapDevContext, 0, 0, SRCCOPY);
  1204.                 SelectObject(bitmapDevContext, oldBitmap);
  1205.                 DeleteObject(bitmap);
  1206.                 DeleteDC(bitmapDevContext);
  1207.             }
  1208.             break;
  1209.     }
  1210. }
  1211.  
  1212. /**********************************************************************/
  1213.  
  1214. static void
  1215. HandlePaint(HWND window)
  1216. {
  1217.     HDC     devContext;
  1218.     PAINTSTRUCT paintStruct;
  1219.     RECT        rect;
  1220.  
  1221.     devContext = BeginPaint(window, &paintStruct);
  1222.     GetClientRect(window, &rect);
  1223.     FrameRect3D(devContext, rect.left, rect.top,
  1224.                             rect.right, rect.bottom, TRUE);
  1225.      Rectangle3D(devContext, rect.left + 1, rect.top + 1,
  1226.                             rect.right - 1, rect.bottom - 1, TRUE);
  1227.     EndPaint(window, &paintStruct);
  1228. }
  1229.  
  1230. /**************************************************************************
  1231.     About Dialogue Box Stuff
  1232. **************************************************************************/
  1233. void DlgDrawItem(DRAWITEMSTRUCT FAR *dis)
  1234. {
  1235.     HDC hdcMemory;
  1236.     HBITMAP hbmplogo, hbmpOld;
  1237.     BITMAP bm;
  1238.  
  1239.     hbmplogo = LoadBitmap(AppInstance, MAKEINTRESOURCE(CRITERION_LOGO));
  1240.     GetObject(hbmplogo, sizeof(BITMAP), &bm);
  1241.  
  1242.     hdcMemory = CreateCompatibleDC(dis->hDC);
  1243.     hbmpOld = SelectObject(hdcMemory, hbmplogo);
  1244.  
  1245.     BitBlt(dis->hDC, dis->rcItem.left, dis->rcItem.top, 
  1246.                dis->rcItem.right - dis->rcItem.left,
  1247.                dis->rcItem.bottom - dis->rcItem.top,
  1248.                hdcMemory, 0, 0, SRCCOPY);
  1249.  
  1250.     SelectObject(hdcMemory, hbmpOld);
  1251.     DeleteDC(hdcMemory);
  1252.     DeleteObject(hbmplogo);
  1253. }
  1254.  
  1255. BOOL FAR PASCAL AboutDlgProc(HWND hDlg, WORD message, WPARAM wParam, LPARAM lParam)
  1256. {
  1257.     switch(message)
  1258.     {
  1259.     case WM_INITDIALOG:
  1260.         return TRUE;
  1261.  
  1262.     case WM_COMMAND:
  1263.         switch(wParam)
  1264.         {
  1265.         case IDOK:
  1266.         case IDCANCEL:
  1267.             EndDialog(hDlg, 0);
  1268.             return(TRUE);
  1269.         }
  1270.         break;
  1271.  
  1272.     case WM_DRAWITEM:
  1273.  
  1274.           DlgDrawItem((DRAWITEMSTRUCT FAR *)MK_FP32((void *)lParam));
  1275.         return(TRUE);
  1276.     }
  1277.     return(FALSE);
  1278. }
  1279. /**********************************************************************/
  1280.  
  1281. static void
  1282. HandleMenu(HWND window, UINT menuID)
  1283. {
  1284.     switch (menuID)
  1285.     {
  1286.         case EXIT_ITEM_ID:
  1287.             DestroyWindow(window);
  1288.             break;
  1289.         case ABOUT_ITEM_ID:
  1290.             DialogBox(AppInstance, "ABOUT", window, MakeProcInstance(AboutDlgProc, AppInstance));
  1291.             break;            
  1292.     }
  1293. }
  1294.  
  1295. /**********************************************************************/
  1296.  
  1297. static void
  1298. HandleCommand(HWND window, UINT controlID)
  1299. {
  1300.     static UINT oldcontrol = 0;
  1301.  
  1302.     if (oldcontrol)
  1303.         SendDlgItemMessage(window, oldcontrol, BM_SETSTATE, FALSE, 0);
  1304.  
  1305.     switch (controlID)
  1306.     {
  1307.         case LOOK_UP_BUTTON_ID:
  1308.             RwTiltCamera(Camera, -CameraTilt);
  1309.             CameraTilt = CREAL(-20.0);
  1310.             RwTiltCamera(Camera, CameraTilt);
  1311.             SetStatusMessage("Look Up");
  1312.             break;
  1313.         case LOOK_AHEAD_BUTTON_ID:
  1314.             RwTiltCamera(Camera, -CameraTilt);
  1315.             CameraTilt = CREAL(0.0);
  1316.             RwTiltCamera(Camera, CameraTilt);
  1317.             SetStatusMessage("Look Ahead");
  1318.             break;
  1319.         case LOOK_DOWN_BUTTON_ID:
  1320.             RwTiltCamera(Camera, -CameraTilt);
  1321.             CameraTilt = CREAL(20.0);
  1322.             RwTiltCamera(Camera, CameraTilt);
  1323.             SetStatusMessage("Look Down");
  1324.             break;
  1325.     }
  1326.     oldcontrol = controlID;
  1327.     if (oldcontrol)
  1328.         SendDlgItemMessage(window, oldcontrol, BM_SETSTATE, TRUE, 0);
  1329.  
  1330.     RenderFlag = TRUE;
  1331. }
  1332.  
  1333. /**********************************************************************/
  1334.  
  1335. long far PASCAL
  1336. WindowProc(HWND window, WORD message, WPARAM wParam, LPARAM lParam)
  1337. {
  1338.     static int init_flag = 0;
  1339.  
  1340.     switch (message)
  1341.     {
  1342.     case WM_CREATE:
  1343.             return 0L;
  1344.  
  1345.     case WM_SIZE:
  1346.             return 0L;
  1347.  
  1348.     case WM_PAINT:
  1349.             HandlePaint(window);
  1350.             if (!init_flag)
  1351.             {
  1352.                 HandleCommand(window, LOOK_AHEAD_BUTTON_ID); /* simulate press */
  1353.                 SetStatusMessage(DEFAULT_STATUS_MESSAGE);
  1354.                 init_flag = TRUE;
  1355.             }
  1356.             return 0L;
  1357.  
  1358.         case WM_DRAWITEM:
  1359.             HandleDrawItem(wParam, (DRAWITEMSTRUCT FAR*)MK_FP32((void*)lParam));
  1360.             return 0L;
  1361.  
  1362.         case WM_COMMAND:
  1363.             if (LOWORD(lParam) == 0)
  1364.             {
  1365.                 HandleMenu(window, wParam);
  1366.             }
  1367.             else
  1368.             {
  1369.                 HandleCommand(window, wParam);
  1370.             }
  1371.             return 0L;
  1372.     
  1373.     case WM_DESTROY:
  1374.         PostQuitMessage(0);
  1375.             return 0L;
  1376.     }
  1377.  
  1378.     return DefWindowProc(window, message, wParam, lParam);
  1379. }
  1380.  
  1381. /**********************************************************************/
  1382.  
  1383. /*
  1384.  * MS Windows application entry point.
  1385.  */
  1386. int PASCAL
  1387. WinMain(HANDLE instance, HANDLE prevInstance, LPSTR cmdLine, int cmdShow)
  1388. {
  1389.     MSG  message;         
  1390.  
  1391.     AppInstance = instance;
  1392.  
  1393.     if (prevInstance)
  1394.     {
  1395.         MessageBox((HWND)0, "RwShop is already running...",
  1396.                    ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  1397.         return FALSE;
  1398.     }
  1399.     if (!InitApplication(instance))
  1400.     {                         
  1401.         MessageBox((HWND)0, "Internal error\nPlease contact Criterion Software Ltd.",
  1402.                    ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  1403.         return FALSE;       
  1404.     }
  1405.  
  1406.     if (!Init3D(instance))
  1407.     {
  1408.     return FALSE;
  1409.     }
  1410.  
  1411.     if (!(Window = InitInstance(instance)))
  1412.     {
  1413.         return FALSE;
  1414.     }
  1415.     CheckDisplayDepth(Window);
  1416.  
  1417.     ShowWindow(Window, cmdShow); 
  1418.     UpdateWindow(Window);
  1419.  
  1420.     while (GetMessage(&message, NULL, 0, 0))
  1421.     {
  1422.     TranslateMessage(&message);
  1423.     DispatchMessage(&message);
  1424.     }
  1425.  
  1426.     TidyUp3D();
  1427.  
  1428.     UnregisterClass(RWSHOP_CLASS_NAME, instance);
  1429.     UnregisterClass(RWWINDOW_CLASS_NAME, instance);
  1430.     UnregisterClass(RWMOVEBUTTON_CLASS_NAME, instance);
  1431.     return message.wParam;
  1432. }
  1433.  
  1434. /**********************************************************************/
  1435.