home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / Managed / Direct3D / EmptyProject / EmptyProject.cs next >
Encoding:
Text File  |  2004-09-27  |  22.3 KB  |  463 lines

  1. //-----------------------------------------------------------------------------
  2. // File: EmptyProject.cs
  3. //
  4. // Starting point for new Direct3D applications
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8.  
  9.  
  10. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  11. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  12.  
  13. using System;
  14. using Microsoft.DirectX;
  15. using Microsoft.DirectX.Direct3D;
  16. using Microsoft.Samples.DirectX.UtilityToolkit;
  17.  
  18. namespace EmptyProjectSample
  19. {
  20.     /// <summary>EmptyProject Sample Class</summary>
  21.     public class EmptyProject : IFrameworkCallback, IDeviceCreation
  22.     {
  23.         #region Creation
  24.         /// <summary>Create a new instance of the class</summary>
  25.         public EmptyProject(Framework f) 
  26.         { 
  27.             // Store framework
  28.             sampleFramework = f; 
  29.             // Create dialogs
  30.             hud = new Dialog(sampleFramework); 
  31.             sampleUi = new Dialog(sampleFramework); 
  32.         }
  33.         #endregion
  34.  
  35.         // Variables
  36.         private Framework sampleFramework = null; // Framework for samples
  37.         private Font statsFont = null; // Font for drawing text
  38.         private Sprite textSprite = null; // Sprite for batching text calls
  39.         private Effect effect = null; // D3DX Effect Interface
  40.         private ModelViewerCamera camera = new ModelViewerCamera(); // A model viewing camera
  41.         private bool isHelpShowing = true; // If true, renders the UI help text
  42.         private Dialog hud = null; // dialog for standard controls
  43.         private Dialog sampleUi = null; // dialog for sample specific controls
  44.  
  45.         // HUD Ui Control constants
  46.         private const int ToggleFullscreen = 1;
  47.         private const int ToggleReference = 3;
  48.         private const int ChangeDevice = 4;
  49.  
  50.         /// <summary>
  51.         /// Called during device initialization, this code checks the device for some 
  52.         /// minimum set of capabilities, and rejects those that don't pass by returning false.
  53.         /// </summary>
  54.         public bool IsDeviceAcceptable(Caps caps, Format adapterFormat, Format backBufferFormat, bool windowed)
  55.         {
  56.             // Skip back buffer formats that don't support alpha blending
  57.             if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, adapterFormat, 
  58.                 Usage.QueryPostPixelShaderBlending, ResourceType.Textures, backBufferFormat))
  59.                 return false;
  60.  
  61.             return true;
  62.         }
  63.  
  64.         /// <summary>
  65.         /// This callback function is called immediately before a device is created to allow the 
  66.         /// application to modify the device settings. The supplied settings parameter 
  67.         /// contains the settings that the framework has selected for the new device, and the 
  68.         /// application can make any desired changes directly to this structure.  Note however that 
  69.         /// the sample framework will not correct invalid device settings so care must be taken 
  70.         /// to return valid device settings, otherwise creating the Device will fail.  
  71.         /// </summary>
  72.         public void ModifyDeviceSettings(DeviceSettings settings, Caps caps)
  73.         {
  74.             // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  75.             // then switch to SWVP.
  76.             if ( (!caps.DeviceCaps.SupportsHardwareTransformAndLight) ||
  77.                 (caps.VertexShaderVersion < new Version(1,1)) )
  78.             {
  79.                 settings.BehaviorFlags = CreateFlags.SoftwareVertexProcessing;
  80.             }
  81.             else
  82.             {
  83.                 settings.BehaviorFlags = CreateFlags.HardwareVertexProcessing;
  84.             }
  85.  
  86.             // This application is designed to work on a pure device by not using 
  87.             // any get methods, so create a pure device if supported and using HWVP.
  88.             if ( (caps.DeviceCaps.SupportsPureDevice) && 
  89.                 ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) )
  90.                 settings.BehaviorFlags |= CreateFlags.PureDevice;
  91.  
  92.             // Debugging vertex shaders requires either REF or software vertex processing 
  93.             // and debugging pixel shaders requires REF.  
  94. #if(DEBUG_VS)
  95.             if (settings.DeviceType != DeviceType.Reference )
  96.             {
  97.                 settings.BehaviorFlags &= ~CreateFlags.HardwareVertexProcessing;
  98.                 settings.BehaviorFlags |= CreateFlags.SoftwareVertexProcessing;
  99.             }
  100. #endif
  101. #if(DEBUG_PS)
  102.             settings.DeviceType = DeviceType.Reference;
  103. #endif
  104.  
  105.         }
  106.  
  107.         /// <summary>
  108.         /// This event will be fired immediately after the Direct3D device has been 
  109.         /// created, which will happen during application initialization and windowed/full screen 
  110.         /// toggles. This is the best location to create Pool.Managed resources since these 
  111.         /// resources need to be reloaded whenever the device is destroyed. Resources created  
  112.         /// here should be released in the Disposing event. 
  113.         /// </summary>
  114.         private void OnCreateDevice(object sender, DeviceEventArgs e)
  115.         {
  116.             // Initialize the stats font
  117.             statsFont = ResourceCache.GetGlobalInstance().CreateFont(e.Device, 15, 0, FontWeight.Bold, 1, false, CharacterSet.Default,
  118.                 Precision.Default, FontQuality.Default, PitchAndFamily.FamilyDoNotCare | PitchAndFamily.DefaultPitch
  119.                 , "Arial");
  120.  
  121.             // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  122.             // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  123.             // processing, and debugging pixel shaders requires REF.  The 
  124.             // ShaderFlags.Force*SoftwareNoOptimizations flag improves the debug experience in the 
  125.             // shader debugger.  It enables source level debugging, prevents instruction 
  126.             // reordering, prevents dead code elimination, and forces the compiler to compile 
  127.             // against the next higher available software target, which ensures that the 
  128.             // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  129.             // flags will cause slower rendering since the shaders will be unoptimized and 
  130.             // forced into software.  See the DirectX documentation for more information about 
  131.             // using the shader debugger.
  132.             ShaderFlags shaderFlags = ShaderFlags.None;
  133. #if(DEBUG_VS)
  134.             shaderFlags |= ShaderFlags.ForceVertexShaderSoftwareNoOptimizations;
  135. #endif
  136. #if(DEBUG_PS)
  137.             shaderFlags |= ShaderFlags.ForcePixelShaderSoftwareNoOptimizations;
  138. #endif
  139.             // Read the D3DX effect file
  140.             string path = Utility.FindMediaFile("EmptyProject.fx");
  141.             effect = ResourceCache.GetGlobalInstance().CreateEffectFromFile(e.Device,
  142.                 path, null, null, shaderFlags, null);
  143.  
  144.             // Setup the camera's view parameters
  145.             camera.SetViewParameters(new Vector3(0.0f, 0.0f, -5.0f), Vector3.Empty);
  146.         }
  147.         
  148.         /// <summary>
  149.         /// This event will be fired immediately after the Direct3D device has been 
  150.         /// reset, which will happen after a lost device scenario. This is the best location to 
  151.         /// create Pool.Default resources since these resources need to be reloaded whenever 
  152.         /// the device is lost. Resources created here should be released in the OnLostDevice 
  153.         /// event. 
  154.         /// </summary>
  155.         private void OnResetDevice(object sender, DeviceEventArgs e)
  156.         {
  157.             SurfaceDescription desc = e.BackBufferDescription;
  158.             // Create a sprite to help batch calls when drawing many lines of text
  159.             textSprite = new Sprite(e.Device);
  160.  
  161.             // Setup the camera's projection parameters
  162.             float aspectRatio = (float)desc.Width / (float)desc.Height;
  163.             camera.SetProjectionParameters((float)Math.PI / 4, aspectRatio, 0.1f, 1000.0f);
  164.             camera.SetWindow(desc.Width, desc.Height);
  165.  
  166.             // Setup UI locations
  167.             hud.SetLocation(desc.Width-170, 0);
  168.             hud.SetSize(170,170);
  169.             sampleUi.SetLocation(desc.Width - 170, desc.Height - 350);
  170.             sampleUi.SetSize(170,300);
  171.         }
  172.  
  173.         /// <summary>
  174.         /// This event function will be called fired after the Direct3D device has 
  175.         /// entered a lost state and before Device.Reset() is called. Resources created
  176.         /// in the OnResetDevice callback should be released here, which generally includes all 
  177.         /// Pool.Default resources. See the "Lost Devices" section of the documentation for 
  178.         /// information about lost devices.
  179.         /// </summary>
  180.         private void OnLostDevice(object sender, EventArgs e)
  181.         {
  182.             if (textSprite != null)
  183.             {
  184.                 textSprite.Dispose();
  185.                 textSprite = null;
  186.             }
  187.         }
  188.  
  189.         /// <summary>
  190.         /// This callback function will be called immediately after the Direct3D device has 
  191.         /// been destroyed, which generally happens as a result of application termination or 
  192.         /// windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  193.         /// should be released here, which generally includes all Pool.Managed resources. 
  194.         /// </summary>
  195.         private void OnDestroyDevice(object sender, EventArgs e)
  196.         {
  197.         }
  198.  
  199.         /// <summary>
  200.         /// This callback function will be called once at the beginning of every frame. This is the
  201.         /// best location for your application to handle updates to the scene, but is not 
  202.         /// intended to contain actual rendering calls, which should instead be placed in the 
  203.         /// OnFrameRender callback.  
  204.         /// </summary>
  205.         public void OnFrameMove(Device device, double appTime, float elapsedTime)
  206.         {
  207.             // Update the camera's position based on user input 
  208.             camera.FrameMove(elapsedTime);
  209.         }
  210.  
  211.         /// <summary>
  212.         /// This callback function will be called at the end of every frame to perform all the 
  213.         /// rendering calls for the scene, and it will also be called if the window needs to be 
  214.         /// repainted. After this function has returned, the sample framework will call 
  215.         /// Device.Present to display the contents of the next buffer in the swap chain
  216.         /// </summary>
  217.         public void OnFrameRender(Device device, double appTime, float elapsedTime)
  218.         {
  219.             bool beginSceneCalled = false;
  220.  
  221.             // Clear the render target and the zbuffer 
  222.             device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, 0x002D32AA, 1.0f, 0);
  223.             try
  224.             {
  225.                 device.BeginScene();
  226.                 beginSceneCalled = true;
  227.  
  228.                 // Update the effect's variables.  Instead of using strings, it would 
  229.                 // be more efficient to cache a handle to the parameter by calling 
  230.                 // Effect.GetParameter
  231.                 effect.SetValue("worldViewProjection", camera.WorldMatrix * camera.ViewMatrix * camera.ProjectionMatrix);
  232.                 effect.SetValue("worldMatrix", camera.WorldMatrix);
  233.                 effect.SetValue("appTime", (float)appTime);
  234.  
  235.                 // Show frame rate
  236.                 RenderText();
  237.  
  238.                 // Show UI
  239.                 hud.OnRender(elapsedTime);
  240.                 sampleUi.OnRender(elapsedTime);
  241.             }
  242.             finally
  243.             {
  244.                 if (beginSceneCalled)
  245.                     device.EndScene();
  246.             }
  247.         }
  248.  
  249.         /// <summary>
  250.         /// Render the help and statistics text. This function uses the Font object for 
  251.         /// efficient text rendering.
  252.         /// </summary>
  253.         private void RenderText()
  254.         {
  255.             TextHelper txtHelper = new TextHelper(statsFont, textSprite, 15);
  256.  
  257.             // Output statistics
  258.             txtHelper.Begin();
  259.             txtHelper.SetInsertionPoint(5,5);
  260.             txtHelper.SetForegroundColor(System.Drawing.Color.Yellow);
  261.             txtHelper.DrawTextLine(sampleFramework.FrameStats);
  262.             txtHelper.DrawTextLine(sampleFramework.DeviceStats);
  263.  
  264.             txtHelper.SetForegroundColor(System.Drawing.Color.White);
  265.             txtHelper.DrawTextLine("Put some status text here.");
  266.  
  267.             // Draw help
  268.             if (isHelpShowing)
  269.             {
  270.                 txtHelper.SetInsertionPoint(10, sampleFramework.BackBufferSurfaceDescription.Height-15*6);
  271.                 txtHelper.SetForegroundColor(System.Drawing.Color.DarkOrange);
  272.                 txtHelper.DrawTextLine("Controls (F1 to hide):");
  273.  
  274.                 txtHelper.SetInsertionPoint(40, sampleFramework.BackBufferSurfaceDescription.Height-15*5);
  275.                 txtHelper.DrawTextLine("Help Item Misc: X");
  276.                 txtHelper.DrawTextLine("Quit: Esc");
  277.                 txtHelper.DrawTextLine("Hide help: F1");
  278.             }
  279.             else
  280.             {
  281.                 txtHelper.SetInsertionPoint(10, sampleFramework.BackBufferSurfaceDescription.Height-15*2);
  282.                 txtHelper.SetForegroundColor(System.Drawing.Color.White);
  283.                 txtHelper.DrawTextLine("Press F1 for help");
  284.             }
  285.  
  286.             txtHelper.End();
  287.         }
  288.  
  289.         /// <summary>
  290.         /// As a convenience, the sample framework inspects the incoming windows messages for
  291.         /// keystroke messages and decodes the message parameters to pass relevant keyboard
  292.         /// messages to the application.  The framework does not remove the underlying keystroke 
  293.         /// messages, which are still passed to the application's MsgProc callback.
  294.         /// </summary>
  295.         private void OnKeyEvent(System.Windows.Forms.Keys key, bool isKeyDown, bool isKeyUp)
  296.         {
  297.             if (isKeyDown)
  298.             {
  299.                 switch(key)
  300.                 {
  301.                     case System.Windows.Forms.Keys.F1:
  302.                         isHelpShowing = !isHelpShowing;
  303.                         break;
  304.                 }
  305.             }
  306.         }
  307.  
  308.         /// <summary>
  309.         /// Before handling window messages, the sample framework passes incoming windows 
  310.         /// messages to the application through this callback function. If the application sets 
  311.         /// noFurtherProcessing to true, the sample framework will not process the message
  312.         /// </summary>
  313.         public IntPtr OnMsgProc(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam, ref bool noFurtherProcessing)
  314.         {
  315.             // Give the dialog a chance to handle the message first
  316.             noFurtherProcessing = hud.MessageProc(hWnd, msg, wParam, lParam);
  317.             if (noFurtherProcessing)
  318.                 return IntPtr.Zero;
  319.  
  320.             noFurtherProcessing = sampleUi.MessageProc(hWnd, msg, wParam, lParam);
  321.             if (noFurtherProcessing)
  322.                 return IntPtr.Zero;
  323.  
  324.             // Pass all remaining windows messages to camera so it can respond to user input
  325.             camera.HandleMessages(hWnd, msg, wParam, lParam);
  326.  
  327.             return IntPtr.Zero;
  328.         }
  329.  
  330.         /// <summary>
  331.         /// Initializes the application
  332.         /// </summary>
  333.         public void InitializeApplication()
  334.         {
  335.             int y = 10;
  336.             // Initialize the HUD
  337.             Button fullScreen = hud.AddButton(ToggleFullscreen,"Toggle full screen", 35, y, 125,22);
  338.             Button toggleRef = hud.AddButton(ToggleReference,"Toggle reference (F3)", 35, y += 24, 125,22);
  339.             Button changeDevice = hud.AddButton(ChangeDevice,"Change Device (F2)", 35, y += 24, 125,22);
  340.             // Hook the button events for when these items are clicked
  341.             fullScreen.Click += new EventHandler(OnFullscreenClicked);
  342.             toggleRef.Click += new EventHandler(OnRefClicked);
  343.             changeDevice.Click += new EventHandler(OnChangeDevicClicked);
  344.  
  345.             // Now add the sample specific UI
  346.             y = 10;
  347.             const int ComboBox1 = ChangeDevice + 1;
  348.             const int CheckBox1 = ChangeDevice + 2;
  349.             const int CheckBox2 = ChangeDevice + 3;
  350.             const int Radiobutton1 = ChangeDevice + 4;
  351.             const int Radiobutton2 = ChangeDevice + 5;
  352.             const int Radiobutton3 = ChangeDevice + 6;
  353.             const int Button1 = ChangeDevice + 7;
  354.             const int Button2 = ChangeDevice + 8;
  355.             const int Radiobutton4 = ChangeDevice + 9;
  356.             const int Radiobutton5 = ChangeDevice + 10;
  357.             const int SliderControl = ChangeDevice + 11;
  358.             
  359.             ComboBox cb1 = sampleUi.AddComboBox(ComboBox1, 35, y +=24, 125, 22);
  360.             for (int i = 0; i < 50; i++) cb1.AddItem("Item#" + i.ToString(), null);
  361.             sampleUi.AddCheckBox(CheckBox1, "Checkbox1", 35, y+=24, 125,22, false);
  362.             sampleUi.AddCheckBox(CheckBox2, "Checkbox2", 35, y+=24, 125,22, false);
  363.             sampleUi.AddRadioButton(Radiobutton1, 1, "Radio1G1", 35, y+=24, 125, 22, true);
  364.             sampleUi.AddRadioButton(Radiobutton2, 1, "Radio2G1", 35, y+=24, 125, 22, false);
  365.             sampleUi.AddRadioButton(Radiobutton3, 1, "Radio3G1", 35, y+=24, 125, 22, false);
  366.             sampleUi.AddButton(Button1, "Button1", 35, y+=24, 125, 22);
  367.             sampleUi.AddButton(Button2, "Button2", 35, y+=24, 125, 22);
  368.             sampleUi.AddRadioButton(Radiobutton4, 2, "Radio1G2", 35, y+=24, 125, 22, true);
  369.             sampleUi.AddRadioButton(Radiobutton5, 2, "Radio2G2", 35, y+=24, 125, 22, false);
  370.             sampleUi.AddSlider(SliderControl, 50,y+=24, 100, 22);
  371.  
  372.             // If you wanted to respond to any of these you would need to add an event hook here
  373.         }
  374.  
  375.         /// <summary>Called when the change device button is clicked</summary>
  376.         private void OnChangeDevicClicked(object sender, EventArgs e)
  377.         {
  378.             sampleFramework.ShowSettingsDialog(!sampleFramework.IsD3DSettingsDialogShowing);
  379.         }
  380.  
  381.         /// <summary>Called when the full screen button is clicked</summary>
  382.         private void OnFullscreenClicked(object sender, EventArgs e)
  383.         {
  384.             sampleFramework.ToggleFullscreen();
  385.         }
  386.  
  387.         /// <summary>Called when the ref button is clicked</summary>
  388.         private void OnRefClicked(object sender, EventArgs e)
  389.         {
  390.             sampleFramework.ToggleReference();
  391.         }
  392.  
  393.         /// <summary>
  394.         /// Entry point to the program. Initializes everything and goes into a message processing 
  395.         /// loop. Idle time is used to render the scene.
  396.         /// </summary>
  397.         static int Main() 
  398.         {
  399.             using(Framework sampleFramework = new Framework())
  400.             {
  401.                 EmptyProject sample = new EmptyProject(sampleFramework);
  402.                 // Set the callback functions. These functions allow the sample framework to notify
  403.                 // the application about device changes, user input, and windows messages.  The 
  404.                 // callbacks are optional so you need only set callbacks for events you're interested 
  405.                 // in. However, if you don't handle the device reset/lost callbacks then the sample 
  406.                 // framework won't be able to reset your device since the application must first 
  407.                 // release all device resources before resetting.  Likewise, if you don't handle the 
  408.                 // device created/destroyed callbacks then the sample framework won't be able to 
  409.                 // recreate your device resources.
  410.                 sampleFramework.Disposing += new EventHandler(sample.OnDestroyDevice);
  411.                 sampleFramework.DeviceLost += new EventHandler(sample.OnLostDevice);
  412.                 sampleFramework.DeviceCreated += new DeviceEventHandler(sample.OnCreateDevice);
  413.                 sampleFramework.DeviceReset += new DeviceEventHandler(sample.OnResetDevice);
  414.  
  415.                 sampleFramework.SetKeyboardCallback(new KeyboardCallback(sample.OnKeyEvent));
  416.                 sampleFramework.SetWndProcCallback(new WndProcCallback(sample.OnMsgProc));
  417.  
  418.                 sampleFramework.SetCallbackInterface(sample);
  419.                 try
  420.                 {
  421.  
  422.                     // Show the cursor and clip it when in full screen
  423.                     sampleFramework.SetCursorSettings(true, true);
  424.  
  425.                     // Initialize
  426.                     sample.InitializeApplication();
  427.  
  428.                     // Initialize the sample framework and create the desired window and Direct3D 
  429.                     // device for the application. Calling each of these functions is optional, but they
  430.                     // allow you to set several options which control the behavior of the sampleFramework.
  431.                     sampleFramework.Initialize( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  432.                     sampleFramework.CreateWindow("EmptyProject");
  433.                     sampleFramework.CreateDevice( 0, true, Framework.DefaultSizeWidth, Framework.DefaultSizeHeight, 
  434.                         sample);
  435.  
  436.                     // Pass control to the sample framework for handling the message pump and 
  437.                     // dispatching render calls. The sample framework will call your FrameMove 
  438.                     // and FrameRender callback when there is idle time between handling window messages.
  439.                     sampleFramework.MainLoop();
  440.  
  441.                 }
  442. #if(DEBUG)
  443.                 catch (Exception e)
  444.                 {
  445.                     // In debug mode show this error (maybe - depending on settings)
  446.                     sampleFramework.DisplayErrorMessage(e);
  447. #else
  448.             catch
  449.             {
  450.                 // In release mode fail silently
  451. #endif
  452.                     // Ignore any exceptions here, they would have been handled by other areas
  453.                     return (sampleFramework.ExitCode == 0) ? 1 : sampleFramework.ExitCode; // Return an error code here
  454.                 }
  455.  
  456.                 // Perform any application-level cleanup here. Direct3D device resources are released within the
  457.                 // appropriate callback functions and therefore don't require any cleanup code here.
  458.                 return sampleFramework.ExitCode;
  459.             }
  460.         }
  461.     }
  462. }
  463.