//BSD License  
//DXGfx® - http://www.eteractions.com
//Copyright (c) 2005
//by Guillaume Randon
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software
//and associated documentation files (the "Software"), to deal in the Software without restriction,
//including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
//and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
//subject to the following conditions:
//The above copyright notice and this permission notice shall be included in all copies or substantial
//portions of the Software.
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
//AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
//DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.Samples.DirectX.UtilityToolkit;
using Microsoft.DirectX.DirectSound;
using DXGfxLib;
using Game;

namespace Sample
{
    class Sample : IFrameworkCallback, IDeviceCreation
    {
        // Variables
        private Framework sampleFramework = null; // Framework for samples
        private Font statsFont = null; // Font for drawing text
        private Sprite textSprite = null; // Sprite for batching text calls
        //private ThirdPersonCamera camera = new ThirdPersonCamera(); // A model viewing camera
        private bool isHelpShowing = true; // If true, renders the UI help text
        private Dialog hud = null; // dialog for standard controls
        private Dialog missionUi = null;
        private Matrix worldCenter;

        // HUD Ui Control constants
        private const int ToggleFullscreen = 1;
        private const int ToggleReference = 3;
        private const int ChangeDevice = 4;

        // DXGfxLib related variables
        private OutDoorScene outdoorScene;
        private Matrix computedViewMat;
        private const int MissionText = 1;

        // Wordl related variables
        //private Tiger tiger;
        private World world;
        private Boat boat;
        private Vegetals veg;
        private double lastAIUpdate = 0.0f;
        private Hashtable worldEntities = new Hashtable();

        // Need a soundDevice in order to be able to play sounds.
        private Microsoft.DirectX.DirectSound.Device soundDevice = null;

        private StateBlock defaultState = null;

        #region Creation
        /// <summary>Create a new instance of the class</summary>
        public Sample(Framework f) 
        { 
            // Store framework
            sampleFramework = f; 
            // Create dialogs
            hud = new Dialog(sampleFramework); 
            missionUi = new Dialog(sampleFramework);

            DXGfxManager.GetGlobalInstance().Init(sampleFramework);
        }
        #endregion

        public void InitSound()
        {
            soundDevice = new Microsoft.DirectX.DirectSound.Device();
            soundDevice.SetCooperativeLevel(this.sampleFramework.Window.Handle, CooperativeLevel.Priority);
        }

        /// <summary>
        /// Called during device initialization, this code checks the device for some 
        /// minimum set of capabilities, and rejects those that don't pass by returning false.
        /// In this implementation we require at least support for shader 1.1 and we require
        /// a backbuffer format which does support alpha blending.
        /// </summary>
        public bool IsDeviceAcceptable(Microsoft.DirectX.Direct3D.Caps caps, Format adapterFormat, Format backBufferFormat, bool windowed)
        {
            // No fallback, need at least PS1.1
            if (caps.PixelShaderVersion < new Version(1, 1))
                return false;

            // Skip back buffer formats that don't support alpha blending
            if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, adapterFormat,
                Usage.QueryPostPixelShaderBlending, ResourceType.Textures, backBufferFormat))
                return false;

            return true;
        }

        /// <summary>
        /// This callback function is called immediately before a device is created to allow the 
        /// application to modify the device settings. The supplied settings parameter 
        /// contains the settings that the framework has selected for the new device, and the 
        /// application can make any desired changes directly to this structure.  Note however that 
        /// the sample framework will not correct invalid device settings so care must be taken 
        /// to return valid device settings, otherwise creating the Device will fail.  
        /// </summary>
        public void ModifyDeviceSettings(DeviceSettings settings, Microsoft.DirectX.Direct3D.Caps caps)
        {
            // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
            // then switch to SWVP.
            //if ((!caps.DeviceCaps.SupportsHardwareTransformAndLight) ||
            //    (caps.VertexShaderVersion < new Version(1, 1)))
            if(!caps.DeviceCaps.SupportsHardwareTransformAndLight)
            {
                settings.BehaviorFlags = CreateFlags.SoftwareVertexProcessing;
                settings.BehaviorFlags = CreateFlags.MixedVertexProcessing;
            }
            else
            {
                settings.BehaviorFlags = CreateFlags.HardwareVertexProcessing;
            }

            // This application is designed to work on a pure device by not using 
            // any get methods, so create a pure device if supported and using HWVP.
            if ((caps.DeviceCaps.SupportsPureDevice) &&
                ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0))
            {
                // Until the state manager is implemented it is better to keep this commented !!
                //settings.BehaviorFlags |= CreateFlags.DisableDriverManagement;
                //settings.BehaviorFlags |= CreateFlags.PureDevice;
            }
            // Debugging vertex shaders requires either REF or software vertex processing 
            // and debugging pixel shaders requires REF.  
#if(DEBUG_VS)
            if (settings.DeviceType != DeviceType.Reference )
            {
                settings.BehaviorFlags &= ~CreateFlags.HardwareVertexProcessing;
                settings.BehaviorFlags |= CreateFlags.SoftwareVertexProcessing;
            }
#endif
#if(DEBUG_PS)
            settings.DeviceType = DeviceType.Reference;
#endif

            // For the first device created if its a REF device, optionally display a warning dialog box
            if (settings.DeviceType == DeviceType.Reference)
            {
                Utility.DisplaySwitchingToRefWarning(sampleFramework, "Sample");
            }
        }

        /// <summary>
        /// This event will be fired immediately after the Direct3D device has been 
        /// created, which will happen during application initialization and windowed/full screen 
        /// toggles. This is the best location to create Pool.Managed resources since these 
        /// resources need to be reloaded whenever the device is destroyed. Resources created  
        /// here should be released in the Disposing event. 
        /// </summary>
        private void OnCreateDevice(object sender, DeviceEventArgs e)
        {
            // Initialize the stats font
            statsFont = ResourceCache.GetGlobalInstance().CreateFont(e.Device, 15, 0, FontWeight.Bold, 1, false, CharacterSet.Default,
                Precision.Default, FontQuality.Default, PitchAndFamily.FamilyDoNotCare | PitchAndFamily.DefaultPitch
                , "Arial");

            // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
            // shader debugger. Debugging vertex shaders requires either REF or software vertex 
            // processing, and debugging pixel shaders requires REF.  The 
            // ShaderFlags.Force*SoftwareNoOptimizations flag improves the debug experience in the 
            // shader debugger.  It enables source level debugging, prevents instruction 
            // reordering, prevents dead code elimination, and forces the compiler to compile 
            // against the next higher available software target, which ensures that the 
            // unoptimized shaders do not exceed the shader model limitations.  Setting these 
            // flags will cause slower rendering since the shaders will be unoptimized and 
            // forced into software.  See the DirectX documentation for more information about 
            // using the shader debugger.
            ShaderFlags shaderFlags = ShaderFlags.NotCloneable;
#if(DEBUG_VS)
            shaderFlags |= ShaderFlags.ForceVertexShaderSoftwareNoOptimizations;
#endif
#if(DEBUG_PS)
            shaderFlags |= ShaderFlags.ForcePixelShaderSoftwareNoOptimizations;
#endif

            // Before everything let's notify the DXGfxManager
            DXGfxManager.GetGlobalInstance().OnCreateDevice(sender, e);

            // Let's create our scene
            AABBox desiredBBox = new AABBox(new BBox(new Vector3(0.0f, 0.0f, 0.0f), 1000.0f));
            outdoorScene = new OutDoorScene(desiredBBox, 2);
            DXGfxManager.GetGlobalInstance().SetScene(outdoorScene);

            world = new World();
            world.Attach(outdoorScene);

            // Setup the camera's view parameters
            DXGfxManager.GetGlobalInstance().CurrentCamera.SetViewParameters(new Vector3(0.0f, 0.0f, -5.0f), Vector3.Empty);

            //outdoorScene.camera = camera;
            outdoorScene.LoadTerrain(e.Device, "heigthmap.bmp");

            //Water theWater = new Water(e.Device, 2000, 2000, 10, 10, "water.bmp");
            Water2 theWater = new Water2(2000);
            outdoorScene.SceneWater = theWater;

            //SkyBox theSky = new SkyBox(e.Device, "skybox2.x", 160);
            //outdoorScene.SceneSky = theSky;
            SkyDome theSky = new SkyDome();
            theSky.LoadFromFile(e.Device, "domei.x");
            outdoorScene.SceneSky = theSky;
            //FrameworkMesh tigerMesh = new FrameworkMesh(e.Device, "tiger.x");
            //SceneObject sceneObject = outdoorScene.Attach(tigerMesh);

            FrameworkMesh boatMesh = new FrameworkMesh(e.Device, "tiger.x");
            SceneObject sceneObject = outdoorScene.Attach(boatMesh);

            Random rand = new Random();
            float tigerx = rand.Next(-500, 500);
            float tigerz = rand.Next(-500, 500);
            float tigery = sceneObject.extents.Y * 0.5f + outdoorScene.GetHeigth(tigerx, tigerz);

            // This will guarantee we put our boat on Water !!
            while (tigery > 0.0f)
            {
                tigerx = rand.Next(-500, 500);
                tigerz = rand.Next(-500, 500);
                tigery = sceneObject.extents.Y * 0.5f + outdoorScene.GetHeigth(tigerx, tigerz);
            }

            sceneObject.WorldMat = Matrix.Translation(tigerx, 0.0f, tigerz);
            //tiger = new Tiger();
            //tiger.SceneObject = sceneObject;
            //worldEntities.Add(sceneObject, tiger);
            //tiger.speed = 20.0f;
            //tiger.selectSound = new SecondaryBuffer("oink5.wav", soundDevice);
            //tiger.channels.Add(new TigerChannel());
            boat = new Boat();
            boat.SceneObject = sceneObject;
            worldEntities.Add(sceneObject, boat);
            boat.speed = 20.0f;

            //ObjectFromObj testObj = new ObjectFromObj();
            //testObj.Load(e.Device, "ZMapper_Elephant.obj");
            //testObj.Position = new Vector3(tigerx + 5.0f, tigery + 5.0f, tigerz + 5.0f);
            //outdoorScene.Attach(testObj);

            //MeshRessource tree = new MeshRessource(e.Device, "sapin.x");
            ////Matrix[] matrices = new Matrix[500];

            //for (int i = 0; i < 2000; i++)
            //{
            //    ObjectFromMeshRessource treeObj = new ObjectFromMeshRessource();
            //    treeObj.Attach(tree);
            //    float x = rand.Next(-500, 500);
            //    float z = rand.Next(-500, 500);
            //    float y = outdoorScene.GetHeigth(x, z);

            //    while (y < 35.0f)
            //    {
            //        x = rand.Next(-500, 500);
            //        z = rand.Next(-500, 500);
            //        y = outdoorScene.GetHeigth(x, z);
            //    }
            //    treeObj.Position = new Vector3(x, y, z);
            //    outdoorScene.AttachStatic(treeObj);
            //    //matrices[i] = Matrix.Translation(x, y, z);
            //}
            //Impostor imp = new Impostor();
            //imp.Attach(tree);

            //ExtendedMaterial[] materials = null;
            //Mesh theMesh = Mesh.FromFile("sapin.x", MeshFlags.SystemMemory, e.Device, out materials);

            //// We need to extract the material properties and texture names 
            //Texture[] meshTextures = new Texture[materials.Length];
            //Material[] meshMaterials = new Material[materials.Length];
            //for (int i = 0; i < materials.Length; i++)
            //{
            //    meshMaterials[i] = materials[i].Material3D;
            //    // Set the ambient color for the material (D3DX does not do this)
            //    meshMaterials[i].Ambient = meshMaterials[i].Diffuse;

            //    // Create the texture
            //    meshTextures[i] = ResourceCache.GetGlobalInstance().CreateTextureFromFile(e.Device,
            //                                                                      materials[i].TextureFilename);
            //}
            //outdoorScene.AttachBatch(imp.meshes[0], imp.meshMaterials, imp.meshTextures, matrices);





            //MeshRessource tour = new MeshRessource(e.Device, "tour.x");

            //for (int i = 0; i < 100; i++)
            //{
            //    ObjectFromMeshRessource tourObj = new ObjectFromMeshRessource();
            //    tourObj.Attach(tour);
            //    float x = rand.Next(-500, 500);
            //    float z = rand.Next(-500, 500);
            //    float y = outdoorScene.GetHeigth(x, z);

            //    while (y < 60.0f)
            //    {
            //        x = rand.Next(-500, 500);
            //        z = rand.Next(-500, 500);
            //        y = outdoorScene.GetHeigth(x, z);
            //    }
            //    Matrix s = Matrix.Scaling(2.0f, 3.0f, 2.0f);
            //    tourObj.ApplyLocalTransform(s);
            //    tourObj.Position = new Vector3(x, y, z);
            //    outdoorScene.AttachStatic(tourObj);
            //}

            //Eating eat = new Eating(tiger);
            //eat.complement = veg;
            //Mission tigerMission = new Mission();
            //Step uniqueStep = new Step();
            //uniqueStep.actionToBePerformed = eat;
            //tigerMission.start = uniqueStep;
            //tigerMission.currentStep = uniqueStep;
            //tiger.mission = tigerMission;

            // At the moment the positionning of an articulated model is not correct. Articulated mode
            // display the model, run the default animation but the model is always in 0,0,0 in world space coordinates.
            // This should be fixed soon.
            //ArticulatedModel tiny = new ArticulatedModel();
            //tiny.LoadFromFile(e.Device, "tiny.x");
            //float tinyy = tiny.extents.Y*0.5f + outdoorScene.GetHeigth(2.0f, 10.0f);
            //tiny.Position = new Vector3(2.0f, tinyy, 10.0f);
            //outdoorScene.Attach(tiny);

            DXGfxManager.GetGlobalInstance().CurrentCamera.Person = boat.SceneObject;
            DXGfxManager.GetGlobalInstance().CurrentCamera.camera.positionConstraint = outdoorScene;
            DXGfxManager.GetGlobalInstance().CurrentCamera.Person.positionConstraint = outdoorScene;
        }

        /// <summary>
        /// This event will be fired immediately after the Direct3D device has been 
        /// reset, which will happen after a lost device scenario. This is the best location to 
        /// create Pool.Default resources since these resources need to be reloaded whenever 
        /// the device is lost. Resources created here should be released in the OnLostDevice 
        /// event. 
        /// </summary>
        private void OnResetDevice(object sender, DeviceEventArgs e)
        {
            SurfaceDescription desc = e.BackBufferDescription;
            // Create a sprite to help batch calls when drawing many lines of text
            textSprite = new Sprite(e.Device);

            // Setup the camera's projection parameters
            DXGfxManager.GetGlobalInstance().OnDeviceReset(sender, e);

            // Setup UI locations
            hud.SetLocation(desc.Width - 170, 0);
            hud.SetSize(170, 170);

            // Scene call
            outdoorScene.DeviceChanged(e.Device);

            missionUi.SetLocation(0, desc.Height - 120);
            missionUi.SetSize(170, 120);
        }

        /// <summary>
        /// This event function will be called fired after the Direct3D device has 
        /// entered a lost state and before Device.Reset() is called. Resources created
        /// in the OnResetDevice callback should be released here, which generally includes all 
        /// Pool.Default resources. See the "Lost Devices" section of the documentation for 
        /// information about lost devices.
        /// </summary>
        private void OnLostDevice(object sender, EventArgs e)
        {
            if (outdoorScene != null)
            {
                outdoorScene.CleanOnLostDevice();
            }

            if (textSprite != null)
            {
                textSprite.Dispose();
                textSprite = null;
            }
        }

        /// <summary>
        /// This callback function will be called immediately after the Direct3D device has 
        /// been destroyed, which generally happens as a result of application termination or 
        /// windowed/full screen toggles. Resources created in the OnCreateDevice callback 
        /// should be released here, which generally includes all Pool.Managed resources. 
        /// </summary>
        private void OnDestroyDevice(object sender, EventArgs e)
        {
            //meshTextures = null;
            //meshMaterials = null;

            //if (fullMesh != null)
            //    fullMesh.Dispose();

            //if ((meshes != null) && (meshes.Length > 0))
            //{
            //    for (int i = 0; i < meshes.Length; i++)
            //    {
            //        if (meshes[i] != null)
            //            meshes[i].Dispose();
            //    }
            //}
            //meshes = null;
        }

        /// <summary>
        /// This callback function will be called once at the beginning of every frame. This is the
        /// best location for your application to handle updates to the scene, but is not 
        /// intended to contain actual rendering calls, which should instead be placed in the 
        /// OnFrameRender callback.  
        /// </summary>
        public void OnFrameMove(Microsoft.DirectX.Direct3D.Device device, double appTime, float elapsedTime)
        {
            // Update the camera's position based on user input 
            DXGfxManager.GetGlobalInstance().CurrentInputHandler.FrameMove(elapsedTime);

            // Let's update our tiger
            double tmp = appTime - lastAIUpdate;
            //if (tmp > 10)
            //{
            //tiger.UpdateAI(appTime, elapsedTime);
            //tiger.UpdateIA(elapsedTime, appTime);
            boat.UpdateAI(appTime, elapsedTime);
            lastAIUpdate = appTime;
            //}

            //if (tiger.mission.missionCompleted)
            //{
            //    missionUi.GetButton(MissionText).SetText("Mission Completed!!");
            //}
            //switch (tiger.currentState)
            //{
            //    case State.Bois:
            //        missionUi.GetButton(MissionText).SetText("Bois!!");
            //        break;
            //    case State.Dort:
            //        missionUi.GetButton(MissionText).SetText("Dort!!");
            //        break;
            //    case State.Explore:
            //        missionUi.GetButton(MissionText).SetText("Explore!!");
            //        break;
            //    case State.Fuit:
            //        missionUi.GetButton(MissionText).SetText("Fuit!!");
            //        break;
            //    case State.Mange:
            //        missionUi.GetButton(MissionText).SetText("Mange!!");
            //        break;
            //    default:
            //        missionUi.GetButton(MissionText).SetText("Default!!");
            //        break;
            //}
        }

        /// <summary>
        /// This callback function will be called at the end of every frame to perform all the 
        /// rendering calls for the scene, and it will also be called if the window needs to be 
        /// repainted. After this function has returned, the sample framework will call 
        /// Device.Present to display the contents of the next buffer in the swap chain
        /// </summary>
        public void OnFrameRender(Microsoft.DirectX.Direct3D.Device device, double appTime, float elapsedTime)
        {
            bool beginSceneCalled = false;

            if (defaultState==null)
            {
                defaultState = new StateBlock(device, StateBlockType.All);
                defaultState.Capture();
            }

            // Get the world matrix
            Matrix worldMatrix = worldCenter * DXGfxManager.GetGlobalInstance().CurrentCamera.WorldMatrix;
            computedViewMat = Matrix.Multiply(DXGfxManager.GetGlobalInstance().CurrentCamera.WorldMatrix, DXGfxManager.GetGlobalInstance().CurrentCamera.ViewMatrix);
            outdoorScene.Update(device, computedViewMat, DXGfxManager.GetGlobalInstance().CurrentCamera.ProjectionMatrix, appTime, elapsedTime);

            defaultState.Apply();

            // Clear the render target and the zbuffer 
            device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, 0x00424B79, 1.0f, 0);
            try
            {
                //device.BeginScene();
                beginSceneCalled = true;

                // Show scene
                device.SetTransform(TransformType.World, DXGfxManager.GetGlobalInstance().CurrentCamera.WorldMatrix);
                device.SetTransform(TransformType.View, computedViewMat);
                device.SetTransform(TransformType.Projection, DXGfxManager.GetGlobalInstance().CurrentCamera.ProjectionMatrix);
                outdoorScene.RenderScene(device, outdoorScene.currentFrustrum);

                device.RenderState.AlphaBlendEnable = false;

                // Show frame rate
                RenderText();

                // Show UI
                hud.OnRender(elapsedTime);
                missionUi.OnRender(elapsedTime);
            }
            finally
            {
                //if (beginSceneCalled)
                //    device.EndScene();
            }
        }

        /// <summary>
        /// Render the help and statistics text. This function uses the Font object for 
        /// efficient text rendering.
        /// </summary>
        private void RenderText()
        {
            TextHelper txtHelper = new TextHelper(statsFont, textSprite, 15);

            // Output statistics
            txtHelper.Begin();
            txtHelper.SetInsertionPoint(5, 5);
            txtHelper.SetForegroundColor(System.Drawing.Color.Yellow);
            txtHelper.DrawTextLine(sampleFramework.FrameStats);
            txtHelper.DrawTextLine(sampleFramework.DeviceStats);

            txtHelper.SetForegroundColor(System.Drawing.Color.White);

            txtHelper.End();
        }

        /// <summary>
        /// As a convenience, the sample framework inspects the incoming windows messages for
        /// keystroke messages and decodes the message parameters to pass relevant keyboard
        /// messages to the application.  The framework does not remove the underlying keystroke 
        /// messages, which are still passed to the application's MsgProc callback.
        /// </summary>
        private void OnKeyEvent(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case System.Windows.Forms.Keys.F1:
                    isHelpShowing = !isHelpShowing;
                    break;
            }
        }

        private void OnDoubleMouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            WorldLocation destinationLocation = new WorldLocation();

            Vector2 point = new Vector2(e.X, e.Y);

            Vector3 rayO; Vector3 rayD;
            MathUtil.RayFromScreenPos(sampleFramework.Device.Viewport, DXGfxManager.GetGlobalInstance().CurrentCamera.ProjectionMatrix, computedViewMat, point, out rayO, out rayD);
            List<SceneObject> theList = new List<SceneObject>();

            bool foundnothing = true;

            if (outdoorScene.Intersect(rayO, rayD, ref theList))
            {
                foreach (SceneObject obj in theList)
                {
                    WorldEntity entity = (WorldEntity)worldEntities[obj];
                    if (entity != null)
                    {
                        foundnothing = false;
                        missionUi.GetButton(MissionText).SetText(entity.selectString);

                        if (entity.selectSound != null)
                        {
                            entity.selectSound.Play(0, BufferPlayFlags.Default);
                        }
                    }
                    else
                    {
                        destinationLocation.SceneObject.Position = outdoorScene.PickEnvironmentPosition(sampleFramework.Device.Viewport, DXGfxManager.GetGlobalInstance().CurrentCamera.ProjectionMatrix, computedViewMat, point);

                        Moving moveAction = new Moving(boat);
                        moveAction.destination = destinationLocation;
                        boat.CurrentAction = moveAction;
                    }
                }
            }

            if (foundnothing)
            {
                destinationLocation.SceneObject.Position = outdoorScene.PickEnvironmentPosition(sampleFramework.Device.Viewport, DXGfxManager.GetGlobalInstance().CurrentCamera.ProjectionMatrix, computedViewMat, point);

                if (destinationLocation.SceneObject.Position.Y > 0)
                {
                    // Check if boat is near if yes add a tiger on ground
                    float dist = Vector3.Length(destinationLocation.SceneObject.Position - boat.SceneObject.Position);

                    if (dist < 50.0f)
                    {
                        FrameworkMesh boatMesh = new FrameworkMesh(DXGfxManager.GetGlobalInstance().d3dDevice, "tiger.x");
                        SceneObject sceneObject = outdoorScene.Attach(boatMesh);
                        sceneObject.Position = destinationLocation.SceneObject.Position;

                        Boat newboat = new Boat();
                        newboat.SceneObject = sceneObject;
                        worldEntities.Add(sceneObject, newboat);
                        newboat.speed = 20.0f;
                    }
                }

                Moving moveAction = new Moving(boat);
                moveAction.destination = destinationLocation;
                boat.CurrentAction = moveAction;
            }
        }

        /// <summary>
        /// Before handling window messages, the sample framework passes incoming windows 
        /// messages to the application through this callback function. If the application sets 
        /// noFurtherProcessing to true, the sample framework will not process the message
        /// </summary>
        public IntPtr OnMsgProc(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam, ref bool noFurtherProcessing)
        {
            // Give the dialog a chance to handle the message first
            noFurtherProcessing = hud.MessageProc(hWnd, msg, wParam, lParam);
            if (noFurtherProcessing)
                return IntPtr.Zero;

            noFurtherProcessing = missionUi.MessageProc(hWnd, msg, wParam, lParam);
            if (noFurtherProcessing)
                return IntPtr.Zero;

            // Pass all remaining windows messages to camera so it can respond to user input
            //DXGfxManager.CurrentCamera.HandleMessages(hWnd, msg, wParam, lParam);
            if (DXGfxManager.GetGlobalInstance().CurrentInputHandler != null)
            {
                DXGfxManager.GetGlobalInstance().CurrentInputHandler.OnMsgProc(hWnd, msg, wParam, lParam);
            }
            return IntPtr.Zero;
        }

        /// <summary>
        /// Initializes the application
        /// </summary>
        public void InitializeApplication()
        {
            int y = 10;

            // Initialize the HUD
            Button fullScreen = hud.AddButton(ToggleFullscreen, "Toggle full screen", 35, y, 125, 22);
            Button toggleRef = hud.AddButton(ToggleReference, "Toggle reference (F3)", 35, y += 24, 125, 22);
            Button changeDevice = hud.AddButton(ChangeDevice, "Change Device (F2)", 35, y += 24, 125, 22);
            // Hook the button events for when these items are clicked
            fullScreen.Click += new EventHandler(OnFullscreenClicked);
            toggleRef.Click += new EventHandler(OnRefClicked);
            changeDevice.Click += new EventHandler(OnChangeDevicClicked);

            // Our own UI
            Button missionText = missionUi.AddButton(MissionText, "Salut!!", 0, 0, 170, 120);
            missionText.Click += new EventHandler(missionText_Click);
        }

        void missionText_Click(object sender, EventArgs e)
        {
            missionUi.GetButton(MissionText).SetText("Button Clicked!!");
        }

        /// <summary>Called when the change device button is clicked</summary>
        private void OnChangeDevicClicked(object sender, EventArgs e)
        {
            sampleFramework.ShowSettingsDialog(!sampleFramework.IsD3DSettingsDialogShowing);
        }

        /// <summary>Called when the full screen button is clicked</summary>
        private void OnFullscreenClicked(object sender, EventArgs e)
        {
            sampleFramework.ToggleFullscreen();
        }

        /// <summary>Called when the ref button is clicked</summary>
        private void OnRefClicked(object sender, EventArgs e)
        {
            sampleFramework.ToggleReference();
        }

        /// <summary>
        /// Entry point to the program. Initializes everything and goes into a message processing 
        /// loop. Idle time is used to render the scene.
        /// </summary>
        static int Main()
        {
            System.Windows.Forms.Application.EnableVisualStyles();
            using (Framework sampleFramework = new Framework())
            {
                Sample sample = new Sample(sampleFramework);
                // Set the callback functions. These functions allow the sample framework to notify
                // the application about device changes, user input, and windows messages.  The 
                // callbacks are optional so you need only set callbacks for events you're interested 
                // in. However, if you don't handle the device reset/lost callbacks then the sample 
                // framework won't be able to reset your device since the application must first 
                // release all device resources before resetting.  Likewise, if you don't handle the 
                // device created/destroyed callbacks then the sample framework won't be able to 
                // recreate your device resources.
                sampleFramework.Disposing += new EventHandler(sample.OnDestroyDevice);
                sampleFramework.DeviceLost += new EventHandler(sample.OnLostDevice);
                sampleFramework.DeviceCreated += new DeviceEventHandler(sample.OnCreateDevice);
                sampleFramework.DeviceReset += new DeviceEventHandler(sample.OnResetDevice);

                sampleFramework.SetWndProcCallback(new WndProcCallback(sample.OnMsgProc));

                sampleFramework.SetCallbackInterface(sample);
                //try
                //{

                    // Show the cursor and clip it when in full screen
                    sampleFramework.SetCursorSettings(true, true);




                    // Initialize
                    
                    sample.InitializeApplication();

                    // Initialize the sample framework and create the desired window and Direct3D 
                    // device for the application. Calling each of these functions is optional, but they
                    // allow you to set several options which control the behavior of the sampleFramework.
                    sampleFramework.Initialize(true, true, true); // Parse the command line, handle the default hotkeys, and show msgboxes
                    sampleFramework.CreateWindow("Sample: Using DXGfxLib");
                    // Change windows size
                    //sampleFramework.Window.Width = 1024;
                    //sampleFramework.Window.Height = 768;

                    // Now we should be able to call InitSound (it needs at least that the window be created!)
                    // But we need to do this before the create device because we load the sound when the tiger in created!
                    sample.InitSound();

                    // Hook the keyboard event
                    sampleFramework.Window.KeyDown += new System.Windows.Forms.KeyEventHandler(sample.OnKeyEvent);
                    sampleFramework.Window.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(sample.OnDoubleMouseClick);
                    sampleFramework.CreateDevice(0, true, Framework.DefaultSizeWidth, Framework.DefaultSizeHeight,
                        sample);



                    // Pass control to the sample framework for handling the message pump and 
                    // dispatching render calls. The sample framework will call your FrameMove 
                    // and FrameRender callback when there is idle time between handling window messages.
                    sampleFramework.MainLoop();

//                }
//#if(DEBUG)
//                catch (Exception e)
//                {
//                    // In debug mode show this error (maybe - depending on settings)
//                    sampleFramework.DisplayErrorMessage(e);
//#else
//            catch
//            {
//                // In release mode fail silently
//#endif
//                    // Ignore any exceptions here, they would have been handled by other areas
//                    return (sampleFramework.ExitCode == 0) ? 1 : sampleFramework.ExitCode; // Return an error code here
//                }

                // Perform any application-level cleanup here. Direct3D device resources are released within the
                // appropriate callback functions and therefore don't require any cleanup code here.
                return sampleFramework.ExitCode;
            }
        }
    }
}
