Exemplo n.º 1
0
    public static ScatteredArranger CreateIndexedArrangerFromImage(string imageFile, ColorModel colorModel,
                                                                   bool zeroIndexTransparent, ICodecFactory factory, IGraphicsCodec codec)
    {
        var image        = new Bitmap(imageFile);
        var imagePalette = image.Palette;

        var palette      = new Palette("testPalette", new ColorFactory(), colorModel, zeroIndexTransparent, PaletteStorageSource.Project);
        var colorSources = imagePalette.Entries
                           .Select(x => new ProjectNativeColorSource(new ColorRgba32(x.R, x.G, x.B, x.A)));

        palette.SetColorSources(colorSources);

        var file   = new MemoryDataSource("test", image.Width * image.Height);
        var elemsX = image.Width / codec.Width;
        var elemsY = image.Height / codec.Height;

        var arranger = new ScatteredArranger("testArranger", PixelColorType.Indexed, ElementLayout.Tiled, elemsX, elemsY, codec.Width, codec.Height);

        var address = new BitAddress(0);

        for (int y = 0; y < elemsY; y++)
        {
            for (int x = 0; x < elemsX; x++)
            {
                var element = new ArrangerElement(x, y, file, address, factory.CloneCodec(codec), palette);
                address += codec.StorageSize;

                arranger.SetElement(element, x, y);
            }
        }

        return(arranger);
    }
Exemplo n.º 2
0
    public MagitekResult AddScatteredArranger(ScatteredArrangerModel arrangerModel, string parentNodePath, string fileLocation)
    {
        var arranger = new ScatteredArranger(arrangerModel.Name, arrangerModel.ColorType, arrangerModel.Layout,
                                             arrangerModel.ArrangerElementSize.Width, arrangerModel.ArrangerElementSize.Height, arrangerModel.ElementPixelSize.Width, arrangerModel.ElementPixelSize.Height);

        for (int x = 0; x < arrangerModel.ElementGrid.GetLength(0); x++)
        {
            for (int y = 0; y < arrangerModel.ElementGrid.GetLength(1); y++)
            {
                var result = CreateElement(arrangerModel, x, y);

                if (result.IsT0)
                {
                    arranger.SetElement(result.AsT0.Result, x, y);
                }
                else if (result.IsT1)
                {
                    return(new MagitekResult.Failed(result.AsT1.Reason));
                }
            }
        }

        var arrangerNode = new ArrangerNode(arranger.Name, arranger)
        {
            DiskLocation = fileLocation,
            Model        = arrangerModel
        };

        Tree.TryGetNode(parentNodePath, out var parentNode);
        parentNode.AttachChildNode(arrangerNode);

        return(MagitekResult.SuccessResult);
    }
Exemplo n.º 3
0
    /// <summary>
    /// Copies elements from the source into specified destination ScatteredArranger
    /// </summary>
    /// <param name="source"></param>
    /// <param name="dest"></param>
    /// <param name="sourceStart">Starting point of source arranger in element coordinates</param>
    /// <param name="destStart">Starting point of destination arranger in element coordinates</param>
    /// <param name="copyWidth">Width of copy in elements</param>
    /// <param name="copyHeight">Height of copy in elements</param>
    public static MagitekResult CopyElements(ElementCopy source, ScatteredArranger dest, Point sourceStart, Point destStart, int copyWidth, int copyHeight)
    {
        var result = CanCopyElements(source, dest, sourceStart, destStart, copyWidth, copyHeight);

        if (result.Value is MagitekResult.Success)
        {
            CopyElementsInternal(source, dest, sourceStart, destStart, copyWidth, copyHeight);
        }

        return(result);
Exemplo n.º 4
0
    public static ScatteredArrangerModel MapToModel(this ScatteredArranger arranger, Dictionary <IProjectResource, string> resourceMap)
    {
        var model = new ScatteredArrangerModel()
        {
            Name = arranger.Name,
            ArrangerElementSize = arranger.ArrangerElementSize,
            ElementPixelSize    = arranger.ElementPixelSize,
            Layout    = arranger.Layout,
            ColorType = arranger.ColorType
        };

        model.ElementGrid = new ArrangerElementModel[model.ArrangerElementSize.Width, model.ArrangerElementSize.Height];

        for (int x = 0; x < model.ElementGrid.GetLength(0); x++)
        {
            for (int y = 0; y < model.ElementGrid.GetLength(1); y++)
            {
                if (arranger.GetElement(x, y) is ArrangerElement el)
                {
                    model.ElementGrid[x, y] = MapToModel(el, x, y);
                }
            }
        }

        return(model);

        ArrangerElementModel MapToModel(ArrangerElement el, int elemX, int elemY)
        {
            var model = new ArrangerElementModel
            {
                FileAddress = el.SourceAddress,
                PositionX   = elemX,
                PositionY   = elemY,
                CodecName   = el.Codec.Name,
                Mirror      = el.Mirror,
                Rotation    = el.Rotation
            };

            if (el.Source is not null && resourceMap.TryGetValue(el.Source, out var dataFileKey))
            {
                model.DataFileKey = dataFileKey;
            }

            if (el.Palette is not null && resourceMap.TryGetValue(el.Palette, out var paletteKey))
            {
                model.PaletteKey = paletteKey;
            }

            return(model);
        }
    }
Exemplo n.º 5
0
 static void CopyElementsInternal(ElementCopy source, ScatteredArranger dest, Point sourceStart, Point destStart, int copyWidth, int copyHeight)
 {
     for (int y = 0; y < copyHeight; y++)
     {
         for (int x = 0; x < copyWidth; x++)
         {
             var el = source.Elements[x + sourceStart.X, y + sourceStart.Y];
             if (el is ArrangerElement element)
             {
                 dest.SetElement(element, x + destStart.X, y + destStart.Y);
             }
         }
     }
 }
Exemplo n.º 6
0
    /// <summary>
    /// Adds the specified resource to the parent resource node
    /// </summary>
    /// <param name="parentNode">ResourceNode that is contained by the project</param>
    /// <param name="resource">New resource to add</param>
    /// <returns>The added resource node result</returns>
    public virtual MagitekResult <ResourceNode> AddResource(ResourceNode parentNode, IProjectResource resource)
    {
        var tree = _projects.FirstOrDefault(x => x.ContainsNode(parentNode));

        if (tree is null)
        {
            return(new MagitekResult <ResourceNode> .Failed($"{parentNode.Item.Name} is not contained within any loaded project"));
        }

        if (parentNode.ContainsChildNode(resource.Name))
        {
            return(new MagitekResult <ResourceNode> .Failed($"'{parentNode.Name}' already contains a child named '{resource.Name}'"));
        }
        else if (parentNode.Item.CanContainChildResources == false)
        {
            return(new MagitekResult <ResourceNode> .Failed($"'{parentNode.Name}' cannot contain children"));
        }

        try
        {
            ResourceNode childNode = resource switch
            {
                DataSource df => new DataFileNode(df.Name, df),
                ScatteredArranger arranger => new ArrangerNode(arranger.Name, arranger),
                Palette pal => new PaletteNode(pal.Name, pal),
                ResourceFolder folder => new ResourceFolderNode(folder.Name, folder),
                _ => null
            };

            if (childNode is null)
            {
                return(new MagitekResult <ResourceNode> .Failed($"Cannot add a resource of type '{resource.GetType()}'"));
            }

            var contents = _serializerFactory.CreateWriter(tree).SerializeResource(childNode);
            var location = ResourceFileLocator.LocateByParent(tree, parentNode, childNode);
            File.WriteAllText(location, contents);

            parentNode.AttachChildNode(childNode);
            childNode.DiskLocation = location;
            UpdateNodeModel(tree, childNode);

            return(new MagitekResult <ResourceNode> .Success(childNode));
        }
        catch (Exception ex)
        {
            return(new MagitekResult <ResourceNode> .Failed(ex.Message));
        }
    }
Exemplo n.º 7
0
    public void ScatteredArranger_Reversibility_CanReverse(ScatteredArranger arranger, string imageFileName)
    {
        var exportedImageFileName = $"test.png";

        var indexedImage = new IndexedImage(arranger);

        indexedImage.ImportImage(imageFileName, new ImageSharpFileAdapter(), ColorMatchStrategy.Exact);
        indexedImage.ExportImage(exportedImageFileName, new ImageSharpFileAdapter());

        using var expected = Image <Rgba32> .Load <Rgba32>(imageFileName);

        using var actual = Image <Rgba32> .Load <Rgba32>(exportedImageFileName);

        ImageRgba32Assert.AreEqual(expected, actual);
    }
Exemplo n.º 8
0
    public void Build_ScatteredArranger()
    {
        ScatteredArranger arranger = ArrangerBuilder
                                     .WithTiledLayout()
                                     .WithArrangerElementSize(8, 16)
                                     .WithElementPixelSize(8, 8)
                                     .WithPixelColorType(PixelColorType.Indexed)
                                     .WithName("ScatteredTestArranger")
                                     .AsScatteredArranger()
                                     .Build();

        Assert.That(arranger.Layout == ElementLayout.Tiled);
        Assert.That(arranger.ArrangerElementSize == new Size(8, 16));
        Assert.That(arranger.ElementPixelSize == new Size(8, 8));
        Assert.That(arranger.ColorType == PixelColorType.Indexed);
        Assert.That(arranger.Name == "ScatteredTestArranger");
    }
Exemplo n.º 9
0
    public void Setup()
    {
        _df            = new MemoryDataSource("MemoryDataSource");
        _sourceIndexed = new ScatteredArranger("source", PixelColorType.Indexed, ElementLayout.Tiled, 6, 6, 8, 8);

        for (int y = 0; y < _sourceIndexed.ArrangerElementSize.Height; y++)
        {
            for (int x = 0; x < _sourceIndexed.ArrangerElementSize.Width; x++)
            {
                if (_sourceIndexed.GetElement(x, y) is ArrangerElement element)
                {
                    element = element.WithTarget(_df, new BitAddress(x * y), new Snes3bppCodec(8, 8), null);
                    _sourceIndexed.SetElement(element, x, y);
                }
            }
        }
    }
Exemplo n.º 10
0
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item == null || container is null)
        {
            return(null);
        }

        if (item is ResourceChangeViewModel changeVm)
        {
            return(changeVm.Resource switch
            {
                ResourceFolder _ => FolderNodeTemplate,
                DataSource _ => DataFileNodeTemplate,
                ScatteredArranger _ => ArrangerNodeTemplate,
                Palette _ => PaletteNodeTemplate,
                _ => throw new ArgumentException($"{nameof(SelectTemplate)} does not contain a template for type {changeVm.Resource.GetType()}")
            });
Exemplo n.º 11
0
    /// <summary>
    /// Tests if the source can be copied into the specified destination ScatteredArranger
    /// </summary>
    /// <param name="source"></param>
    /// <param name="dest"></param>
    /// <param name="destStart">Upper-left point to begin copying into in element coordinates</param>
    /// <returns></returns>
    public static MagitekResult CanCopyElements(ElementCopy source, ScatteredArranger dest, Point sourceStart, Point destStart, int copyWidth, int copyHeight)
    {
        if (copyWidth > dest.ArrangerElementSize.Width - destStart.X)
        {
            return(new MagitekResult.Failed($"Destination arranger '{dest.Name}' with width ({dest.ArrangerElementSize.Width}) is insufficient to copy {copyWidth} elements starting from position {destStart.X}"));
        }

        if (copyHeight > dest.ArrangerElementSize.Height - destStart.Y)
        {
            return(new MagitekResult.Failed($"Destination arranger '{dest.Name}' with height ({dest.ArrangerElementSize.Height}) is insufficient to copy {copyHeight} elements starting from position {destStart.Y}"));
        }

        if (copyWidth > source.Width - sourceStart.X)
        {
            return(new MagitekResult.Failed($"Source copy with width ({source.Width}) is insufficient to copy {copyWidth} elements starting from position {sourceStart.X}"));
        }

        if (copyHeight > source.Height - sourceStart.Y)
        {
            return(new MagitekResult.Failed($"Source copy with height ({source.Height}) is insufficient to copy {copyHeight} elements starting from position {sourceStart.Y}"));
        }

        if (source.Source.ElementPixelSize != dest.ElementPixelSize)
        {
            return(new MagitekResult.Failed($"Source arranger '{source.Source.Name}' with element size ({source.Source.ElementPixelSize.Width}, {source.Source.ElementPixelSize.Height}) does not match destination arranger '{dest.Name}' with element size ({dest.ElementPixelSize.Width}, {dest.ElementPixelSize.Height})"));
        }

        if (dest.Layout != ElementLayout.Tiled && (copyWidth != 1 || copyHeight != 1))
        {
            return(new MagitekResult.Failed($"Destination arranger '{dest.Name}' is not a tiled layout"));
        }

        if (source.Source.ColorType != dest.ColorType)
        {
            return(new MagitekResult.Failed($"Source arranger '{source.Source.Name}' ColorType {source.Source.ColorType} does not match destination arranger ColorType {dest.ColorType}"));
        }

        return(MagitekResult.SuccessResult);
    }
Exemplo n.º 12
0
    public void Setup(string dataFileName, string arrangerName)
    {
        using (var fs = File.Create(dataFileName))
        {
            Random rng  = new Random();
            var    data = new byte[3 * 16 * 32];
            rng.NextBytes(data);
            fs.Write(data);
        }

        _df = new FileDataSource("FileSource", Path.GetFullPath(dataFileName));

        _arranger = new ScatteredArranger(arrangerName, PixelColorType.Indexed, ElementLayout.Tiled, 16, 32, 8, 8);

        for (int y = 0; y < _arranger.ArrangerElementSize.Height; y++)
        {
            for (int x = 0; x < _arranger.ArrangerElementSize.Width; x++)
            {
                var el = new ArrangerElement(x * 8, y * 8, _df, new BitAddress(24 * x + 24 * x * y), _codec, _pal);
                _arranger.SetElement(el, x, y);
            }
        }
    }
Exemplo n.º 13
0
    /// <summary>
    /// Private method for cloning an Arranger
    /// </summary>
    /// <param name="posX">Left edge of Arranger in pixel coordinates</param>
    /// <param name="posY">Top edge of Arranger in pixel coordinates</param>
    /// <param name="width">Width of Arranger in pixels</param>
    /// <param name="height">Height of Arranger in pixels</param>
    /// <returns></returns>
    protected override Arranger CloneArrangerCore(int posX, int posY, int width, int height)
    {
        var elemX       = posX / ElementPixelSize.Width;
        var elemY       = posY / ElementPixelSize.Height;
        var elemsWidth  = (width + ElementPixelSize.Width - 1) / ElementPixelSize.Width;
        var elemsHeight = (height + ElementPixelSize.Height - 1) / ElementPixelSize.Height;

        var arranger = new ScatteredArranger(Name, ColorType, Layout, elemsWidth, elemsHeight, ElementPixelSize.Width, ElementPixelSize.Height);

        for (int y = 0; y < elemsHeight; y++)
        {
            for (int x = 0; x < elemsWidth; x++)
            {
                var el = ElementGrid[y + elemY, x + elemX]?.WithLocation(x * ElementPixelSize.Width, y * ElementPixelSize.Height);
                if (el is ArrangerElement element)
                {
                    arranger.SetElement(element, x, y);
                }
            }
        }

        return(arranger);
    }
Exemplo n.º 14
0
 public ArrangerNode(string nodeName, ScatteredArranger resource) : base(nodeName, resource)
 {
 }