static List <PanePatch> DiffPanes(BflytFile _or, BflytFile _ed, string filename)
        {
            List <PanePatch> curFile = new List <PanePatch>();

            foreach (var orpane_ in _or.EnumeratePanes().Where(x => x is INamedPane))
            {
                var edpane = _ed[((INamedPane)orpane_).PaneName];
                if (edpane == null)
                {
                    throw new Exception($"{filename} is missing {((INamedPane)orpane_).PaneName}");
                }
                if (orpane_.name != edpane.name)
                {
                    throw new Exception($"{filename} : {((INamedPane)orpane_).PaneName} Two panes with the same name are of a different type");
                }
                if (IgnorePaneList.Contains(orpane_.name))
                {
                    continue;
                }

                var edPan = (Pan1Pane)edpane;
                var orPan = (Pan1Pane)orpane_;

                PanePatch curPatch = new PanePatch()
                {
                    PaneName = edPan.PaneName
                };
                curPatch.UsdPatches = MakeUsdPatch(edPan.UserData, orPan.UserData);
                if (edPan.data.SequenceEqual(orPan.data))
                {
                    if (curPatch.UsdPatches != null)
                    {
                        curFile.Add(curPatch);
                    }
                    continue;
                }

                if (edPan.Position != orPan.Position)
                {
                    curPatch.Position = edPan.Position;
                }
                if (edPan.Rotation != orPan.Rotation)
                {
                    curPatch.Rotation = edPan.Rotation;
                }
                if (edPan.Scale != orPan.Scale)
                {
                    curPatch.Scale = edPan.Scale;
                }
                if (edPan.Size != orPan.Size)
                {
                    curPatch.Size = edPan.Size;
                }
                if (edPan.Visible != orPan.Visible)
                {
                    curPatch.Visible = edPan.Visible;
                }

                if (edPan.originX != orPan.originX)
                {
                    curPatch.OriginX = (byte)edPan.originX;
                }
                if (edPan.originY != orPan.originY)
                {
                    curPatch.OriginY = (byte)edPan.originY;
                }
                if (edPan.ParentOriginX != orPan.ParentOriginX)
                {
                    curPatch.ParentOriginX = (byte)edPan.ParentOriginX;
                }
                if (edPan.ParentOriginY != orPan.ParentOriginY)
                {
                    curPatch.ParentOriginY = (byte)edPan.ParentOriginY;
                }

                if (edPan is Pic1Pane && orPan is Pic1Pane)
                {
                    var edPic = (Pic1Pane)edPan;
                    var orPic = (Pic1Pane)orPan;
                    if (edPic.ColorTopLeft != orPic.ColorTopLeft)
                    {
                        curPatch.PaneSpecific0 = edPic.ColorTopLeft.AsHexLEString();
                    }
                    if (edPic.ColorTopRight != orPic.ColorTopRight)
                    {
                        curPatch.PaneSpecific1 = edPic.ColorTopRight.AsHexLEString();
                    }
                    if (edPic.ColorBottomLeft != orPic.ColorBottomLeft)
                    {
                        curPatch.PaneSpecific2 = edPic.ColorBottomLeft.AsHexLEString();
                    }
                    if (edPic.ColorBottomRight != orPic.ColorBottomRight)
                    {
                        curPatch.PaneSpecific3 = edPic.ColorBottomRight.AsHexLEString();
                    }
                }

                if (edPan is Txt1Pane && orPan is Txt1Pane)
                {
                    var edTxt = (Txt1Pane)edPan;
                    var orTxt = (Txt1Pane)orPan;
                    if (edTxt.FontTopColor != orTxt.FontTopColor)
                    {
                        curPatch.PaneSpecific0 = edTxt.FontTopColor.AsHexLEString();
                    }
                    if (edTxt.ShadowTopColor != orTxt.ShadowTopColor)
                    {
                        curPatch.PaneSpecific1 = edTxt.ShadowTopColor.AsHexLEString();
                    }
                    if (edTxt.FontBottomColor != orTxt.FontBottomColor)
                    {
                        curPatch.PaneSpecific2 = edTxt.FontBottomColor.AsHexLEString();
                    }
                    if (edTxt.ShadowBottomColor != orTxt.ShadowBottomColor)
                    {
                        curPatch.PaneSpecific3 = edTxt.ShadowBottomColor.AsHexLEString();
                    }
                }
                curFile.Add(curPatch);
            }

            return(curFile);
        }
Exemple #2
0
        public static (LayoutPatch, string) Diff(SarcData original, SarcData edited)
        {
            List <LayoutFilePatch> Patches = new List <LayoutFilePatch>();

            if (!ScrambledEquals <string>(original.Files.Keys, edited.Files.Keys))
            {
                throw new Exception("The provided archives don't have the same files");
            }

            bool hasAtLeastAnExtraGroup = false;             //Used to detect if animations are properly implemented

            foreach (var f in original.Files.Keys.Where(x => x.EndsWith(".bflyt")))
            {
                if (original.Files[f].SequenceEqual(edited.Files[f]))
                {
                    continue;
                }
                BflytFile _or = new BflytFile(original.Files[f]);
                BflytFile _ed = new BflytFile(edited.Files[f]);

                List <PanePatch> curFile = new List <PanePatch>();
                foreach (var orpane_ in _or.EnumeratePanes().Where(x => x is INamedPane))
                {
                    var edpane = _ed[((INamedPane)orpane_).PaneName];
                    if (edpane == null)
                    {
                        throw new Exception($"{f} is missing {((INamedPane)orpane_).PaneName}");
                    }
                    if (orpane_.name != edpane.name)
                    {
                        throw new Exception($"{f} : {((INamedPane)orpane_).PaneName} Two panes with the same name are of a different type");
                    }
                    if (IgnorePaneList.Contains(orpane_.name))
                    {
                        continue;
                    }

                    var edPan = (Pan1Pane)edpane;
                    var orPan = (Pan1Pane)orpane_;

                    PanePatch curPatch = new PanePatch()
                    {
                        PaneName = edPan.PaneName
                    };
                    curPatch.UsdPatches = MakeUsdPatch(edPan.UserData, orPan.UserData);
                    if (edPan.data.SequenceEqual(orPan.data))
                    {
                        if (curPatch.UsdPatches != null)
                        {
                            curFile.Add(curPatch);
                        }
                        continue;
                    }

                    if (!VecEqual(edPan.Position, orPan.Position))
                    {
                        curPatch.Position = ToNullVec(edPan.Position);
                    }
                    if (!VecEqual(edPan.Rotation, orPan.Rotation))
                    {
                        curPatch.Rotation = ToNullVec(edPan.Rotation);
                    }
                    if (!VecEqual(edPan.Scale, orPan.Scale))
                    {
                        curPatch.Scale = ToNullVec(edPan.Scale);
                    }
                    if (!VecEqual(edPan.Size, orPan.Size))
                    {
                        curPatch.Size = ToNullVec(edPan.Size);
                    }
                    if (edPan.Visible != orPan.Visible)
                    {
                        curPatch.Visible = edPan.Visible;
                    }

                    if (edPan.originX != orPan.originX)
                    {
                        curPatch.OriginX = (byte)edPan.originX;
                    }
                    if (edPan.originY != orPan.originY)
                    {
                        curPatch.OriginY = (byte)edPan.originY;
                    }
                    if (edPan.ParentOriginX != orPan.ParentOriginX)
                    {
                        curPatch.ParentOriginX = (byte)edPan.ParentOriginX;
                    }
                    if (edPan.ParentOriginY != orPan.ParentOriginY)
                    {
                        curPatch.ParentOriginY = (byte)edPan.ParentOriginY;
                    }

                    if (edPan is Pic1Pane && orPan is Pic1Pane)
                    {
                        var edPic = (Pic1Pane)edPan;
                        var orPic = (Pic1Pane)orPan;
                        if (edPic.ColorTopLeft != orPic.ColorTopLeft)
                        {
                            curPatch.PaneSpecific0 = edPic.ColorTopLeft.AsHexLEString();
                        }
                        if (edPic.ColorTopRight != orPic.ColorTopRight)
                        {
                            curPatch.PaneSpecific1 = edPic.ColorTopRight.AsHexLEString();
                        }
                        if (edPic.ColorBottomLeft != orPic.ColorBottomLeft)
                        {
                            curPatch.PaneSpecific2 = edPic.ColorBottomLeft.AsHexLEString();
                        }
                        if (edPic.ColorBottomRight != orPic.ColorBottomRight)
                        {
                            curPatch.PaneSpecific3 = edPic.ColorBottomRight.AsHexLEString();
                        }
                    }

                    if (edPan is Txt1Pane && orPan is Txt1Pane)
                    {
                        var edTxt = (Txt1Pane)edPan;
                        var orTxt = (Txt1Pane)orPan;
                        if (edTxt.FontTopColor != orTxt.FontTopColor)
                        {
                            curPatch.PaneSpecific0 = edTxt.FontTopColor.AsHexLEString();
                        }
                        if (edTxt.ShadowTopColor != orTxt.ShadowTopColor)
                        {
                            curPatch.PaneSpecific1 = edTxt.ShadowTopColor.AsHexLEString();
                        }
                        if (edTxt.FontBottomColor != orTxt.FontBottomColor)
                        {
                            curPatch.PaneSpecific2 = edTxt.FontBottomColor.AsHexLEString();
                        }
                        if (edTxt.ShadowBottomColor != orTxt.ShadowBottomColor)
                        {
                            curPatch.PaneSpecific3 = edTxt.ShadowBottomColor.AsHexLEString();
                        }
                    }
                    curFile.Add(curPatch);
                }

                List <ExtraGroup> extraGroups = new List <ExtraGroup>();
                string[]          ogPanes     = _or.EnumeratePanes(_or.RootGroup).Select(x => ((Grp1Pane)x).GroupName).ToArray();
                var edPanes = _ed.EnumeratePanes(_ed.RootGroup).Cast <Grp1Pane>();
                foreach (var p in edPanes)
                {
                    if (ogPanes.Contains(p.GroupName))
                    {
                        continue;
                    }
                    extraGroups.Add(new ExtraGroup()
                    {
                        GroupName = p.GroupName, Panes = p.Panes.ToArray()
                    });
                    hasAtLeastAnExtraGroup = true;
                }
                if (extraGroups.Count == 0)
                {
                    extraGroups = null;
                }

                List <MaterialPatch> materials = new List <MaterialPatch>();
                if (_ed.GetMat != null && _or.GetMat != null)
                {
                    var edMat = _ed.GetMat;
                    foreach (var orM in _or.GetMat.Materials)
                    {
                        var edM = edMat.Materials.Where(x => x.Name == orM.Name).FirstOrDefault();
                        if (edM == null)
                        {
                            continue;
                        }
                        if (edM.ForegroundColor == orM.ForegroundColor && edM.BackgroundColor == orM.BackgroundColor)
                        {
                            continue;
                        }
                        MaterialPatch m = new MaterialPatch()
                        {
                            MaterialName = orM.Name
                        };
                        if (edM.ForegroundColor != orM.ForegroundColor)
                        {
                            m.ForegroundColor = edM.ForegroundColor.AsHexLEString();
                        }
                        if (edM.BackgroundColor != orM.BackgroundColor)
                        {
                            m.BackgroundColor = edM.BackgroundColor.AsHexLEString();
                        }
                        materials.Add(m);
                    }
                }
                if (materials.Count == 0)
                {
                    materials = null;
                }

                if (curFile.Count > 0 || extraGroups?.Count > 0 || materials?.Count > 0)
                {
                    Patches.Add(new LayoutFilePatch()
                    {
                        FileName = f, Patches = curFile.ToArray(), Materials = materials?.ToArray(), AddGroups = extraGroups?.ToArray()
                    });
                }
            }
            if (Patches.Count == 0)             //animation edits depend on bflyt changes so this is relevant
            {
                throw new Exception("Couldn't find any difference");
            }

            string Message = null;

            List <AnimFilePatch> AnimPatches = new List <AnimFilePatch>();

            foreach (var f in original.Files.Keys.Where(x => x.EndsWith(".bflan")))
            {
                if (original.Files[f].SequenceEqual(edited.Files[f]))
                {
                    continue;
                }
                BflanFile anim = new BflanFile(edited.Files[f]);
                AnimPatches.Add(new AnimFilePatch()
                {
                    FileName = f, AnimJson = BflanSerializer.ToJson(anim)
                });
            }
            if (AnimPatches.Count == 0)
            {
                AnimPatches = null;
            }
            else if (!hasAtLeastAnExtraGroup)
            {
                Message = "This theme uses custom animations but doesn't have custom group in the layouts, this means that the nxtheme will work on the firmware it has been developed on but it may break on older or newer ones. It's *highly recommended* to create custom groups to handle animations";
            }

            var targetPatch = SzsPatcher.DetectSarc(original, DefaultTemplates.templates);

            return(new LayoutPatch()
            {
                PatchName = "diffPatch" + (targetPatch == null ? "" : " for " + targetPatch.TemplateName),
                TargetName = targetPatch?.szsName,
                AuthorName = "autoDiff",
                Files = Patches.ToArray(),
                Anims = AnimPatches?.ToArray(),
                ID = $"Generated_{Guid.NewGuid()}"
            }, Message);
        }