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()); }
// 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()); }
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}"); }