public void AddFastBuildParts(MyGizmoSpaceProperties gizmoSpace, MyCubeBlockDefinition cubeBlockDefinition, MyCubeGrid grid)
        {
            if (cubeBlockDefinition != null && gizmoSpace.m_startBuild != null && gizmoSpace.m_continueBuild != null)
            {
                var start = Vector3I.Min(gizmoSpace.m_startBuild.Value, gizmoSpace.m_continueBuild.Value);
                var end = Vector3I.Max(gizmoSpace.m_startBuild.Value, gizmoSpace.m_continueBuild.Value);

                Vector3I temp = new Vector3I();

                int baseCount = gizmoSpace.m_cubeMatricesTemp.Count;

                for (temp.X = start.X; temp.X <= end.X; temp.X += cubeBlockDefinition.Size.X)
                    for (temp.Y = start.Y; temp.Y <= end.Y; temp.Y += cubeBlockDefinition.Size.Y)
                        for (temp.Z = start.Z; temp.Z <= end.Z; temp.Z += cubeBlockDefinition.Size.Z)
                        {
                            var offset = temp - gizmoSpace.m_startBuild.Value;
                            if (offset == Vector3.Zero)
                                continue;

                            Vector3D tempWorldPos = grid != null ? (Vector3D.Transform(temp * grid.GridSize, grid.WorldMatrix)) : ((Vector3D)temp * MyDefinitionManager.Static.GetCubeSize(cubeBlockDefinition.CubeSize));

                            for (int i = 0; i < baseCount; i++)
                            {
                                gizmoSpace.m_cubeModelsTemp.Add(gizmoSpace.m_cubeModelsTemp[i]);
                                MatrixD m = gizmoSpace.m_cubeMatricesTemp[i];
                                m.Translation = tempWorldPos;
                                gizmoSpace.m_cubeMatricesTemp.Add(m);
                            }
                        }
            }
        }
        private void MirrorGizmoSpace(MyGizmoSpaceProperties targetSpace, MyGizmoSpaceProperties sourceSpace, MySymmetrySettingModeEnum mirrorPlane, Vector3I mirrorPosition, bool isOdd,
            MyCubeBlockDefinition cubeBlockDefinition, MyCubeGrid cubeGrid)
        {
            targetSpace.m_addPos = MirrorBlockByPlane(mirrorPlane, mirrorPosition, isOdd, sourceSpace.m_addPos);

            targetSpace.m_localMatrixAdd.Translation = targetSpace.m_addPos;

            targetSpace.m_addDir = MirrorDirByPlane(mirrorPlane, mirrorPosition, isOdd, sourceSpace.m_addDir);

            targetSpace.m_removePos = MirrorBlockByPlane(mirrorPlane, mirrorPosition, isOdd, sourceSpace.m_removePos);
            targetSpace.m_removeBlock = cubeGrid.GetCubeBlock(targetSpace.m_removePos);

            if (sourceSpace.m_startBuild.HasValue)
                targetSpace.m_startBuild = MirrorBlockByPlane(mirrorPlane, mirrorPosition, isOdd, sourceSpace.m_startBuild.Value);
            else
                targetSpace.m_startBuild = null;

            if (sourceSpace.m_continueBuild.HasValue)
                targetSpace.m_continueBuild = MirrorBlockByPlane(mirrorPlane, mirrorPosition, isOdd, sourceSpace.m_continueBuild.Value);
            else
                targetSpace.m_continueBuild = null;

            if (sourceSpace.m_startRemove.HasValue)
                targetSpace.m_startRemove = MirrorBlockByPlane(mirrorPlane, mirrorPosition, isOdd, sourceSpace.m_startRemove.Value);
            else
                targetSpace.m_startRemove = null;

            //Find block axis ortogonal to mirror plane normal
            Vector3 mirrorNormal = Vector3.Zero;
            switch (mirrorPlane)
            {
                case MySymmetrySettingModeEnum.XPlane:
                    mirrorNormal = Vector3.Right;
                    break;
                case MySymmetrySettingModeEnum.YPlane:
                    mirrorNormal = Vector3.Up;
                    break;
                case MySymmetrySettingModeEnum.ZPlane:
                    mirrorNormal = Vector3.Forward;
                    break;

                default:
                    System.Diagnostics.Debug.Assert(false);
                    break;
            }

            var blockMirrorAxis = Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.None;
            if (MyUtils.IsZero(Math.Abs(Vector3.Dot(sourceSpace.m_localMatrixAdd.Right, mirrorNormal)) - 1.0f))
            {
                blockMirrorAxis = Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.X;
            }
            else
                if (MyUtils.IsZero(Math.Abs(Vector3.Dot(sourceSpace.m_localMatrixAdd.Up, mirrorNormal)) - 1.0f))
                {
                    blockMirrorAxis = Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.Y;
                }
                else
                    if (MyUtils.IsZero(Math.Abs(Vector3.Dot(sourceSpace.m_localMatrixAdd.Forward, mirrorNormal)) - 1.0f))
                    {
                        blockMirrorAxis = Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.Z;
                    }

            var blockMirrorOption = Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.None;
            switch (blockMirrorAxis)
            {
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.X:
                    blockMirrorOption = cubeBlockDefinition.SymmetryX;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.Y:
                    blockMirrorOption = cubeBlockDefinition.SymmetryY;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.Z:
                    blockMirrorOption = cubeBlockDefinition.SymmetryZ;
                    break;

                default:
                    System.Diagnostics.Debug.Assert(false);
                    break;
            }

            switch (blockMirrorOption)
            {
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.X:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.Y:
                    //targetSpace.m_gizmoLocalMatrixAdd = sourceSpace.m_gizmoLocalMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.Z:
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.ZThenOffsetX:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.HalfX:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(-MathHelper.PiOver2) * sourceSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.HalfY:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(-MathHelper.PiOver2) * sourceSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.HalfZ:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(-MathHelper.PiOver2) * sourceSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.XHalfY:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.YHalfY:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.ZHalfY:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.XHalfX:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(-MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.YHalfX:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(-MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.ZHalfX:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(-MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.XHalfZ:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(-MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.YHalfZ:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(-MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.ZHalfZ:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(-MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.XMinusHalfZ:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.YMinusHalfZ:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.ZMinusHalfZ:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.XMinusHalfX:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.YMinusHalfX:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.ZMinusHalfX:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.Pi) * sourceSpace.m_localMatrixAdd;
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.PiOver2) * targetSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.MinusHalfX:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationX(MathHelper.PiOver2) * sourceSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.MinusHalfY:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationY(MathHelper.PiOver2) * sourceSpace.m_localMatrixAdd;
                    break;
                case Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.MinusHalfZ:
                    targetSpace.m_localMatrixAdd = Matrix.CreateRotationZ(MathHelper.PiOver2) * sourceSpace.m_localMatrixAdd;
                    break;

                default:
                    targetSpace.m_localMatrixAdd = sourceSpace.m_localMatrixAdd;
                    break;
            }

            if (!string.IsNullOrEmpty(sourceSpace.m_blockDefinition.MirroringBlock))
            {
                targetSpace.m_blockDefinition = MyDefinitionManager.Static.GetCubeBlockDefinition(new MyDefinitionId(typeof(MyObjectBuilder_CubeBlock), sourceSpace.m_blockDefinition.MirroringBlock));
            }
            else
                targetSpace.m_blockDefinition = sourceSpace.m_blockDefinition;

            // Correct mirroring of objects with center offset
            // if (blockMirrorOption == Common.ObjectBuilders.Definitions.MySymmetryAxisEnum.None)
            if (cubeBlockDefinition.SymmetryX == MySymmetryAxisEnum.None && cubeBlockDefinition.SymmetryY == MySymmetryAxisEnum.None && cubeBlockDefinition.SymmetryZ == MySymmetryAxisEnum.None)
            {
                Vector3 min = sourceSpace.m_min * cubeGrid.GridSize - new Vector3(cubeGrid.GridSize / 2);
                Vector3 max = sourceSpace.m_max * cubeGrid.GridSize + new Vector3(cubeGrid.GridSize / 2);

                BoundingBox box = new BoundingBox(min, max);

                //Mirroring algorithm
                // 1. Find vector from closest source box side to mirror (vector A)
                // 2. Find vector from source box pos to opposite side (vector B)
                // 3. Correct mirrored position is source box pos + A - B

                if (box.Size.X > 1 * cubeGrid.GridSize || box.Size.Y > 1 * cubeGrid.GridSize || box.Size.Z > 1 * cubeGrid.GridSize)
                {
                    //align to mirror
                    BoundingBox worldAABB = box.Transform((Matrix)cubeGrid.WorldMatrix);
                    //VRageRender.MyRenderProxy.DebugDrawAABB(worldAABB, Vector3.One, 1, 1, false);

                    Vector3 sourceCenterFloatLocal = sourceSpace.m_localMatrixAdd.Translation * cubeGrid.GridSize;
                    Vector3 sourceCenterWorld = Vector3.Transform(sourceCenterFloatLocal, cubeGrid.WorldMatrix);
                    //VRageRender.MyRenderProxy.DebugDrawSphere(sourceCenterWorld, 0.5f, Vector3.One, 1, false, false);

                    Vector3I localToMirror = mirrorPosition - new Vector3I(sourceSpace.m_localMatrixAdd.Translation);
                    Vector3 floatLocalToMirror = localToMirror * cubeGrid.GridSize;
                    if (isOdd)
                    {
                        floatLocalToMirror.X -= cubeGrid.GridSize / 2;
                        floatLocalToMirror.Y -= cubeGrid.GridSize / 2;
                        floatLocalToMirror.Z += cubeGrid.GridSize / 2;
                    }


                    Vector3 fullFloatLocalToMirror = floatLocalToMirror;
                    Vector3 alignedFloatLocalToMirror = Vector3.Clamp(sourceCenterFloatLocal + floatLocalToMirror, box.Min, box.Max) - sourceCenterFloatLocal;
                    Vector3 alignedFloatLocalToBoxEnd = Vector3.Clamp(sourceCenterFloatLocal + floatLocalToMirror * 100, box.Min, box.Max) - sourceCenterFloatLocal;
                    Vector3 oppositeFromMirror = Vector3.Clamp(sourceCenterFloatLocal - floatLocalToMirror * 100, box.Min, box.Max) - sourceCenterFloatLocal;


                    if (mirrorPlane == MySymmetrySettingModeEnum.XPlane || mirrorPlane == MySymmetrySettingModeEnum.XPlaneOdd)
                    {
                        oppositeFromMirror.Y = 0;
                        oppositeFromMirror.Z = 0;
                        alignedFloatLocalToMirror.Y = 0;
                        alignedFloatLocalToMirror.Z = 0;
                        fullFloatLocalToMirror.Y = 0;
                        fullFloatLocalToMirror.Z = 0;
                        alignedFloatLocalToBoxEnd.Y = 0;
                        alignedFloatLocalToBoxEnd.Z = 0;
                    }
                    else
                        if (mirrorPlane == MySymmetrySettingModeEnum.YPlane || mirrorPlane == MySymmetrySettingModeEnum.YPlaneOdd)
                        {
                            oppositeFromMirror.X = 0;
                            oppositeFromMirror.Z = 0;
                            alignedFloatLocalToMirror.X = 0;
                            alignedFloatLocalToMirror.Z = 0;
                            fullFloatLocalToMirror.X = 0;
                            fullFloatLocalToMirror.Z = 0;
                            alignedFloatLocalToBoxEnd.X = 0;
                            alignedFloatLocalToBoxEnd.Z = 0;
                        }
                        else
                            if (mirrorPlane == MySymmetrySettingModeEnum.ZPlane || mirrorPlane == MySymmetrySettingModeEnum.ZPlaneOdd)
                            {
                                oppositeFromMirror.Y = 0;
                                oppositeFromMirror.X = 0;
                                alignedFloatLocalToMirror.Y = 0;
                                alignedFloatLocalToMirror.X = 0;
                                fullFloatLocalToMirror.Y = 0;
                                fullFloatLocalToMirror.X = 0;
                                alignedFloatLocalToBoxEnd.Y = 0;
                                alignedFloatLocalToBoxEnd.X = 0;
                            }

                    Vector3 sideLocalToMirror = fullFloatLocalToMirror - alignedFloatLocalToMirror;


                    Vector3 alignedWorldToMirror = Vector3.TransformNormal(alignedFloatLocalToMirror, cubeGrid.WorldMatrix);
                    Vector3 fullWorldToMirror = Vector3.TransformNormal(fullFloatLocalToMirror, cubeGrid.WorldMatrix);
                    Vector3 oppositeWorldToMirror = Vector3.TransformNormal(oppositeFromMirror, cubeGrid.WorldMatrix);
                    //VRageRender.MyRenderProxy.DebugDrawLine3D(sourceCenterWorld, sourceCenterWorld + alignedWorldToMirror, Color.Red, Color.Red, false);
                    //VRageRender.MyRenderProxy.DebugDrawLine3D(sourceCenterWorld + alignedWorldToMirror, sourceCenterWorld + fullWorldToMirror, Color.Yellow, Color.Yellow, false);
                    //VRageRender.MyRenderProxy.DebugDrawLine3D(sourceCenterWorld, sourceCenterWorld + oppositeWorldToMirror, Color.Blue, Color.Blue, false);

                    bool isInsideMirror = false;
                    if (fullFloatLocalToMirror.LengthSquared() < alignedFloatLocalToBoxEnd.LengthSquared())
                    {
                        isInsideMirror = true;
                    }


                    Vector3 newOffsetFromMirror = sideLocalToMirror;
                    Vector3 newOffsetFromBox = -oppositeFromMirror;
                    Vector3 newOffsetFromMirrorWorld = Vector3.TransformNormal(newOffsetFromMirror, cubeGrid.WorldMatrix);
                    Vector3 newOffsetFromBoxWorld = Vector3.TransformNormal(newOffsetFromBox, cubeGrid.WorldMatrix);
                    Vector3 mirrorPositionWorld = sourceCenterWorld + fullWorldToMirror;
                    //VRageRender.MyRenderProxy.DebugDrawLine3D(mirrorPositionWorld, mirrorPositionWorld + newOffsetFromMirrorWorld, Color.Yellow, Color.Yellow, false);
                    //VRageRender.MyRenderProxy.DebugDrawLine3D(mirrorPositionWorld + newOffsetFromMirrorWorld, mirrorPositionWorld + newOffsetFromMirrorWorld + newOffsetFromBoxWorld, Color.Blue, Color.Blue, false);

                    Vector3 newLocalFromMirror = newOffsetFromMirror + newOffsetFromBox;
                    Vector3 newWorldFromMirror = Vector3.TransformNormal(newLocalFromMirror, cubeGrid.WorldMatrix);
                    //VRageRender.MyRenderProxy.DebugDrawLine3D(mirrorPositionWorld, mirrorPositionWorld + newWorldFromMirror, Color.Green, Color.Green, false);


                    Vector3 fromMirrorFloat = sourceSpace.m_localMatrixAdd.Translation + (fullFloatLocalToMirror + newLocalFromMirror) / cubeGrid.GridSize;


                    if (!isInsideMirror)
                    {
                        Vector3 worldFromMirror = Vector3.TransformNormal(fromMirrorFloat, cubeGrid.WorldMatrix);

                        //VRageRender.MyRenderProxy.DebugDrawLine3D(sourceCenterWorld, sourceCenterWorld + worldFromMirror, Color.White, Color.Black, false);

                        Vector3 newPos = fromMirrorFloat;// / CurrentGrid.GridSize;
                        //VRageRender.MyRenderProxy.DebugDrawSphere(Vector3.Transform(targetSpace.m_gizmoAddPos * CurrentGrid.GridSize, CurrentGrid.WorldMatrix), 0.2f, Vector3.One, 1, false);
                        targetSpace.m_mirroringOffset = new Vector3I(newPos) - targetSpace.m_addPos;
                        targetSpace.m_addPos += targetSpace.m_mirroringOffset;
                        targetSpace.m_removePos += targetSpace.m_mirroringOffset;
                        targetSpace.m_removeBlock = cubeGrid.GetCubeBlock(targetSpace.m_removePos);
                        targetSpace.m_addDir = sourceSpace.m_addDir;


                        targetSpace.m_localMatrixAdd.Translation = targetSpace.m_addPos;
                        if (targetSpace.m_startBuild != null)
                            targetSpace.m_startBuild = targetSpace.m_startBuild + targetSpace.m_mirroringOffset;
                    }
                    else
                    {
                        targetSpace.m_mirroringOffset = Vector3I.Zero;
                        targetSpace.m_addPos = sourceSpace.m_addPos;
                        targetSpace.m_removePos = sourceSpace.m_removePos;
                        targetSpace.m_removeBlock = cubeGrid.GetCubeBlock(sourceSpace.m_removePos);
                    }
                }
            }

            if (blockMirrorOption == MySymmetryAxisEnum.ZThenOffsetX)
            {
                Vector3I offset = new Vector3I(targetSpace.m_localMatrixAdd.Down);
                targetSpace.m_mirroringOffset = offset;
                targetSpace.m_addPos += targetSpace.m_mirroringOffset;
                targetSpace.m_removePos += targetSpace.m_mirroringOffset;
                targetSpace.m_removeBlock = cubeGrid.GetCubeBlock(targetSpace.m_removePos);
                //targetSpace.m_gizmoAddDir = sourceSpace.m_gizmoAddDir;
                targetSpace.m_localMatrixAdd.Translation += offset;
            }


            targetSpace.m_worldMatrixAdd = targetSpace.m_localMatrixAdd * cubeGrid.WorldMatrix;

            Debug.Assert(!targetSpace.m_worldMatrixAdd.IsNan(), "Invalid gizmo matrix");
        }
 private void RemoveGizmoCubeParts(MyGizmoSpaceProperties gizmoSpace)
 {
     gizmoSpace.m_cubeMatrices.Clear();
     gizmoSpace.m_cubeModels.Clear();
 }
        private void AddGizmoCubeParts(MyGizmoSpaceProperties gizmoSpace, MyBlockBuilderRenderData renderData, ref MatrixD invGridWorldMatrix, MyCubeBlockDefinition definition)
        {
            Vector3UByte[] bones = null;
            MyTileDefinition[] tiles = null;
            MatrixD invGridWorldMatrixOrientation = invGridWorldMatrix.GetOrientation();
            float gridSize = 1f;
            if (definition != null && definition.Skeleton != null)
            {
                tiles = MyCubeGridDefinitions.GetCubeTiles(definition);
                gridSize = MyDefinitionManager.Static.GetCubeSize(definition.CubeSize);
            }

            for (int faceIndex = 0; faceIndex < gizmoSpace.m_cubeModelsTemp.Count; faceIndex++)
            {
                string cubePartModel = gizmoSpace.m_cubeModelsTemp[faceIndex];

                gizmoSpace.m_cubeModels.Add(cubePartModel);
                gizmoSpace.m_cubeMatrices.Add(gizmoSpace.m_cubeMatricesTemp[faceIndex]);

                int tileIndex = faceIndex % tiles.Count();

                var invertedTile = Matrix.Transpose(tiles[tileIndex].LocalMatrix);
                var onlyOrientation = invertedTile * gizmoSpace.m_cubeMatricesTemp[faceIndex].GetOrientation();
                var boneMatrix = onlyOrientation * invGridWorldMatrixOrientation;

                if (tiles != null)
                {
                    bones = new Vector3UByte[9];
                    for (int i = 0; i < 9; i++)
                    {
                        bones[i] = new Vector3UByte(128, 128, 128);
                    }

                    var model = MyModels.GetModel(cubePartModel);

                    for (int index = 0; index < Math.Min(model.BoneMapping.Length, 9); index++)
                    {
                        var boneOffset = model.BoneMapping[index];
                        Vector3 centered = boneOffset - Vector3.One;

                        Vector3I transformedOffset = Vector3I.Round(Vector3.Transform(centered, tiles[tileIndex].LocalMatrix) + Vector3.One);

                        for (int skeletonIndex = 0; skeletonIndex < definition.Skeleton.Count; skeletonIndex++)
                        {
                            BoneInfo skeletonBone = definition.Skeleton[skeletonIndex];
                            if (skeletonBone.BonePosition == (SerializableVector3I)transformedOffset)
                            {
                                Vector3 bone = Vector3UByte.Denormalize(skeletonBone.BoneOffset, gridSize);
                                Vector3 transformedBone = Vector3.Transform(bone, boneMatrix);
                                bones[index] = Vector3UByte.Normalize(transformedBone, gridSize);
                                break;
                            }
                        }
                    }
                }

                renderData.AddInstance(MyModel.GetId(cubePartModel), gizmoSpace.m_cubeMatricesTemp[faceIndex], ref invGridWorldMatrix, bones: bones, gridSize: gridSize);
            }
        }
 public void UpdateGizmoCubeParts(MyGizmoSpaceProperties gizmoSpace, MyBlockBuilderRenderData renderData, ref MatrixD invGridWorldMatrix, MyCubeBlockDefinition definition = null)
 {
     RemoveGizmoCubeParts(gizmoSpace);
     AddGizmoCubeParts(gizmoSpace, renderData, ref invGridWorldMatrix, definition);
 }
        public void SetupLocalAddMatrix(MyGizmoSpaceProperties gizmoSpace, Vector3I normal)
        {
            var norm = -normal; // Make it towards the cube

            // Rotation from identity to normal
            Matrix rotToNormal = Matrix.CreateWorld(Vector3.Zero, norm, Vector3I.Shift(norm));

            // Rotation from normal to identity
            Matrix rotFromNormal = Matrix.Invert(rotToNormal);
            var dir = Vector3I.Round((rotToNormal * gizmoSpace.m_localMatrixAdd).Up);

            // When incoming rotation is invalid for current direction (e.g. changing face)
            if (dir == gizmoSpace.m_addDir || dir == -gizmoSpace.m_addDir)
                dir = Vector3I.Shift(dir);

            // Rotation from identity to target (gizmo add direction)
            Matrix rotToTarget = Matrix.CreateWorld(Vector3.Zero, gizmoSpace.m_addDir, dir);
            Debug.Assert(!rotToTarget.IsNan(), "Invalid gizmo matrix");

            // First rotate from normal direction to identity, than to target
            gizmoSpace.m_localMatrixAdd = rotFromNormal * rotToTarget;
            Debug.Assert(!gizmoSpace.m_localMatrixAdd.IsNan(), "Invalid gizmo matrix");
        }
        public MyCubeBuilderGizmo()
        {
            for (int i = 0; i < 8; i++)
            {
                m_spaces[i] = new MyGizmoSpaceProperties();
            }

            m_spaces[(int)MyGizmoSpaceEnum.Default].Enabled = true;
            m_spaces[(int)MyGizmoSpaceEnum.SymmetryX].SourceSpace = MyGizmoSpaceEnum.Default;
            m_spaces[(int)MyGizmoSpaceEnum.SymmetryX].SymmetryPlane = MySymmetrySettingModeEnum.NoPlane;

            m_spaces[(int)MyGizmoSpaceEnum.SymmetryX].SourceSpace = MyGizmoSpaceEnum.Default;
            m_spaces[(int)MyGizmoSpaceEnum.SymmetryX].SymmetryPlane = MySymmetrySettingModeEnum.XPlane;

            m_spaces[(int)MyGizmoSpaceEnum.SymmetryY].SourceSpace = MyGizmoSpaceEnum.Default;
            m_spaces[(int)MyGizmoSpaceEnum.SymmetryY].SymmetryPlane = MySymmetrySettingModeEnum.YPlane;

            m_spaces[(int)MyGizmoSpaceEnum.SymmetryZ].SourceSpace = MyGizmoSpaceEnum.Default;
            m_spaces[(int)MyGizmoSpaceEnum.SymmetryZ].SymmetryPlane = MySymmetrySettingModeEnum.ZPlane;

            m_spaces[(int)MyGizmoSpaceEnum.SymmetryXY].SourceSpace = MyGizmoSpaceEnum.SymmetryX;
            m_spaces[(int)MyGizmoSpaceEnum.SymmetryXY].SymmetryPlane = MySymmetrySettingModeEnum.YPlane;

            m_spaces[(int)MyGizmoSpaceEnum.SymmetryYZ].SourceSpace = MyGizmoSpaceEnum.SymmetryY;
            m_spaces[(int)MyGizmoSpaceEnum.SymmetryYZ].SymmetryPlane = MySymmetrySettingModeEnum.ZPlane;

            m_spaces[(int)MyGizmoSpaceEnum.SymmetryXZ].SourceSpace = MyGizmoSpaceEnum.SymmetryX;
            m_spaces[(int)MyGizmoSpaceEnum.SymmetryXZ].SymmetryPlane = MySymmetrySettingModeEnum.ZPlane;

            m_spaces[(int)MyGizmoSpaceEnum.SymmetryXYZ].SourceSpace = MyGizmoSpaceEnum.SymmetryXZ;
            m_spaces[(int)MyGizmoSpaceEnum.SymmetryXYZ].SymmetryPlane = MySymmetrySettingModeEnum.YPlane;
        }