public void FromMouseCursorRayHit(MouseCursorRayHit cursorRayHit)
        {
            _isValid = false;

            if (!cursorRayHit.WasAnythingHit)
            {
                return;
            }
            else
            if (cursorRayHit.WasAnObjectHit && !ObjectSnapSettings.Get().IgnoreObjectsWhenSnapping)
            {
                GameObjectRayHit gameObjectRayHit = FindClosestHitObjectWhichCanBeUsedAsSnapSurface(cursorRayHit);
                if (gameObjectRayHit != null)
                {
                    if (!cursorRayHit.WasACellHit)
                    {
                        ExtractData(gameObjectRayHit);
                    }
                    else
                    {
                        if (gameObjectRayHit.HitEnter <= cursorRayHit.GridCellRayHit.HitEnter)
                        {
                            ExtractData(gameObjectRayHit);
                        }
                    }
                }
            }

            // If we didn't manage to build the surface up until now, we will give it one last chance
            // using the cursor grid cell ray hit.
            if (!_isValid && cursorRayHit.WasACellHit)
            {
                ExtractData(cursorRayHit.GridCellRayHit);
            }
        }
        public ObjectSnapSettingsView(ObjectSnapSettings settings)
        {
            _settings = settings;

            ToggleVisibilityBeforeRender = true;
            VisibilityToggleLabel        = "Object Snap Settings";
            SurroundWithBox = true;
        }
        public void FromXZOrientedQuad(XZOrientedQuad3D orientedQuad)
        {
            float desiredCellSize = ObjectSnapSettings.Get().ObjectColliderSnapSurfaceGridSettings.DesiredCellSize;

            // As a first step, ensure that the grid sits in the middle of the quad and has the same orientation
            Grid.SetOriginPosition(orientedQuad.GetOriginPosition());
            Grid.SetRotation(orientedQuad.GetRotation());

            Vector2 quadSize  = orientedQuad.ScaledXZSize;
            float   cellSizeX = desiredCellSize;
            float   cellSizeZ = desiredCellSize;

            int cellCountX, cellCountZ;

            if (cellSizeX > quadSize.x)
            {
                cellSizeX  = quadSize.x;
                cellCountX = 1;
            }
            else
            {
                // Adjust the cell size in such a way that we get an integer number of cells along each dimension
                float divisionResult = quadSize.x / cellSizeX;
                cellCountX = (int)divisionResult;
                float fractionalValue = divisionResult - cellCountX;
                if (fractionalValue != 0.0f)
                {
                    cellSizeX += (fractionalValue / cellCountX) * desiredCellSize;                              // If the fractional value is not 0, it means the cell size needs to be adjusted
                }
                // in such a way that the calculated number of cells ('cellCountX') covers the entire
                // quad area along the corresponding dimension.
            }

            if (cellSizeZ > quadSize.y)
            {
                cellSizeZ  = quadSize.y;
                cellCountZ = 1;
            }
            else
            {
                float divisionResult = quadSize.y / cellSizeZ;
                cellCountZ = (int)divisionResult;
                float fractionalValue = divisionResult - cellCountZ;
                if (fractionalValue != 0.0f)
                {
                    cellSizeZ += (fractionalValue / cellCountZ) * desiredCellSize;
                }
            }

            // Make sure the cell size is not larger than the quad
            if (cellSizeX > quadSize.x)
            {
                cellSizeX = quadSize.x;
            }
            if (cellSizeZ > quadSize.y)
            {
                cellSizeZ = quadSize.y;
            }

            Grid.CellSizeSettings.CellSizeX = cellSizeX;
            Grid.CellSizeSettings.CellSizeZ = cellSizeZ;

            // Store the cell count without taking into consideration the cell which sits at the origin of the grid
            int cellCountXNoMiddle = cellCountX - 1;
            int cellCountZNoMiddle = cellCountZ - 1;

            if (cellCountXNoMiddle % 2 == 0)
            {
                int halfCount = cellCountXNoMiddle / 2;
                Grid.DimensionSettings.FiniteDimensionSettings.XAxisCellIndexRange.Min = -halfCount;
                Grid.DimensionSettings.FiniteDimensionSettings.XAxisCellIndexRange.Max = halfCount;
            }
            else
            {
                int halfCount = cellCountXNoMiddle / 2;
                Grid.DimensionSettings.FiniteDimensionSettings.XAxisCellIndexRange.Min = -halfCount;
                Grid.DimensionSettings.FiniteDimensionSettings.XAxisCellIndexRange.Max = halfCount + 1;
            }

            if (cellCountZNoMiddle % 2 == 0)
            {
                int halfCount = cellCountZNoMiddle / 2;
                Grid.DimensionSettings.FiniteDimensionSettings.ZAxisCellIndexRange.Min = -halfCount;
                Grid.DimensionSettings.FiniteDimensionSettings.ZAxisCellIndexRange.Max = halfCount;
            }
            else
            {
                int halfCount = cellCountZNoMiddle / 2;
                Grid.DimensionSettings.FiniteDimensionSettings.ZAxisCellIndexRange.Min = -halfCount;
                Grid.DimensionSettings.FiniteDimensionSettings.ZAxisCellIndexRange.Max = halfCount + 1;
            }

            // We need to make sure that the grid nicely sits within the boundaries of the quad. In order to do this, we will
            // align the top left corners of the quad and the grid's top left cell.
            Vector3          quadTopLeftCornerPoint     = orientedQuad.GetCornerPoints()[(int)XZOrientedQuad3DCornerPoint.TopLeft];
            XZOrientedQuad3D topLeftCellQuad            = Grid.CalculateCellQuad(Grid.DimensionSettings.FiniteDimensionSettings.XAxisCellIndexRange.Min, Grid.DimensionSettings.FiniteDimensionSettings.ZAxisCellIndexRange.Max);
            Vector3          cellQuadTopLeftCornerPoint = topLeftCellQuad.GetCornerPoints()[(int)XZOrientedQuad3DCornerPoint.TopLeft];
            Vector3          gridOriginMoveVector       = quadTopLeftCornerPoint - cellQuadTopLeftCornerPoint;

            Grid.Translate(gridOriginMoveVector);
        }
        private static void SaveSnapSettings(XmlTextWriter xmlWriter, Octave3DConfigSaveLoadSettings saveSettings)
        {
            if (saveSettings.SnapSettings)
            {
                ObjectSnapSettings snapSettings = ObjectSnapSettings.Get();

                xmlWriter.WriteNewLine(1);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapSettingsNode);

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.UseOriginalPivotNode);
                xmlWriter.WriteString(snapSettings.UseOriginalPivot.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.IgnoreObjectsWhenSnappingNode);
                xmlWriter.WriteString(snapSettings.IgnoreObjectsWhenSnapping.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapToCursorHitPointNode);
                xmlWriter.WriteString(snapSettings.SnapToCursorHitPoint.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapCenterToCenterGridNode);
                xmlWriter.WriteString(snapSettings.SnapCenterToCenterForXZGrid.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapCenterToCenterObjectSurfaceNode);
                xmlWriter.WriteString(snapSettings.SnapCenterToCenterForObjectSurface.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.EnableObjectToObjectSnapNode);
                xmlWriter.WriteString(snapSettings.EnableObjectToObjectSnap.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.ObjectToObjectSnapModeNode);
                xmlWriter.WriteString(snapSettings.ObjectToObjectSnapMode.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.ObjectToObjectSnapEpsilonNode);
                xmlWriter.WriteString(snapSettings.ObjectToObjectSnapEpsilon.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapGridXOffsetNode);
                xmlWriter.WriteString(snapSettings.XZSnapGridXOffset.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapGridYOffsetNode);
                xmlWriter.WriteString(snapSettings.XZSnapGridYOffset.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapGridYOffsetStepNode);
                xmlWriter.WriteString(snapSettings.XZGridYOffsetStep.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapGridZOffsetNode);
                xmlWriter.WriteString(snapSettings.XZSnapGridZOffset.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.ObjectSurfaceGridDesiredCellSizeNode);
                xmlWriter.WriteString(snapSettings.ObjectColliderSnapSurfaceGridSettings.DesiredCellSize.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapGridCellSizeXNode);
                xmlWriter.WriteString(ObjectSnapping.Get().XZSnapGrid.CellSizeSettings.CellSizeX.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(2);
                xmlWriter.WriteStartElement(Octave3DConfigXMLInfo.SnapGridCellSizeZNode);
                xmlWriter.WriteString(ObjectSnapping.Get().XZSnapGrid.CellSizeSettings.CellSizeZ.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteNewLine(1);
                xmlWriter.WriteEndElement();
            }
        }