Skip to content

Instantly share code, notes, and snippets.

@andybak
Last active July 28, 2024 11:43
Show Gist options
  • Save andybak/07d372884fec99f6d8785ba677d2fa2d to your computer and use it in GitHub Desktop.
Save andybak/07d372884fec99f6d8785ba677d2fa2d to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
using Unity.Mathematics;
using Unity.VectorGraphics;
using UnityEngine;
using UnityEngine.Splines;
public class SplineTest : MonoBehaviour
{
public string svgPath;
[Multiline(16)]
public string rawSvg;
public string Id;
public List<int> childIndices;
public Vector3 translation = Vector3.zero;
public Vector3 rotation = Vector3.zero;
public Vector3 scale = new (1, -1, 1);
public Vector3 translateEach = Vector3.zero;
public Vector3 rotateEach = Vector3.zero;
public Vector3 scaleEach = new (1, 1, 1);
void Start()
{
Generate();
}
private string _GetNodeInfo(SceneNode node)
{
return $"{node.Children?.Count ?? 0} children. {node.Shapes?.Count ?? 0} shapes.";
}
[ContextMenu("Generate")]
void Generate()
{
var importer = new RuntimeSVGImporter();
string svg;
if (!string.IsNullOrEmpty(svgPath))
{
svg = System.IO.File.ReadAllText(svgPath);
}
else
{
svg = rawSvg;
}
SVGParser.SceneInfo sceneInfo = importer.ParseToSceneInfo(svg);
if (!string.IsNullOrEmpty(Id))
{
// Extract a node by it's id
sceneInfo = sceneInfo.FromNodeId(Id);
}
else if (childIndices != null && childIndices.Count > 0)
{
foreach (var index in childIndices)
{
sceneInfo = sceneInfo.FromChildIndex(index);
}
}
var scene = sceneInfo.Scene;
int numChildren = scene.Root.Children?.Count ?? 0;
// // Some useful debugging info
// for (var i = 0; i < numChildren; i++)
// {
// var child = scene.Root.Children[i];
// Debug.Log($"Child {i}: {_GetNodeInfo(child)}");
// }
// foreach (var id in sceneInfo.NodeIDs)
// {
// Debug.Log($"NodeIDs: {id.Key}: {_GetNodeInfo(id.Value)}");
// }
// foreach (var opacity in sceneInfo.NodeOpacity)
// {
// Debug.Log($"NodeOpacity: {opacity.Key}: {opacity.Value}");
// }
int numShapes = scene.Root.Shapes?.Count ?? 0;
bool singleNode = numChildren == 0 && numShapes > 0;
int numMeshes = singleNode ? 1 : numChildren;
CombineInstance[] combine = new CombineInstance[numMeshes];
var tr = Matrix4x4.TRS(
translation,
Quaternion.Euler(rotation),
scale
);
var splineContainer = gameObject.GetComponent<SplineContainer>();
for (var i = 0; i < splineContainer.Splines.Count; i++)
{
splineContainer.RemoveSplineAt(i);
}
for (var i = 0; i < numMeshes; i++)
{
tr *= Matrix4x4.TRS(
translateEach,
Quaternion.Euler(rotateEach),
scaleEach
);
// Edge case - a single node with shapes but no children
SVGParser.SceneInfo newSceneInfo = sceneInfo;
// Common case - a node with children
if (!singleNode)
{
newSceneInfo = sceneInfo.FromChildIndex(i);
}
var shapes = newSceneInfo.Scene.Root.Shapes;
if (shapes != null)
{
foreach (var shape in shapes)
{
foreach (var contour in shape.Contours)
{
var spline = new Spline();
spline.Closed = contour.Closed;
int numSegments = contour.Segments.Length;
for (int idx = 0; idx < numSegments; idx++)
{
int prevIdx = (int)Mathf.Repeat(idx - 1, numSegments);
Debug.Log($"m: {numSegments} i: {idx} i-1: {prevIdx}");
var prevSeg = contour.Segments[prevIdx];
var seg = contour.Segments[idx];
float3 p0 = tr.MultiplyPoint3x4(new float3(seg.P0.x, seg.P0.y, 0));
float3 p1 = tr.MultiplyPoint3x4(new float3(prevSeg.P2.x, prevSeg.P2.y, 0));
float3 p2 = tr.MultiplyPoint3x4(new float3(seg.P1.x, seg.P1.y, 0));
BezierKnot knot = new BezierKnot(p0, p1 - p0, p2 - p0);
spline.Add(knot);
}
splineContainer.AddSpline(spline);
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment