private void EnableGizmoSpace(MyGizmoSpaceEnum gizmoSpaceEnum, bool enable, Vector3I? planePos, bool isOdd, MyCubeBlockDefinition cubeBlockDefinition, MyCubeGrid cubeGrid)
        {
            var gizmoSpace = m_spaces[(int)gizmoSpaceEnum];
            gizmoSpace.Enabled = enable;

            if (enable)
            {
                if (planePos.HasValue)
                    gizmoSpace.SymmetryPlanePos = planePos.Value;
                gizmoSpace.SymmetryIsOdd = isOdd;
                gizmoSpace.m_buildAllowed = false;

                if (cubeBlockDefinition != null)
                {
                    Quaternion orientationQuat = gizmoSpace.LocalOrientation;
                    MyBlockOrientation blockOrientation = new MyBlockOrientation(ref orientationQuat);

                    Vector3I rotatedBlockSize;
                    MyCubeGridDefinitions.GetRotatedBlockSize(cubeBlockDefinition, ref gizmoSpace.m_localMatrixAdd, out rotatedBlockSize);

                    //integer local center of the cube
                    Vector3I center = cubeBlockDefinition.Center;

                    //integer rotated/world center of the cube
                    Vector3I rotatedCenter;
                    Vector3I.TransformNormal(ref center, ref gizmoSpace.m_localMatrixAdd, out rotatedCenter);

                    //offset to the cube to align exactly on intersected cube
                    Vector3I worldDir = new Vector3I(
                        Math.Sign(rotatedBlockSize.X) == Math.Sign(gizmoSpace.m_addDir.X) ? rotatedCenter.X : Math.Sign(gizmoSpace.m_addDir.X) * ((Math.Abs(rotatedBlockSize.X) - Math.Abs(rotatedCenter.X) - 1)),
                        Math.Sign(rotatedBlockSize.Y) == Math.Sign(gizmoSpace.m_addDir.Y) ? rotatedCenter.Y : Math.Sign(gizmoSpace.m_addDir.Y) * ((Math.Abs(rotatedBlockSize.Y) - Math.Abs(rotatedCenter.Y) - 1)),
                        Math.Sign(rotatedBlockSize.Z) == Math.Sign(gizmoSpace.m_addDir.Z) ? rotatedCenter.Z : Math.Sign(gizmoSpace.m_addDir.Z) * ((Math.Abs(rotatedBlockSize.Z) - Math.Abs(rotatedCenter.Z) - 1)));

                    gizmoSpace.m_positions.Clear();
                    gizmoSpace.m_positionsSmallOnLarge.Clear();

                    if (MyFakes.ENABLE_STATIC_SMALL_GRID_ON_LARGE && gizmoSpace.m_addPosSmallOnLarge != null) {
                        float smallToLarge = MyDefinitionManager.Static.GetCubeSize(cubeBlockDefinition.CubeSize) / cubeGrid.GridSize;

                        gizmoSpace.m_minSmallOnLarge = Vector3.MaxValue;
                        gizmoSpace.m_maxSmallOnLarge = Vector3.MinValue;
                        gizmoSpace.m_centerPosSmallOnLarge = gizmoSpace.m_addPosSmallOnLarge.Value + smallToLarge * worldDir;
                        gizmoSpace.m_buildAllowed = true;

                        Vector3I temp = new Vector3I();

                        for (temp.X = 0; temp.X < cubeBlockDefinition.Size.X; temp.X++)
                            for (temp.Y = 0; temp.Y < cubeBlockDefinition.Size.Y; temp.Y++)
                                for (temp.Z = 0; temp.Z < cubeBlockDefinition.Size.Z; temp.Z++) {
                                    Vector3I rotatedTemp;
                                    Vector3I centeredTemp = temp - center;
                                    Vector3I.TransformNormal(ref centeredTemp, ref gizmoSpace.m_localMatrixAdd, out rotatedTemp);

                                    Vector3 tempIntPos = gizmoSpace.m_addPosSmallOnLarge.Value + smallToLarge * (rotatedTemp + worldDir);
                                    gizmoSpace.m_minSmallOnLarge = Vector3.Min(tempIntPos, gizmoSpace.m_minSmallOnLarge);
                                    gizmoSpace.m_maxSmallOnLarge = Vector3.Max(tempIntPos, gizmoSpace.m_maxSmallOnLarge);

                                    // Commented out - small block can be placed in occupied large block areas 
                                    //if (!cubeGrid.CanAddCube(Vector3I.Round(tempIntPos), blockOrientation, null))
                                    //    gizmoSpace.m_buildAllowed = false;

                                    gizmoSpace.m_positionsSmallOnLarge.Add(tempIntPos);
                                }

                    }
                    else {
                        gizmoSpace.m_min = Vector3I.MaxValue;
                        gizmoSpace.m_max = Vector3I.MinValue;
                        gizmoSpace.m_centerPos = gizmoSpace.m_addPos + worldDir;
                        gizmoSpace.m_buildAllowed = true;

                        Vector3I temp = new Vector3I();

                        for (temp.X = 0; temp.X < cubeBlockDefinition.Size.X; temp.X++)
                            for (temp.Y = 0; temp.Y < cubeBlockDefinition.Size.Y; temp.Y++)
                                for (temp.Z = 0; temp.Z < cubeBlockDefinition.Size.Z; temp.Z++) {
                                    Vector3I rotatedTemp;
                                    Vector3I centeredTemp = temp - center;
                                    Vector3I.TransformNormal(ref centeredTemp, ref gizmoSpace.m_localMatrixAdd, out rotatedTemp);

                                    Vector3I tempIntPos = gizmoSpace.m_addPos + rotatedTemp + worldDir;
                                    gizmoSpace.m_min = Vector3I.Min(tempIntPos, gizmoSpace.m_min);
                                    gizmoSpace.m_max = Vector3I.Max(tempIntPos, gizmoSpace.m_max);

                                    if (cubeGrid != null && !cubeGrid.CanAddCube(tempIntPos, blockOrientation, cubeBlockDefinition))
                                        gizmoSpace.m_buildAllowed = false;

                                    gizmoSpace.m_positions.Add(tempIntPos);
                                }
                    }
                }

                if (gizmoSpace.SymmetryPlane != MySymmetrySettingModeEnum.Disabled)
                    MirrorGizmoSpace(gizmoSpace, m_spaces[(int)gizmoSpace.SourceSpace], gizmoSpace.SymmetryPlane, planePos.Value, isOdd, cubeBlockDefinition, cubeGrid);
            }
        }
        public bool PointInsideGizmo(Vector3D point, MyGizmoSpaceEnum gizmo, ref MatrixD invGridWorldMatrix, float gridSize, float inflate = 0.0f, bool onVoxel = false)
        {
            MatrixD m = new MatrixD();
            BoundingBoxD gizmoBox = new BoundingBoxD();
            GetGizmoPointTestVariables(ref invGridWorldMatrix, gridSize, out gizmoBox, out m, gizmo, inflate: inflate, onVoxel: onVoxel);

            Vector3D localPoint = Vector3D.Transform(point, m);

            return gizmoBox.Contains(localPoint) == ContainmentType.Contains;
        }
        private void GetGizmoPointTestVariables(ref MatrixD invGridWorldMatrix, float gridSize, out BoundingBoxD bb, out MatrixD m, MyGizmoSpaceEnum gizmo, float inflate = 0.0f, bool onVoxel = false)
        {
            m = invGridWorldMatrix * MatrixD.CreateScale(1.0f / gridSize);
            var gizmoSpace = m_spaces[(int)gizmo];

            if (onVoxel)
            {
                m = invGridWorldMatrix;
                Vector3D worldMin = MyCubeGrid.StaticGlobalGrid_UGToWorld(gizmoSpace.m_min, gridSize, MyPerGameSettings.BuildingSettings.StaticGridAlignToCenter) - Vector3D.Half * gridSize;
                Vector3D worldMax = MyCubeGrid.StaticGlobalGrid_UGToWorld(gizmoSpace.m_max, gridSize, MyPerGameSettings.BuildingSettings.StaticGridAlignToCenter) + Vector3D.Half * gridSize;
                bb = new BoundingBoxD(worldMin - new Vector3D(inflate * gridSize), worldMax + new Vector3D(inflate * gridSize));
            }
            else if (MyFakes.ENABLE_STATIC_SMALL_GRID_ON_LARGE && gizmoSpace.m_addPosSmallOnLarge != null) 
            {
                float smallToLarge = MyDefinitionManager.Static.GetCubeSize(gizmoSpace.m_blockDefinition.CubeSize) / gridSize;
                Debug.Assert(smallToLarge < 0.5f);
                Vector3 localMin = gizmoSpace.m_minSmallOnLarge - new Vector3(0.5f * smallToLarge);
                Vector3 localMax = gizmoSpace.m_maxSmallOnLarge + new Vector3(0.5f * smallToLarge);
                bb = new BoundingBoxD(localMin - new Vector3(inflate), localMax + new Vector3(inflate));
            }
            else 
            {
                Vector3 localMin = gizmoSpace.m_min - new Vector3(0.5f);
                Vector3 localMax = gizmoSpace.m_max + new Vector3(0.5f);
                bb = new BoundingBoxD(localMin - new Vector3(inflate), localMax + new Vector3(inflate));
            }
        }
        public bool PointsInsideGizmo(List<Vector3> points, MyGizmoSpaceEnum gizmo, ref MatrixD invGridWorldMatrix, float gridSize, float inflate = 0.0f, bool onVoxel = false)
        {
            MatrixD m = new MatrixD();
            BoundingBoxD gizmoBox = new BoundingBoxD();
            GetGizmoPointTestVariables(ref invGridWorldMatrix, gridSize, out gizmoBox, out m, gizmo, inflate: inflate, onVoxel: onVoxel);

            foreach (var point in points)
            {
                Vector3 localPoint = Vector3.Transform(point, m);

                if (gizmoBox.Contains(localPoint) == ContainmentType.Contains)
                    return true;
            }
            return false;
        }
        public bool PointsAABBIntersectsGizmo(List<Vector3D> points, MyGizmoSpaceEnum gizmo, ref MatrixD invGridWorldMatrix, float gridSize, float inflate = 0.0f, bool onVoxel = false, bool dynamicMode = false)
        {
            MatrixD m = new MatrixD();
            BoundingBoxD gizmoBox = new BoundingBoxD();
            GetGizmoPointTestVariables(ref invGridWorldMatrix, gridSize, out gizmoBox, out m, gizmo, inflate: inflate, onVoxel: onVoxel, dynamicMode: dynamicMode);

            BoundingBoxD pointsBox = BoundingBoxD.CreateInvalid();
            foreach (var point in points)
            {
                Vector3D localPoint = Vector3D.Transform(point, m);

                if (gizmoBox.Contains(localPoint) == ContainmentType.Contains)
                    return true;

                pointsBox.Include(localPoint);
            }

            return pointsBox.Intersects(ref gizmoBox);
        }