/// <summary>
        /// Build nav mesh button
        /// </summary>
        private void BuildNavMesh_Click(object sender, EventArgs e)
        {
            CSharpFramework.Scene.ZoneCollection zones = EditorManager.Scene.Zones.ShallowClone();
              GroupAction groupLoadAction = new GroupAction("Load all zones");

              foreach (CSharpFramework.Scene.Zone zone in zones)
            groupLoadAction.Add(new CSharpFramework.Actions.SetZoneLoadedStatusAction(zone, true));
              groupLoadAction.Do();

              {
            // for printing out stats
            BuildStatisticsRichTextBox.ScrollBars = RichTextBoxScrollBars.ForcedVertical;
            Font oldFont = BuildStatisticsRichTextBox.SelectionFont;
            Font newFontPlain = new Font(oldFont, oldFont.Style & ~FontStyle.Bold);
            Font newFontBold = new Font(oldFont, oldFont.Style | FontStyle.Bold);

            ShapeCollection navMeshShapes = EditorManager.Scene.AllShapesOfType(typeof(HavokNavMeshShape));

            // gather all geometry once (divide by zone later)
            ShapeCollection staticGeometries = new ShapeCollection();
            {
              int numEntities = 0, numStaticMeshes = 0, numTerrains = 0;
              int numCarvers = 0, numSeedPoints = 0, numLocalSettings = 0;
              gatherGeometricShapes(ref staticGeometries, ref numEntities, ref numStaticMeshes, ref numTerrains, ref numCarvers, ref numSeedPoints, ref numLocalSettings);

              //
              // print out some debug info
              //
              BuildStatisticsRichTextBox.SelectionStart = BuildStatisticsRichTextBox.Text.Length;
              {
            String inputGeometryLabel = "Input Geometry";
            BuildStatisticsRichTextBox.Text = inputGeometryLabel;
              }
              BuildStatisticsRichTextBox.SelectionLength = BuildStatisticsRichTextBox.Text.Length - BuildStatisticsRichTextBox.SelectionStart;
              BuildStatisticsRichTextBox.SelectionFont = newFontBold;

              {
            String inputGlobalGeometryInfo = "\n\nStatic meshes\t: " + numStaticMeshes + "\nTerrains\t\t: " + numTerrains + "\nEntities\t\t: " + numEntities +
                "\n\nCarvers\t\t: " + numCarvers + "\nSeed points\t: " + numSeedPoints + "\nLocal settings\t: " + numLocalSettings + "\n\n";
            BuildStatisticsRichTextBox.Text += inputGlobalGeometryInfo;
              }
              BuildStatisticsRichTextBox.SelectionLength = BuildStatisticsRichTextBox.Text.Length - BuildStatisticsRichTextBox.SelectionStart;
              BuildStatisticsRichTextBox.SelectionFont = newFontPlain;

              //
              // debug info end
              //
            }

            // actually build the navmeshes here
            int numBuiltNavMeshShapes = 0;
            bool allCompleted = true;
            foreach (HavokNavMeshShape shape in navMeshShapes)
            {
              int numGeometryVertices = 0, numGeometryTriangles = 0;

              // note that the build function only uses static geometries that lie in the same zone!
              bool built = shape.Build(staticGeometries, ref numGeometryVertices, ref numGeometryTriangles);

              if (built)
              {
            numBuiltNavMeshShapes++;

            //
            // print out some debug info
            //
            BuildStatisticsRichTextBox.SelectionStart = BuildStatisticsRichTextBox.Text.Length;
            {
              String navMeshLabel = "\n\nNav Mesh #" + numBuiltNavMeshShapes;
              BuildStatisticsRichTextBox.Text += navMeshLabel;
            }
            BuildStatisticsRichTextBox.SelectionLength = BuildStatisticsRichTextBox.Text.Length - BuildStatisticsRichTextBox.SelectionStart;
            BuildStatisticsRichTextBox.SelectionFont = newFontBold;

            BuildStatisticsRichTextBox.SelectionStart = BuildStatisticsRichTextBox.Text.Length;
            {
              String inputPerNavMeshGeometryInfo = "\nTotal input triangles\t: " + numGeometryTriangles + "\nTotal input vertices\t: " + numGeometryVertices + "\n\n";
              int facesSize = shape.GetNavMeshFaceSize() * shape.GetNumNavMeshFaces();
              int edgesSize = shape.GetNavMeshEdgeSize() * shape.GetNumNavMeshEdges();
              int verticesSize = shape.GetNavMeshVertexSize() * shape.GetNumNavMeshVertices();
              int totalSize = shape.GetNavMeshStructSize() + facesSize + edgesSize + verticesSize;

              String navMeshInfo = "\nTotal size\t\t: " + totalSize +
                  " bytes\nFaces ( " + shape.GetNumNavMeshFaces() + " )\t: " + facesSize +
                  "\nEdges ( " + shape.GetNumNavMeshEdges() + " )\t: " + edgesSize +
                  "\nVertices ( " + shape.GetNumNavMeshVertices() + " )\t: " + verticesSize;
              BuildStatisticsRichTextBox.Text += navMeshInfo;
            }
            BuildStatisticsRichTextBox.SelectionLength = BuildStatisticsRichTextBox.Text.Length - BuildStatisticsRichTextBox.SelectionStart;
            BuildStatisticsRichTextBox.SelectionFont = newFontPlain;

            //
            // debug info end
            //
              }
              else
              {
              allCompleted = false;
              break;
              }
            }

            if (allCompleted)
            {
            // stitch the navmeshes together
            using (HavokAiManaged.EngineInstanceHavokNavMeshLinker linker = new HavokAiManaged.EngineInstanceHavokNavMeshLinker())
            {
                // collect all navmeshes at once
                foreach (HavokNavMeshShape shape in navMeshShapes)
                {
                    if (shape.HasEngineInstance())
                    {
                        linker.AddNavMeshShape(shape._engineInstance.GetNativeObject());

                        HavokNavMeshGlobalSettings globalSettings = GetGlobalSettings(shape.NavMeshGlobalSettingsKey);
                        if (globalSettings != null)
                        {
                          linker.m_linkEdgeMatchTolerance = globalSettings.LinkEdgeMatchTolerance;
                          linker.m_linkMaxStepHeight = globalSettings.LinkMaxStepHeight;
                          linker.m_linkMaxSeparation = globalSettings.LinkMaxSeparation;
                          linker.m_linkMaxOverhang = globalSettings.LinkMaxOverhang;

                          linker.m_linkCosPlanarAlignmentAngle = (float)Math.Cos(globalSettings.LinkPlanarAlignmentAngle / 180.0f * 3.14159f);
                          linker.m_linkCosVerticalAlignmentAngle = (float)Math.Cos(globalSettings.LinkVerticalAlignmentAngle / 180.0f * 3.14159f);
                          linker.m_linkMinEdgeOverlap = globalSettings.LinkMinEdgeOverlap;
                        }
                    }
                }

                // link them together
                linker.LinkNavMeshes();
            }

            // save it to disk (separate from next loop because we want to guarantee that we don't serialize out some runtime only data)
            foreach (HavokNavMeshShape shape in navMeshShapes)
            {
                shape.SaveNavMeshesToFile();
            }

            // finally load it into the havok ai world
            foreach (HavokNavMeshShape shape in navMeshShapes)
            {
                shape.AddNavMeshToWorld();
            }

            if (EditorManager.InPlayingMode && WantPhysicsConnection())
            {
                HavokAiManaged.ManagedModule.SetConnectToPhysicsWorld(true, false);
            }
            }

            EnableBuildButtonAsterisk(false);
            //EnableStreamingDependentControls(shape.GetNumNavMeshes()>1);
              }

              groupLoadAction.Undo();

              EditorManager.ActiveView.UpdateView(true);
        }
        /// <summary>
        /// Build nav mesh button
        /// </summary>
        private void BuildNavMesh_Click(object sender, EventArgs e)
        {
            CSharpFramework.Scene.ZoneCollection zones = EditorManager.Scene.Zones.ShallowClone();
            GroupAction groupLoadAction = new GroupAction("Load all zones");


            foreach (CSharpFramework.Scene.Zone zone in zones)
            {
                groupLoadAction.Add(new CSharpFramework.Actions.SetZoneLoadedStatusAction(zone, true));
            }
            groupLoadAction.Do();

            {
                // for printing out stats
                BuildStatisticsRichTextBox.ScrollBars = RichTextBoxScrollBars.ForcedVertical;
                Font oldFont      = BuildStatisticsRichTextBox.SelectionFont;
                Font newFontPlain = new Font(oldFont, oldFont.Style & ~FontStyle.Bold);
                Font newFontBold  = new Font(oldFont, oldFont.Style | FontStyle.Bold);

                ShapeCollection navMeshShapes = EditorManager.Scene.AllShapesOfType(typeof(HavokNavMeshShape));

                // gather all geometry once (divide by zone later)
                ShapeCollection staticGeometries = new ShapeCollection();
                {
                    int numEntities = 0, numStaticMeshes = 0, numTerrains = 0;
                    int numCarvers = 0, numSeedPoints = 0, numLocalSettings = 0;
                    gatherGeometricShapes(ref staticGeometries, ref numEntities, ref numStaticMeshes, ref numTerrains, ref numCarvers, ref numSeedPoints, ref numLocalSettings);

                    //
                    // print out some debug info
                    //
                    BuildStatisticsRichTextBox.SelectionStart = BuildStatisticsRichTextBox.Text.Length;
                    {
                        String inputGeometryLabel = "Input Geometry";
                        BuildStatisticsRichTextBox.Text = inputGeometryLabel;
                    }
                    BuildStatisticsRichTextBox.SelectionLength = BuildStatisticsRichTextBox.Text.Length - BuildStatisticsRichTextBox.SelectionStart;
                    BuildStatisticsRichTextBox.SelectionFont   = newFontBold;

                    {
                        String inputGlobalGeometryInfo = "\n\nStatic meshes\t: " + numStaticMeshes + "\nTerrains\t\t: " + numTerrains + "\nEntities\t\t: " + numEntities +
                                                         "\n\nCarvers\t\t: " + numCarvers + "\nSeed points\t: " + numSeedPoints + "\nLocal settings\t: " + numLocalSettings + "\n\n";
                        BuildStatisticsRichTextBox.Text += inputGlobalGeometryInfo;
                    }
                    BuildStatisticsRichTextBox.SelectionLength = BuildStatisticsRichTextBox.Text.Length - BuildStatisticsRichTextBox.SelectionStart;
                    BuildStatisticsRichTextBox.SelectionFont   = newFontPlain;

                    //
                    // debug info end
                    //
                }

                // actually build the navmeshes here
                int  numBuiltNavMeshShapes = 0;
                bool allCompleted          = true;
                foreach (HavokNavMeshShape shape in navMeshShapes)
                {
                    int numGeometryVertices = 0, numGeometryTriangles = 0;

                    // note that the build function only uses static geometries that lie in the same zone!
                    bool built = shape.Build(staticGeometries, ref numGeometryVertices, ref numGeometryTriangles);

                    if (built)
                    {
                        numBuiltNavMeshShapes++;

                        //
                        // print out some debug info
                        //
                        BuildStatisticsRichTextBox.SelectionStart = BuildStatisticsRichTextBox.Text.Length;
                        {
                            String navMeshLabel = "\n\nNav Mesh #" + numBuiltNavMeshShapes;
                            BuildStatisticsRichTextBox.Text += navMeshLabel;
                        }
                        BuildStatisticsRichTextBox.SelectionLength = BuildStatisticsRichTextBox.Text.Length - BuildStatisticsRichTextBox.SelectionStart;
                        BuildStatisticsRichTextBox.SelectionFont   = newFontBold;

                        BuildStatisticsRichTextBox.SelectionStart = BuildStatisticsRichTextBox.Text.Length;
                        {
                            String inputPerNavMeshGeometryInfo = "\nTotal input triangles\t: " + numGeometryTriangles + "\nTotal input vertices\t: " + numGeometryVertices + "\n\n";
                            int    facesSize    = shape.GetNavMeshFaceSize() * shape.GetNumNavMeshFaces();
                            int    edgesSize    = shape.GetNavMeshEdgeSize() * shape.GetNumNavMeshEdges();
                            int    verticesSize = shape.GetNavMeshVertexSize() * shape.GetNumNavMeshVertices();
                            int    totalSize    = shape.GetNavMeshStructSize() + facesSize + edgesSize + verticesSize;

                            String navMeshInfo = "\nTotal size\t\t: " + totalSize +
                                                 " bytes\nFaces ( " + shape.GetNumNavMeshFaces() + " )\t: " + facesSize +
                                                 "\nEdges ( " + shape.GetNumNavMeshEdges() + " )\t: " + edgesSize +
                                                 "\nVertices ( " + shape.GetNumNavMeshVertices() + " )\t: " + verticesSize;
                            BuildStatisticsRichTextBox.Text += navMeshInfo;
                        }
                        BuildStatisticsRichTextBox.SelectionLength = BuildStatisticsRichTextBox.Text.Length - BuildStatisticsRichTextBox.SelectionStart;
                        BuildStatisticsRichTextBox.SelectionFont   = newFontPlain;

                        //
                        // debug info end
                        //
                    }
                    else
                    {
                        allCompleted = false;
                        break;
                    }
                }

                if (allCompleted)
                {
                    // stitch the navmeshes together
                    using (HavokAiManaged.EngineInstanceHavokNavMeshLinker linker = new HavokAiManaged.EngineInstanceHavokNavMeshLinker())
                    {
                        // collect all navmeshes at once
                        foreach (HavokNavMeshShape shape in navMeshShapes)
                        {
                            if (shape.HasEngineInstance())
                            {
                                linker.AddNavMeshShape(shape._engineInstance.GetNativeObject());

                                HavokNavMeshGlobalSettings globalSettings = GetGlobalSettings(shape.NavMeshGlobalSettingsKey);
                                if (globalSettings != null)
                                {
                                    linker.m_linkEdgeMatchTolerance = globalSettings.LinkEdgeMatchTolerance;
                                    linker.m_linkMaxStepHeight      = globalSettings.LinkMaxStepHeight;
                                    linker.m_linkMaxSeparation      = globalSettings.LinkMaxSeparation;
                                    linker.m_linkMaxOverhang        = globalSettings.LinkMaxOverhang;

                                    linker.m_linkCosPlanarAlignmentAngle   = (float)Math.Cos(globalSettings.LinkPlanarAlignmentAngle / 180.0f * 3.14159f);
                                    linker.m_linkCosVerticalAlignmentAngle = (float)Math.Cos(globalSettings.LinkVerticalAlignmentAngle / 180.0f * 3.14159f);
                                    linker.m_linkMinEdgeOverlap            = globalSettings.LinkMinEdgeOverlap;
                                }
                            }
                        }

                        // link them together
                        linker.LinkNavMeshes();
                    }

                    // save it to disk (separate from next loop because we want to guarantee that we don't serialize out some runtime only data)
                    foreach (HavokNavMeshShape shape in navMeshShapes)
                    {
                        shape.SaveNavMeshesToFile();
                    }

                    // finally load it into the havok ai world
                    foreach (HavokNavMeshShape shape in navMeshShapes)
                    {
                        shape.AddNavMeshToWorld();
                    }

                    if (EditorManager.InPlayingMode && WantPhysicsConnection())
                    {
                        HavokAiManaged.ManagedModule.SetConnectToPhysicsWorld(true);
                    }
                }

                EnableBuildButtonAsterisk(false);
                //EnableStreamingDependentControls(shape.GetNumNavMeshes()>1);
            }

            groupLoadAction.Undo();

            EditorManager.ActiveView.UpdateView(true);
        }