public (IComponent[], IAsset[]) Render(XdObjectJson xdObject, XdAssetHolder assetHolder, IObbGetter obbGetter)
        {
            var components = new List <IComponent>();
            var assets     = new List <IAsset>();

            var color = xdObject.GetFillUnityColor();
            var svg   = SvgUtil.CreateSvg(xdObject);

            xdObject.Group.Children = new XdObjectJson[] { };

            var size      = obbGetter.Get(xdObject).Size;
            var spriteUid = $"{xdObject.GetSimpleName()}_{xdObject.Id.Substring(0, 8)}.png";
            var svgHash   = FastHash.CalculateHash(svg);

            var cachedSvg = assetHolder.GetCachedSvg(svgHash);

            if (cachedSvg != null)
            {
                spriteUid = cachedSvg.SpriteUid;
            }
            else
            {
                assets.Add(new SpriteAsset(spriteUid, svgHash, size, null, null));
                var xdImportSettings = XdImporter.Settings;
                assetHolder.Save(spriteUid, () => SvgToPng.Convert(svg, size, xdImportSettings));
                assetHolder.SaveCacheSvg(spriteUid, svgHash);
            }
            components.Add(new ImageComponent(
                               spriteUid,
                               new Color(1f, 1f, 1f, color.a),
                               Vector2Int.one
                               ));

            return(components.ToArray(), assets.ToArray());
        }
Beispiel #2
0
            // Renderは親から子供の順番
            private IElement[] Render(XdObjectJson xdObject, [CanBeNull] Obb parent)
            {
                var eid = _nextEid;

                _nextEid++;

                var originalObb = _obbHolder.Get(xdObject);
                var obb         = originalObb.CalcObbInWorld(parent);
                var position    = obb.CalcLocalRect().center - (parent?.Size ?? Vector2.zero) / 2f;
                var size        = obb.Size;
                var anchorX     = AnchorXType.Center;
                var anchorY     = AnchorYType.Middle;
                var rotation    = obb.Rotation;

                if (Mathf.Abs(rotation) < 0.0001f)
                {
                    rotation = 0f;
                }
                var constRight = xdObject.Meta.Ux.ConstraintRight;
                var constLeft  = xdObject.Meta.Ux.ConstraintLeft;

                if (constRight && constLeft)
                {
                    anchorX = AnchorXType.Stretch;
                }
                else if (constRight)
                {
                    anchorX = AnchorXType.Right;
                }
                else if (constLeft)
                {
                    anchorX = AnchorXType.Left;
                }

                var constTop    = xdObject.Meta.Ux.ConstraintTop;
                var constBottom = xdObject.Meta.Ux.ConstraintBottom;

                if (constTop && constBottom)
                {
                    anchorY = AnchorYType.Stretch;
                }
                else if (constTop)
                {
                    anchorY = AnchorYType.Top;
                }
                else if (constBottom)
                {
                    anchorY = AnchorYType.Bottom;
                }

                foreach (var parser in _objectParsers)
                {
                    if (!parser.Is(xdObject))
                    {
                        continue;
                    }
                    var(components, assets) = parser.Render(xdObject, obb, _xdAssetHolder);

                    var children = new IElement[] { };
                    if (xdObject.Group != null)
                    {
                        children = Render(xdObject.Group.Children, originalObb);
                    }

                    var element = new ObjectElement(
                        eid,
                        xdObject.GetSimpleName(),
                        position,
                        size,
                        anchorX,
                        anchorY,
                        rotation,
                        xdObject.Visible ?? true,
                        components,
                        children.Select(x => x.Eid).ToArray()
                        );

                    foreach (var asset in assets)
                    {
                        if (Assets.Any(x => x.FileName == asset.FileName))
                        {
                            continue;
                        }
                        Assets.Add(asset);
                    }

                    Elements.Add(element);
                    return(new IElement[] { element });
                }

                if (xdObject.Type == "group")
                {
                    var components = new List <IComponent>();
                    foreach (var parser in _groupParsers)
                    {
                        if (!parser.Is(xdObject))
                        {
                            continue;
                        }
                        var(c, assets) = parser.Render(xdObject, _xdAssetHolder, _obbHolder);
                        components.AddRange(c);

                        foreach (var asset in assets)
                        {
                            if (Assets.Any(x => x.FileName == asset.FileName))
                            {
                                continue;
                            }
                            Assets.Add(asset);
                        }

                        break;
                    }

                    var generatedChildren = new IElement[] { };
                    if (xdObject.Group != null)
                    {
                        generatedChildren = Render(xdObject.Group.Children, originalObb);
                    }

                    var group = new ObjectElement(
                        eid,
                        xdObject.GetSimpleName(),
                        position,
                        size,
                        anchorX,
                        anchorY,
                        rotation,
                        xdObject.Visible ?? true,
                        components.ToArray(),
                        generatedChildren.Select(x => x.Eid).ToArray()
                        );

                    Elements.Add(group);
                    return(new IElement[] { group });
                }

                throw new Exception($"Unknown object type {xdObject.Type}");
            }
        public static (ImageComponent, IAsset[]) RenderImage(XdObjectJson xdObject, Obb obb, XdAssetHolder assetHolder)
        {
            ImageComponent imageComponent = null;
            SpriteAsset    asset          = null;

            var color     = xdObject.GetFillUnityColor();
            var ux        = xdObject.Style?.Fill?.Pattern?.Meta?.Ux;
            var flipX     = ux?.FlipX ?? false;
            var flipY     = ux?.FlipY ?? false;
            var direction = new Vector2Int(flipX ? -1 : 1, flipY ? -1 : 1);
            var shapeType = xdObject.Shape?.Type;

            if (!string.IsNullOrWhiteSpace(ux?.Uid))
            {
                var spriteUid = $"{xdObject.GetSimpleName()}_{ux?.Uid.Substring(0, 8)}.png";
                asset          = new SpriteAsset(spriteUid, xdObject.Style.Fill.Pattern.Meta.Ux.HrefLastModifiedDate, obb.Size, null, null);
                imageComponent = new ImageComponent(
                    spriteUid,
                    color,
                    direction
                    );
                assetHolder.Save(spriteUid, xdObject.Style.Fill.Pattern.Meta);
            }
            else if (SvgUtil.Types.Contains(shapeType))
            {
                var spriteUid = $"{xdObject.GetSimpleName()}_{xdObject.Id.Substring(0, 8)}.png";
                var svg       = SvgUtil.CreateSvg(xdObject);
                var svgHash   = FastHash.CalculateHash(svg);

                var cachedSvg = assetHolder.GetCachedSvg(svgHash);
                if (cachedSvg != null)
                {
                    spriteUid = cachedSvg.SpriteUid;
                }
                else
                {
                    asset = new SpriteAsset(spriteUid, svgHash, obb.Size, null, null);
                    var xdImportSettings = XdImporter.Settings;
                    assetHolder.Save(spriteUid, () => SvgToPng.Convert(svg, obb.Size, xdImportSettings));
                    assetHolder.SaveCacheSvg(spriteUid, svgHash);
                }

                imageComponent = new ImageComponent(
                    spriteUid,
                    new Color(1f, 1f, 1f, color.a),
                    direction
                    );
            }
            else
            {
                Debug.LogError($"Unknown shape type {shapeType} in {xdObject.Name}({xdObject.Id}, {xdObject.Guid})");
            }

            var assets = new List <IAsset>();

            if (!xdObject.HasParameter("placeholder") && asset != null)
            {
                assets.Add(asset);
            }
            return(imageComponent, assets.ToArray());
        }
Beispiel #4
0
        private static IElement CreateSvgLine(XdObjectJson xdObject, List <IDefElement> defs)
        {
            var id       = xdObject.GetSimpleName().Replace(" ", "_");
            var dataName = xdObject.GetSimpleName();
            var shape    = xdObject.Shape;

            var parameter = new ElementParameter
            {
                Id = id
            };

            parameter.Transform = new Transform {
                Value = xdObject.Transform
            };

            var opacity = xdObject.Style?.Opacity;

            parameter.Opacity = opacity;

            if (xdObject.Group != null)
            {
                if (MaskGroupParser.Is(xdObject))
                {
                    var clipPathId = $"clip-path{defs.Count}";
                    parameter.ClipPath = $"url(#{clipPathId})";
                    var clipPathChildren = xdObject.Meta.Ux.ClipPathResources.Children.Select(x => CreateSvgLine(x, defs));
                    defs.Add(new ClipPathDefElement {
                        Id = clipPathId, Children = clipPathChildren.ToArray()
                    });
                }

                parameter.DataName = dataName;
                var blendMode = xdObject.Style?.BlendMode;
                var isolation = xdObject.Style?.Isolation;
                var children  = xdObject.Group.Children.Select(x => CreateSvgLine(x, defs)).ToArray();
                return(new GroupElement {
                    Parameter = parameter, Children = children, BlendMode = blendMode, Isolation = isolation
                });
            }

            XdStyleFillPatternJson image = null;
            var fill = xdObject.Style?.Fill;

            parameter.EnableFill = true;
            if (fill != null && fill.Type != "none")
            {
                var color = xdObject.Style.Fill.ToUnityColor();
                parameter.Fill = color;

                if (fill.Type == "solid" || fill.Type == "gradient")
                {
                    // nothing to do
                    // gradientはサポートしていないが、知らないタイプというわけではないのでスルー
                }
                else if (fill.Type == "pattern")
                {
                    image          = fill.Pattern;
                    parameter.Fill = null;
                }
                else
                {
                    Debug.LogWarning($"Unknown fill type {fill.Type} in {xdObject.Name}");
                }

                if (!string.IsNullOrWhiteSpace(shape.Winding))
                {
                    parameter.FillRule = shape.Winding;
                }
            }

            float?shapeR = null;

            if (shape.R != null)
            {
                if (shape.R is List <object> list)
                {
                    shapeR = (float)(double)list[0];
                }
                else if (shape.R is double d)
                {
                    shapeR = (float)d;
                }
                else
                {
                    throw new NotSupportedException($"Unknown shape.r type {shape.R.GetType()}");
                }
            }

            if (shapeR != null && shape.Type != CircleElement.Name)
            {
                parameter.Rx = shapeR;
                if (parameter.Rx > shape.Width / 2f)
                {
                    parameter.Rx = shape.Width / 2f;
                }
                if (parameter.Rx > shape.Height / 2f)
                {
                    parameter.Rx = shape.Height / 2f;
                }
            }

            var    stroke      = xdObject.Style?.Stroke;
            string strokeAlign = null;

            if (stroke != null && stroke.Type != "none")
            {
                parameter.EnableStroke     = true;
                parameter.Stroke           = stroke.ToUnityColor();
                parameter.StrokeWidth      = stroke.Width;
                parameter.StrokeMiterLimit = stroke.MiterLimit;

                if (!string.IsNullOrWhiteSpace(stroke.Join))
                {
                    parameter.StrokeLinejoin = stroke.Join;
                }

                if (!string.IsNullOrWhiteSpace(stroke.Cap))
                {
                    parameter.StrokeLinecap = stroke.Cap;
                }

                if (stroke.Dash != null)
                {
                    parameter.StrokeDasharray = stroke.Dash;
                }

                if (stroke.Align == null)
                {
                    strokeAlign = null;
                }
                else if (stroke.Align == "outside")
                {
                    strokeAlign = "outside";
                }
                else if (stroke.Align == "inside")
                {
                    strokeAlign = "inside";
                }
                else
                {
                    throw new NotSupportedException($"{xdObject} has unknown align type {stroke.Align}");
                }
            }

            if (image != null)
            {
                var imageBytes = XdImporter.XdFile.GetResource(fill.Pattern.Meta);
                return(new ImageElement {
                    Parameter = parameter, ImageBytes = imageBytes, Width = shape.Width, Height = shape.Height
                });
            }

            if (shape.Type == PathElement.Name)
            {
                return new PathElement {
                           Parameter = parameter, D = shape.Path
                }
            }
            ;

            if (shape.Type == CompoundElement.Name)
            {
                return new CompoundElement {
                           Parameter = parameter, D = shape.Path
                }
            }
            ;

            if (shape.Type == LineElement.Name)
            {
                return new LineElement {
                           Parameter = parameter, X1 = shape.X1, Y1 = shape.Y1, X2 = shape.X2, Y2 = shape.Y2
                }
            }
            ;

            if (shape.Type == RectElement.Name)
            {
                if (strokeAlign == "outside")
                {
                    return(RectElement.Outside(shape, parameter));
                }
                if (strokeAlign == "inside")
                {
                    return(RectElement.Inside(shape, parameter));
                }
                return(new RectElement {
                    Parameter = parameter, Width = shape.Width, Height = shape.Height
                });
            }

            if (shape.Type == CircleElement.Name)
            {
                if (strokeAlign == "outside")
                {
                    return(CircleElement.Outside(shape, parameter, shapeR));
                }
                if (strokeAlign == "inside")
                {
                    return(CircleElement.Inside(shape, parameter, shapeR));
                }
                return(new CircleElement {
                    Parameter = parameter, Cx = shape.Cx, Cy = shape.Cy, R = shapeR.Value
                });
            }

            if (shape.Type == EllipseElement.Name)
            {
                if (strokeAlign == "outside")
                {
                    return(EllipseElement.Outside(shape, parameter));
                }
                if (strokeAlign == "inside")
                {
                    return(EllipseElement.Inside(shape, parameter));
                }
                return(new EllipseElement {
                    Parameter = parameter, Cx = shape.Cx, Cy = shape.Cy, Rx = shape.Rx, Ry = shape.Ry
                });
            }

            throw new NotSupportedException($"Unknown type {shape.Type}");
        }