Beispiel #1
0
        private void Add(PSB psb)
        {
            //add `easing`
            if (!psb.Objects.ContainsKey("easing"))
            {
                psb.Objects.Add("easing", new PsbCollection(0));
            }

            //add `/object/*/motion/*/bounds`
            //add `/object/*/motion/*/layerIndexMap`
            var obj = (PsbDictionary)psb.Objects["object"];

            foreach (var o in obj)
            {
                //var name = o.Key;
                foreach (var m in (PsbDictionary)((PsbDictionary)o.Value)["motion"])
                {
                    if (m.Value is PsbDictionary mDic)
                    {
                        if (!mDic.ContainsKey("bounds"))
                        {
                            var bounds = new PsbDictionary(4)
                            {
                                { "top", PsbNumber.Zero },
                                { "left", PsbNumber.Zero },
                                { "right", PsbNumber.Zero },
                                { "bottom", PsbNumber.Zero }
                            };
                            mDic.Add("bounds", bounds);
                        }


                        if (!(mDic["layer"] is PsbCollection col))
                        {
                            continue;
                        }

                        if (!mDic.ContainsKey("layerIndexMap"))
                        {
                            var layerIndexList = new List <string>();
                            LayerTravel(col, layerIndexList);
                            var layerIndexMap = new PsbDictionary(layerIndexList.Count);
                            int index         = 0;
                            foreach (var layerName in layerIndexList)
                            {
                                if (layerIndexMap.ContainsKey(layerName))
                                {
                                    continue;
                                }
                                layerIndexMap.Add(layerName, new PsbNumber(index));
                                index++;
                            }
                            mDic.Add("layerIndexMap", layerIndexMap);
                        }
                    }
                }
            }

            void LayerTravel(PsbCollection collection, List <string> indexList)
            {
                foreach (var col in collection)
                {
                    if (col is PsbDictionary dic && dic.ContainsKey("children"))
                    {
                        if (dic["label"] is PsbString str)
                        {
                            indexList.Add(str.Value);
                        }
                        if (dic["children"] is PsbCollection childrenCollection)
                        {
                            LayerTravel(childrenCollection, indexList);
                        }
                    }
                }
            }
        }
Beispiel #2
0
        internal IPsbValue ConvertToken(JToken token, Dictionary <string, PsbString> context)
        {
            switch (token.Type)
            {
            case JTokenType.Null:
                return(PsbNull.Null);

            case JTokenType.Integer:
                var l = token.Value <long>();
                if (l > Int32.MaxValue || l < Int32.MinValue)
                {
                    return(new PsbNumber(l));
                }
                return(new PsbNumber(token.Value <int>()));

            case JTokenType.Float:
                //var numberStr = token.Value<string>();
                var d = token.Value <double>();
                if (UseDoubleOnly)
                {
                    return(new PsbNumber(d));
                }
                var f = token.Value <float>();
                if (Math.Abs(f - d) < 1E-08)     //float //pcc: 1E-05
                //if (Math.Abs(f - d) < float.Epsilon)
                {
                    return(new PsbNumber(f));
                }
                //if (d < float.MaxValue && d > float.MinValue)
                //{
                //    return new PsbNumber(token.Value<float>());
                //}
                return(new PsbNumber(d));

            case JTokenType.Boolean:
                return(new PsbBool(token.Value <bool>()));

            case JTokenType.String:
                string str = token.Value <string>();
                if (str.StartsWith(Consts.NumberStringPrefix))
                {
                    var prefixLen = Consts.NumberStringPrefix.Length;
                    if (str.EndsWith("f"))
                    {
                        return(new PsbNumber(int.Parse(str.Substring(prefixLen, 8), NumberStyles.AllowHexSpecifier))
                        {
                            NumberType = PsbNumberType.Float
                        });
                    }
                    if (str.EndsWith("d"))
                    {
                        return(new PsbNumber(long.Parse(str.Substring(prefixLen, 16), NumberStyles.AllowHexSpecifier))
                        {
                            NumberType = PsbNumberType.Double
                        });
                    }
                    return(new PsbNumber(long.Parse(str.Substring(prefixLen), NumberStyles.AllowHexSpecifier)));
                }
                if (str.StartsWith(Consts.ResourceIdentifier))
                {
                    return(new PsbResource(uint.Parse(str.Replace(Consts.ResourceIdentifier, ""))));
                }
                var psbStr = new PsbString(str, (uint)context.Count);
                if (context.ContainsKey(str))
                {
                    return(context[str]);
                }
                else
                {
                    context.Add(str, psbStr);
                }
                return(psbStr);

            case JTokenType.Array:
                var array      = (JArray)token;
                var collection = new PsbList(array.Count);
                foreach (var val in array)
                {
                    var o = ConvertToken(val, context);
                    if (o is IPsbChild c)
                    {
                        c.Parent = collection;
                    }
                    if (o is IPsbSingleton s)
                    {
                        s.Parents.Add(collection);
                    }
                    collection.Add(o);
                }
                return(collection);

            case JTokenType.Object:
                var obj        = (JObject)token;
                var dictionary = new PsbDictionary(obj.Count);
                foreach (var val in obj)
                {
                    var o = ConvertToken(val.Value, context);
                    if (o is IPsbChild c)
                    {
                        c.Parent = dictionary;
                    }
                    if (o is IPsbSingleton s)
                    {
                        s.Parents.Add(dictionary);
                    }
                    dictionary.Add(val.Key, o);
                }
                return(dictionary);

            default:
                throw new FormatException("Unsupported json element");
            }
        }
Beispiel #3
0
        private Dictionary <string, (string Tex, string IconName)> TranslateResources(PSB psb)
        {
            Dictionary <string, (string Tex, string IconName)> iconInfos = new Dictionary <string, (string, string)>();
            Dictionary <string, Image> textures = new Dictionary <string, Image>();
            var  source        = (PsbDictionary)psb.Objects["source"];
            int  maxSideLength = 2048;
            long area          = 0;

            //Collect textures
            foreach (var tex in source)
            {
                var texName = tex.Key;
                var icons   = (PsbDictionary)((PsbDictionary)tex.Value)["icon"];
                foreach (var icon in icons)
                {
                    var iconName = icon.Key;
                    var info     = (PsbDictionary)icon.Value;
                    var width    = (int)(PsbNumber)info["width"];
                    var height   = (int)(PsbNumber)info["height"];
                    var res      = (PsbResource)info["pixel"];
                    var bmp      = info["compress"]?.ToString().ToUpperInvariant() == "RL"
                        ? RL.DecompressToImage(res.Data, height, width, psb.Platform.DefaultPixelFormat())
                        : RL.ConvertToImage(res.Data, height, width, psb.Platform.DefaultPixelFormat());
                    bmp.Tag = iconName;
                    textures.Add($"{texName}{Delimiter}{icon.Key}", bmp);
                    //estimate area and side length
                    area += width * height;
                    if (width >= maxSideLength || height >= maxSideLength)
                    {
                        maxSideLength = 4096;
                    }
                }
            }

            //Pack textures
            int size = 2048;

            if (maxSideLength > size || (area > 2048 * 2048 && psb.Header.Version > 2))
            {
                size = 4096;
            }
            int padding = TexturePadding >= 0 && TexturePadding <= 100 ? TexturePadding : 1;

            TexturePacker packer = new TexturePacker
            {
                FitHeuristic = FitHeuristic
            };

            packer.Process(textures, TextureSideLength ?? size, padding);

            //Add packed textures to source
            List <PsbDictionary> texs = new List <PsbDictionary>();

            for (var i = 0; i < packer.Atlasses.Count; i++)
            {
                var atlas = packer.Atlasses[i];
                var data  = UseRL
                    ? RL.CompressImage((Bitmap)atlas.ToImage(), TargetPixelFormat)
                    : RL.GetPixelBytesFromImage(atlas.ToImage(), TargetPixelFormat);

                var texDic = new PsbDictionary(4);
                //metadata
                texDic.Add("metadata", new PsbString(i.ToString("D3")));
                var texName = $"tex#{texDic["metadata"]}";
                //icon
                var icons = new PsbDictionary(atlas.Nodes.Count);
                texDic.Add("icon", icons);
                int id = 0;
                foreach (var node in atlas.Nodes)
                {
                    if (node.Texture == null)
                    {
                        continue;
                    }
                    var paths = node.Texture.Source.Split(new[] { Delimiter }, StringSplitOptions.RemoveEmptyEntries);
                    var icon  = (PsbDictionary)source[paths[0]].Children("icon").Children(paths[1]);
                    icon.Remove("compress");
                    icon.Remove("pixel");
                    icon["attr"] = PsbNumber.Zero;
                    icon["left"] = new PsbNumber(node.Bounds.Left);
                    icon["top"]  = new PsbNumber(node.Bounds.Top);
                    icon.Parent  = icons;
                    var iconName = UseMeaningfulName ? node.Texture.Source : id.ToString();
                    icons.Add(iconName, icon);
                    iconInfos.Add(node.Texture.Source, (texName, iconName));
                    id++;
                }
                //texture
                //TODO: support truncated
                var texture = new PsbDictionary(6)
                {
                    { "height", new PsbNumber(atlas.Height) },
                    { "width", new PsbNumber(atlas.Width) },
                    { "truncated_height", new PsbNumber(atlas.Height) },
                    { "truncated_width", new PsbNumber(atlas.Width) },
                    { "type", new PsbString(TargetPixelFormat.ToStringForPsb()) }
                };
                texture.Add("pixel", new PsbResource {
                    Data = data, Parents = new List <IPsbCollection> {
                        texture
                    }
                });
                texDic.Add("texture", texture);
                //type
                texDic.Add("type", PsbNumber.Zero);

                texs.Add(texDic);
            }

            source.Clear();
            foreach (var t in texs)
            {
                source.Add($"tex#{t["metadata"]}", t);
                t["metadata"] = PsbNull.Null;
            }
            return(iconInfos);
        }
Beispiel #4
0
        internal IPsbValue ConvertToken(JToken token, List <PsbString> context)
        {
            switch (token.Type)
            {
            case JTokenType.Null:
                return(PsbNull.Null);

            case JTokenType.Integer:
                return(new PsbNumber(token.Value <int>()));

            case JTokenType.Float:
                var d = token.Value <double>();
                var f = token.Value <float>();
                if (Math.Abs(f - d) < 1E-05)     //float //pcc: 1E-05
                {
                    return(new PsbNumber(token.Value <float>()));
                }
                //if (d < float.MaxValue && d > float.MinValue)
                //{
                //    return new PsbNumber(token.Value<float>());
                //}
                return(new PsbNumber(d));

            case JTokenType.Boolean:
                return(new PsbBool(token.Value <bool>()));

            case JTokenType.String:
                string str = token.Value <string>();
                if (str.StartsWith(PsbResCollector.ResourceIdentifier))
                {
                    return(new PsbResource(uint.Parse(str.Replace(PsbResCollector.ResourceIdentifier, ""))));
                }
                var psbStr = new PsbString(str, (uint)context.Count);
                if (context.Contains(psbStr))
                {
                    return(context.Find(ps => ps.Value == str));
                }
                else
                {
                    context.Add(psbStr);
                }
                return(psbStr);

            case JTokenType.Array:
                var array      = (JArray)token;
                var collection = new PsbCollection(array.Count);
                foreach (var val in array)
                {
                    var o = ConvertToken(val, context);
                    if (o is IPsbChild c)
                    {
                        c.Parent = collection;
                    }
                    if (o is IPsbSingleton s)
                    {
                        s.Parents.Add(collection);
                    }
                    collection.Add(o);
                }
                return(collection);

            case JTokenType.Object:
                var obj        = (JObject)token;
                var dictionary = new PsbDictionary(obj.Count);
                foreach (var val in obj)
                {
                    var o = ConvertToken(val.Value, context);
                    if (o is IPsbChild c)
                    {
                        c.Parent = dictionary;
                    }
                    if (o is IPsbSingleton s)
                    {
                        s.Parents.Add(dictionary);
                    }
                    dictionary.Add(val.Key, o);
                }
                return(dictionary);

            default:
                throw new FormatException("Unsupported json element");
            }
        }