Пример #1
0
    public static MagitekResult TryRotateElement(this Arranger arranger, int elementX, int elementY, RotationOperation rotate)
    {
        if (rotate == RotationOperation.None)
        {
            return(MagitekResult.SuccessResult);
        }

        if (elementX > arranger.ArrangerElementSize.Width || elementY > arranger.ArrangerElementSize.Height)
        {
            return(new MagitekResult.Failed($"Location ({elementX}, {elementY}) is outside of the arranger"));
        }

        if (arranger.GetElement(elementX, elementY) is ArrangerElement el)
        {
            if (el.Width != el.Height)
            {
                return(new MagitekResult.Failed("Only square elements may be rotated"));
            }

            var newRotation = (el.Rotation, rotate) switch
            {
                (RotationOperation.Left, RotationOperation.Left) => RotationOperation.Turn,
                (RotationOperation.Turn, RotationOperation.Left) => RotationOperation.Right,
                (RotationOperation.Right, RotationOperation.Left) => RotationOperation.None,

                (RotationOperation.Left, RotationOperation.Right) => RotationOperation.None,
                (RotationOperation.Turn, RotationOperation.Right) => RotationOperation.Left,
                (RotationOperation.Right, RotationOperation.Right) => RotationOperation.Turn,

                (RotationOperation.Left, RotationOperation.Turn) => RotationOperation.Right,
                (RotationOperation.Turn, RotationOperation.Turn) => RotationOperation.None,
                (RotationOperation.Right, RotationOperation.Turn) => RotationOperation.Left,

                (RotationOperation.None, _) => rotate,
                (_, RotationOperation.None) => el.Rotation,
                _ => el.Rotation
            };

            var rotatedElement = el.WithRotation(newRotation);
            arranger.SetElement(rotatedElement, elementX, elementY);

            return(MagitekResult.SuccessResult);
        }

        return(new MagitekResult.Failed($"No element present at position ({elementX}, {elementY}) to be rotated"));
    }
Пример #2
0
    /// <summary>
    /// Creates a copy of an Arranger's ArrangerElements
    /// </summary>
    /// <param name="source">Arranger containing the elements to be copied from</param>
    /// <param name="elementX">Starting x-coordinate of copy in element coordinates</param>
    /// <param name="elementY">Starting y-coordinate of copy in element coordinates</param>
    /// <param name="copyWidth">Width of copy in element coordinates</param>
    /// <param name="copyHeight">Height of copy in element coordinates</param>
    public ElementCopy(Arranger source, int elementX, int elementY, int copyWidth, int copyHeight)
    {
        Source          = source;
        ProjectResource = Source;
        X                  = elementX;
        Y                  = elementY;
        Width              = copyWidth;
        Height             = copyHeight;
        ElementPixelWidth  = source.ElementPixelSize.Width;
        ElementPixelHeight = source.ElementPixelSize.Height;

        Elements = new ArrangerElement?[copyWidth, copyHeight];

        for (int y = 0; y < copyHeight; y++)
        {
            for (int x = 0; x < copyWidth; x++)
            {
                Elements[x, y] = source.GetElement(x + elementX, y + elementY);
            }
        }
    }
Пример #3
0
    public static MagitekResult TryMirrorElement(this Arranger arranger, int elementX, int elementY, MirrorOperation mirror)
    {
        if (mirror == MirrorOperation.None)
        {
            return(MagitekResult.SuccessResult);
        }

        if (arranger.GetElement(elementX, elementY) is ArrangerElement el)
        {
            var newMirror = (el.Mirror, mirror) switch
            {
                (MirrorOperation.Horizontal, MirrorOperation.Horizontal) => MirrorOperation.None,
                (MirrorOperation.Vertical, MirrorOperation.Horizontal) => MirrorOperation.Both,
                (MirrorOperation.Both, MirrorOperation.Horizontal) => MirrorOperation.Vertical,

                (MirrorOperation.Horizontal, MirrorOperation.Vertical) => MirrorOperation.Both,
                (MirrorOperation.Vertical, MirrorOperation.Vertical) => MirrorOperation.None,
                (MirrorOperation.Both, MirrorOperation.Vertical) => MirrorOperation.Horizontal,

                (MirrorOperation.Horizontal, MirrorOperation.Both) => MirrorOperation.Vertical,
                (MirrorOperation.Vertical, MirrorOperation.Both) => MirrorOperation.Horizontal,
                (MirrorOperation.Both, MirrorOperation.Both) => MirrorOperation.None,

                (MirrorOperation.None, _) => mirror,
                (_, MirrorOperation.None) => el.Mirror,
                _ => el.Mirror
            };

            var mirroredElement = el.WithMirror(newMirror);
            arranger.SetElement(mirroredElement, elementX, elementY);

            return(MagitekResult.SuccessResult);
        }

        return(new MagitekResult.Failed($"No element present at position ({elementX}, {elementY}) to be mirrored"));
    }
Пример #4
0
    public override void Render()
    {
        if (Width <= 0 || Height <= 0)
        {
            throw new InvalidOperationException($"{nameof(Render)}: arranger dimensions for '{Arranger.Name}' are too small to render " +
                                                $"({Width}, {Height})");
        }

        if (Width * Height != Image.Length)
        {
            Image = new byte[Width * Height];
        }

        // TODO: Handle undefined elements explicitly and clear image subsections
        Array.Clear(Image, 0, Image.Length);

        var locations = Arranger.EnumerateElementLocationsWithinPixelRange(Left, Top, Width, Height);

        var imageRect = new Rectangle(Left, Top, Width, Height);

        foreach (var location in locations)
        {
            var el = Arranger.GetElement(location.X, location.Y);
            if (el is ArrangerElement element && element.Codec is IIndexedCodec codec)
            {
                var encodedBuffer = codec.ReadElement(element);

                // TODO: Detect reads past end of file more gracefully
                if (encodedBuffer.Length == 0)
                {
                    continue;
                }

                var elementRect = new Rectangle(element.X1, element.Y1, element.Width, element.Height);
                elementRect.Intersect(imageRect);

                if (elementRect.IsEmpty)
                {
                    continue;
                }

                int minX   = Math.Clamp(element.X1, Left, Right - 1);
                int maxX   = Math.Clamp(element.X2, Left, Right - 1);
                int minY   = Math.Clamp(element.Y1, Top, Bottom - 1);
                int maxY   = Math.Clamp(element.Y2, Top, Bottom - 1);
                int deltaX = minX - element.X1;
                int deltaY = minY - element.Y1;

                var decodedImage = codec.DecodeElement(element, encodedBuffer);
                decodedImage.RotateArray2D(element.Rotation);
                decodedImage.MirrorArray2D(element.Mirror);

                for (int y = 0; y <= maxY - minY; y++)
                {
                    int destidx = (element.Y1 + deltaY + y - Top) * Width + (element.X1 + deltaX - Left);
                    for (int x = 0; x <= maxX - minX; x++)
                    {
                        Image[destidx] = decodedImage[y + deltaY, x + deltaX];
                        destidx++;
                    }
                }
            }