├── Assets ├── Editor.meta ├── Editor │ ├── BezierCurveEditor.cs │ ├── BezierCurveEditor.cs.meta │ ├── ControlPointEditor.cs │ ├── ControlPointEditor.cs.meta │ ├── SplineEditor.cs │ ├── SplineEditor.cs.meta │ ├── SplineMenu.cs │ └── SplineMenu.cs.meta ├── Meshes.meta ├── Meshes │ ├── sun-dial-arrow.fbx │ └── sun-dial-arrow.fbx.meta ├── Resources.meta ├── Resources │ ├── Gizmos.meta │ ├── Gizmos │ │ ├── PlusSign.png │ │ ├── PlusSign.png.meta │ │ ├── Triangle.png │ │ └── Triangle.png.meta │ ├── Prefabs.meta │ ├── Prefabs │ │ ├── BezierCurve.prefab │ │ ├── BezierCurve.prefab.meta │ │ ├── Spline.prefab │ │ └── Spline.prefab.meta │ ├── Scripts.meta │ └── Scripts │ │ ├── BezierCurve.cs │ │ ├── BezierCurve.cs.meta │ │ ├── ControlPoint.cs │ │ ├── ControlPoint.cs.meta │ │ ├── GuideLine.cs │ │ ├── GuideLine.cs.meta │ │ ├── SVGHandler.cs │ │ ├── SVGHandler.cs.meta │ │ ├── Spline.cs │ │ ├── Spline.cs.meta │ │ ├── SplineAnimation.cs │ │ ├── SplineAnimation.cs.meta │ │ ├── SplineGenerator.cs │ │ ├── SplineGenerator.cs.meta │ │ ├── SplineGizmos.cs │ │ ├── SplineGizmos.cs.meta │ │ ├── UTIL.cs │ │ └── UTIL.cs.meta ├── SVGs.meta ├── SVGs │ ├── ash_tree.svg │ ├── ash_tree.svg.meta │ ├── avengers.svg │ ├── avengers.svg.meta │ ├── disney_and_mickey.svg │ ├── disney_and_mickey.svg.meta │ ├── floral_design.svg │ ├── floral_design.svg.meta │ ├── fox_head.svg │ ├── fox_head.svg.meta │ ├── gnu_logo.svg │ ├── gnu_logo.svg.meta │ ├── nz_flag.svg │ ├── nz_flag.svg.meta │ ├── palm_tree.svg │ ├── palm_tree.svg.meta │ ├── tower_bridge.svg │ ├── tower_bridge.svg.meta │ ├── uk_map.svg │ ├── uk_map.svg.meta │ ├── welsh_dragon.svg │ └── welsh_dragon.svg.meta ├── Scenes.meta └── Scenes │ ├── Demo.unity │ └── Demo.unity.meta ├── Images ├── DisneySpline.gif ├── Floral_Design.png ├── GNU_Logo.png ├── SplineDemo1.gif ├── SplineEditorDemo1.png └── SplineEditorDemo2.png ├── LICENSE ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset └── UnityConnectSettings.asset └── README.md /Assets/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26c790e2f87dc4b3097626421c0f1a8d 3 | folderAsset: yes 4 | timeCreated: 1513543228 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Editor/BezierCurveEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | [CustomEditor(typeof(BezierCurve))] 7 | public class BezierCurveEditor : Editor 8 | { 9 | public void OnEnable() 10 | { 11 | 12 | } 13 | 14 | public override void OnInspectorGUI() 15 | { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Assets/Editor/BezierCurveEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b59dadf60e49e406f8c16031dc263ebe 3 | timeCreated: 1504659664 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/ControlPointEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | [CustomEditor(typeof(ControlPoint))] 7 | public class ControlPointEditor : Editor 8 | { 9 | private SerializedProperty _type; 10 | 11 | ControlPoint controlPoint; 12 | 13 | public void OnEnable() 14 | { 15 | SerializedObject cp = new SerializedObject(target); 16 | 17 | _type = cp.FindProperty("Type"); 18 | } 19 | 20 | public override void OnInspectorGUI() 21 | { 22 | EditorGUILayout.PropertyField(_type); 23 | } 24 | 25 | void OnDisable() 26 | { 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Assets/Editor/ControlPointEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 85d8bce8e15964eeab9496ae6341a6ee 3 | timeCreated: 1513643404 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/SplineEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | [CustomEditor(typeof(Spline))] 7 | public class SplineEditor : Editor 8 | { 9 | private SerializedObject _spline; 10 | private SerializedProperty __numSubDivisions; 11 | private SerializedProperty _numSubDivisions; 12 | 13 | Spline spline; 14 | 15 | public void OnEnable() 16 | { 17 | _spline = new SerializedObject(target); 18 | 19 | spline = (Spline)target; 20 | 21 | _numSubDivisions = _spline.FindProperty("NumSubDivisions"); 22 | __numSubDivisions = _numSubDivisions; 23 | } 24 | 25 | public override void OnInspectorGUI() 26 | { 27 | EditorGUILayout.PropertyField(_numSubDivisions); 28 | 29 | _spline.ApplyModifiedProperties(); 30 | 31 | if (SerializedProperty.EqualContents(_numSubDivisions, __numSubDivisions)) 32 | { 33 | __numSubDivisions = _numSubDivisions; 34 | spline = (Spline)target; 35 | spline.UpdateNumberSubDivisions(); 36 | } 37 | 38 | //DrawDefaultInspector(); 39 | 40 | if (GUILayout.Button("Add Point")) 41 | { 42 | Spline spline = (Spline)target; 43 | spline.AddPoint(false); 44 | } 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Assets/Editor/SplineEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0e5b5f085a49c40dea48bca398df9e3f 3 | timeCreated: 1504313418 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/SplineMenu.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | using UnityEditor.SceneManagement; 7 | 8 | public class SplineMenu : EditorWindow 9 | { 10 | Object fileSource; 11 | bool toggleSVG; 12 | 13 | [SerializeField] 14 | private GameObject _splinePrefab; 15 | GameObject splinePrefab 16 | { 17 | get 18 | { 19 | if (_splinePrefab == null) 20 | _splinePrefab = (GameObject)Resources.Load("Prefabs/Spline", typeof(GameObject)); 21 | 22 | return _splinePrefab; 23 | } 24 | } 25 | 26 | [SerializeField] 27 | static string svgName; 28 | 29 | [MenuItem ("Window/Spline Editor")] 30 | public static void Init() 31 | { 32 | SplineMenu window = GetWindow(); 33 | window.titleContent.text = "Spline Editor"; 34 | } 35 | 36 | void OnGUI() 37 | { 38 | EditorGUILayout.BeginVertical(); 39 | 40 | GUILayout.Space(10); 41 | 42 | GUILayout.Label("Add a new Spline to your scene"); 43 | 44 | GUILayout.Space(10); 45 | 46 | toggleSVG = EditorGUILayout.Toggle("Use SVG", toggleSVG); 47 | 48 | GUILayout.Space(5); 49 | 50 | fileSource = EditorGUILayout.ObjectField(fileSource, typeof(Object), false, GUILayout.Width(200)) as Object; 51 | 52 | GUILayout.Space(10); 53 | 54 | if (GUILayout.Button("New Spline", GUILayout.Width(200))) 55 | { 56 | if (toggleSVG) 57 | { 58 | if (fileSource != null) 59 | { 60 | SVGHandler.ConvertToSplines(AssetDatabase.GetAssetPath(fileSource)); 61 | } 62 | } 63 | else 64 | { 65 | Instantiate(splinePrefab); 66 | } 67 | 68 | EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); 69 | } 70 | 71 | EditorGUILayout.EndVertical(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Assets/Editor/SplineMenu.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4f1aadbe6f5024edbb31088375bb82b9 3 | timeCreated: 1513641185 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Meshes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 767d4ff0a4abf46f2a150a3ccf2905a0 3 | folderAsset: yes 4 | timeCreated: 1521064536 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Meshes/sun-dial-arrow.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Assets/Meshes/sun-dial-arrow.fbx -------------------------------------------------------------------------------- /Assets/Meshes/sun-dial-arrow.fbx.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8e4664d41f2ad420fa4a2954e9277f40 3 | timeCreated: 1521064520 4 | licenseType: Free 5 | ModelImporter: 6 | serializedVersion: 21 7 | fileIDToRecycleName: 8 | 100000: //RootNode 9 | 400000: //RootNode 10 | 2300000: //RootNode 11 | 3300000: //RootNode 12 | 4300000: Sundial-Arrow 13 | 9500000: //RootNode 14 | materials: 15 | importMaterials: 1 16 | materialName: 0 17 | materialSearch: 1 18 | animations: 19 | legacyGenerateAnimations: 4 20 | bakeSimulation: 0 21 | resampleCurves: 1 22 | optimizeGameObjects: 0 23 | motionNodeName: 24 | rigImportErrors: 25 | rigImportWarnings: 26 | animationImportErrors: 27 | animationImportWarnings: 28 | animationRetargetingWarnings: 29 | animationDoRetargetingWarnings: 0 30 | animationCompression: 1 31 | animationRotationError: 0.5 32 | animationPositionError: 0.5 33 | animationScaleError: 0.5 34 | animationWrapMode: 0 35 | extraExposedTransformPaths: [] 36 | extraUserProperties: [] 37 | clipAnimations: [] 38 | isReadable: 1 39 | meshes: 40 | lODScreenPercentages: [] 41 | globalScale: 1 42 | meshCompression: 0 43 | addColliders: 0 44 | importVisibility: 1 45 | importBlendShapes: 1 46 | importCameras: 1 47 | importLights: 1 48 | swapUVChannels: 0 49 | generateSecondaryUV: 0 50 | useFileUnits: 1 51 | optimizeMeshForGPU: 1 52 | keepQuads: 0 53 | weldVertices: 1 54 | secondaryUVAngleDistortion: 8 55 | secondaryUVAreaDistortion: 15.000001 56 | secondaryUVHardAngle: 88 57 | secondaryUVPackMargin: 4 58 | useFileScale: 1 59 | tangentSpace: 60 | normalSmoothAngle: 60 61 | normalImportMode: 0 62 | tangentImportMode: 3 63 | normalCalculationMode: 4 64 | importAnimation: 1 65 | copyAvatar: 0 66 | humanDescription: 67 | serializedVersion: 2 68 | human: [] 69 | skeleton: [] 70 | armTwist: 0.5 71 | foreArmTwist: 0.5 72 | upperLegTwist: 0.5 73 | legTwist: 0.5 74 | armStretch: 0.05 75 | legStretch: 0.05 76 | feetSpacing: 0 77 | rootMotionBoneName: 78 | rootMotionBoneRotation: {x: 0, y: 0, z: 0, w: 1} 79 | hasTranslationDoF: 0 80 | hasExtraRoot: 0 81 | skeletonHasParents: 1 82 | lastHumanDescriptionAvatarSource: {instanceID: 0} 83 | animationType: 2 84 | humanoidOversampling: 1 85 | additionalBone: 0 86 | userData: 87 | assetBundleName: 88 | assetBundleVariant: 89 | -------------------------------------------------------------------------------- /Assets/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3dad776ea82cd4120bcf0fcd80150799 3 | folderAsset: yes 4 | timeCreated: 1521169687 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Resources/Gizmos.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a5a15a8f0b71b41af9a200ca4c639d90 3 | folderAsset: yes 4 | timeCreated: 1504652506 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Resources/Gizmos/PlusSign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Assets/Resources/Gizmos/PlusSign.png -------------------------------------------------------------------------------- /Assets/Resources/Gizmos/PlusSign.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 75369ad5ed1f347bab9b4c0b85881ca7 3 | timeCreated: 1513805224 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapsPreserveCoverage: 0 16 | alphaTestReferenceValue: 0.5 17 | mipMapFadeDistanceStart: 1 18 | mipMapFadeDistanceEnd: 3 19 | bumpmap: 20 | convertToNormalMap: 0 21 | externalNormalMap: 0 22 | heightScale: 0.25 23 | normalMapFilter: 0 24 | isReadable: 0 25 | grayScaleToAlpha: 0 26 | generateCubemap: 6 27 | cubemapConvolution: 0 28 | seamlessCubemap: 0 29 | textureFormat: 1 30 | maxTextureSize: 2048 31 | textureSettings: 32 | serializedVersion: 2 33 | filterMode: -1 34 | aniso: -1 35 | mipBias: -1 36 | wrapU: 1 37 | wrapV: -1 38 | wrapW: -1 39 | nPOTScale: 0 40 | lightmap: 0 41 | compressionQuality: 50 42 | spriteMode: 1 43 | spriteExtrude: 1 44 | spriteMeshType: 1 45 | alignment: 0 46 | spritePivot: {x: 0.5, y: 0.5} 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spritePixelsToUnits: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 1 51 | spriteTessellationDetail: -1 52 | textureType: 8 53 | textureShape: 1 54 | maxTextureSizeSet: 0 55 | compressionQualitySet: 0 56 | textureFormatSet: 0 57 | platformSettings: 58 | - buildTarget: DefaultTexturePlatform 59 | maxTextureSize: 2048 60 | textureFormat: -1 61 | textureCompression: 1 62 | compressionQuality: 50 63 | crunchedCompression: 0 64 | allowsAlphaSplitting: 0 65 | overridden: 0 66 | - buildTarget: Standalone 67 | maxTextureSize: 2048 68 | textureFormat: -1 69 | textureCompression: 1 70 | compressionQuality: 50 71 | crunchedCompression: 0 72 | allowsAlphaSplitting: 0 73 | overridden: 0 74 | - buildTarget: iPhone 75 | maxTextureSize: 2048 76 | textureFormat: -1 77 | textureCompression: 1 78 | compressionQuality: 50 79 | crunchedCompression: 0 80 | allowsAlphaSplitting: 0 81 | overridden: 0 82 | - buildTarget: Android 83 | maxTextureSize: 2048 84 | textureFormat: -1 85 | textureCompression: 1 86 | compressionQuality: 50 87 | crunchedCompression: 0 88 | allowsAlphaSplitting: 0 89 | overridden: 0 90 | spriteSheet: 91 | serializedVersion: 2 92 | sprites: [] 93 | outline: [] 94 | physicsShape: [] 95 | spritePackingTag: 96 | userData: 97 | assetBundleName: 98 | assetBundleVariant: 99 | -------------------------------------------------------------------------------- /Assets/Resources/Gizmos/Triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Assets/Resources/Gizmos/Triangle.png -------------------------------------------------------------------------------- /Assets/Resources/Gizmos/Triangle.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 32317fe609ba24bf2ae146444e799639 3 | timeCreated: 1504652868 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: 1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 1 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 1 44 | alphaUsage: 1 45 | alphaIsTransparency: 1 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | - buildTarget: iPhone 70 | maxTextureSize: 2048 71 | textureFormat: -1 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 0 77 | - buildTarget: Android 78 | maxTextureSize: 2048 79 | textureFormat: -1 80 | textureCompression: 1 81 | compressionQuality: 50 82 | crunchedCompression: 0 83 | allowsAlphaSplitting: 0 84 | overridden: 0 85 | spriteSheet: 86 | serializedVersion: 2 87 | sprites: [] 88 | outline: [] 89 | spritePackingTag: 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Assets/Resources/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c599d8c9e590249fd92700b65b9ce0b1 3 | folderAsset: yes 4 | timeCreated: 1521169696 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Resources/Prefabs/BezierCurve.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Assets/Resources/Prefabs/BezierCurve.prefab -------------------------------------------------------------------------------- /Assets/Resources/Prefabs/BezierCurve.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 774bed179cdb04daa8b6c4d72493e54d 3 | timeCreated: 1504314447 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 100100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Resources/Prefabs/Spline.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Assets/Resources/Prefabs/Spline.prefab -------------------------------------------------------------------------------- /Assets/Resources/Prefabs/Spline.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5f5299fbd21344b5f92f4af45f3a287f 3 | timeCreated: 1521169585 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 100100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 247c7884a9d814d9e8873206b83875b0 3 | folderAsset: yes 4 | timeCreated: 1504232567 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/BezierCurve.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | [ExecuteInEditMode] 7 | [System.Serializable] 8 | public class BezierCurve : MonoBehaviour 9 | { 10 | public Transform p0; 11 | public Transform p1; 12 | public Transform p2; 13 | public Transform p3; 14 | 15 | [SerializeField] 16 | BezierCurve next; 17 | [SerializeField] 18 | BezierCurve prev; 19 | 20 | [SerializeField] 21 | private Transform _guideLine; 22 | Transform guideLine 23 | { 24 | get 25 | { 26 | if (_guideLine == null) 27 | { 28 | _guideLine = (new GameObject()).transform; 29 | _guideLine.SetParent(transform); 30 | _guideLine.hideFlags = HideFlags.HideInHierarchy; 31 | } 32 | 33 | return _guideLine; 34 | } 35 | 36 | set 37 | { 38 | _guideLine = value; 39 | } 40 | } 41 | 42 | [SerializeField] 43 | private List _guideLines; 44 | List guideLines 45 | { 46 | get 47 | { 48 | if (_guideLines == null) 49 | _guideLines = new List(); 50 | 51 | return _guideLines; 52 | } 53 | set 54 | { 55 | _guideLines = value; 56 | } 57 | } 58 | 59 | [SerializeField] 60 | float curveLength; 61 | 62 | public void Init(int numSubDivisions, Vector3 origin, bool atStart, Transform parent) 63 | { 64 | transform.SetParent(parent); 65 | gameObject.tag = "BezierCurve"; 66 | 67 | if (atStart) 68 | { 69 | p0.position = origin - Vector3.left * 3; 70 | p1.position = origin - Vector3.left * 2; 71 | p2.position = origin - Vector3.left * 1; 72 | p3.position = origin; 73 | } 74 | else 75 | { 76 | p0.position = origin; 77 | p1.position = origin + Vector3.left * 1; 78 | p2.position = origin + Vector3.left * 2; 79 | p3.position = origin + Vector3.left * 3; 80 | } 81 | 82 | UpdateNumberSubDivisions(numSubDivisions); 83 | } 84 | 85 | public void Init(int divisions, Vector3 _p0, Vector3 _p3, Transform parent) 86 | { 87 | transform.SetParent(parent); 88 | gameObject.tag = "BezierCurve"; 89 | 90 | // TODO: Solution for setting tangent points here 91 | Vector3 dir = (_p3 - _p0).normalized; 92 | 93 | p0.position = _p0; 94 | p1.position = _p0 + dir * 2; 95 | p3.position = _p3; 96 | p2.position = _p3 - dir * 2; 97 | 98 | UpdateNumberSubDivisions(divisions); 99 | } 100 | 101 | public void Init(int divisions, Vector3 _p0, Vector3 _p1, Vector3 _p2, Vector3 _p3, Transform parent) 102 | { 103 | transform.SetParent(parent); 104 | gameObject.tag = "BezierCurve"; 105 | 106 | // TODO: Solution for setting tangent points here 107 | p0.position = _p0; 108 | p1.position = _p1; 109 | p2.position = _p2; 110 | p3.position = _p3; 111 | 112 | UpdateNumberSubDivisions(divisions); 113 | } 114 | 115 | public void SetNext(BezierCurve _next) 116 | { 117 | next = _next; 118 | if (next != null) 119 | p3.position = _next.GetStartPosition(); 120 | } 121 | 122 | public void SetPrev(BezierCurve _prev) 123 | { 124 | prev = _prev; 125 | if (prev != null) 126 | { 127 | // Link p0 control point to p3 of neighbor 128 | p0.position = _prev.GetEndPosition(); 129 | } 130 | 131 | } 132 | 133 | public void UpdateControlPoints(ControlPoint point) 134 | { 135 | DrawGuideLine(); 136 | 137 | if (point.transform == p3 && next != null) 138 | { 139 | //Tell next curve to update p0 to match p3 140 | next.UpdateStartPoint(p3.position); 141 | } 142 | else if (point.transform == p0 && prev != null) 143 | { 144 | prev.UpdateEndPoint(p0.position); 145 | } 146 | 147 | UpdateCurveLength(); 148 | GetComponentInParent().UpdateSplineLength(); 149 | } 150 | 151 | public void UpdateNumberSubDivisions(int num) 152 | { 153 | if (num != guideLines.Count) 154 | { 155 | while (num < guideLines.Count) 156 | { 157 | GuideLine line = guideLines[0]; 158 | guideLines.Remove(line); 159 | GameObject.DestroyImmediate(line.gameObject); 160 | } 161 | 162 | while (num > guideLines.Count) 163 | { 164 | guideLines.Add(CreateGuideLineSegment()); 165 | } 166 | 167 | DrawGuideLine(); 168 | } 169 | 170 | UpdateCurveLength(); 171 | } 172 | 173 | void UpdateCurveLength() 174 | { 175 | curveLength = 0; 176 | 177 | foreach(var line in guideLines) 178 | { 179 | curveLength += line.GetDistance(); 180 | } 181 | } 182 | 183 | void UpdateStartPoint(Vector3 position) 184 | { 185 | p0.position = position; 186 | 187 | UpdateCurveLength(); 188 | GetComponentInParent().UpdateSplineLength(); 189 | } 190 | 191 | void UpdateEndPoint(Vector3 position) 192 | { 193 | p3.position = position; 194 | 195 | UpdateCurveLength(); 196 | GetComponentInParent().UpdateSplineLength(); 197 | } 198 | 199 | void OnDestroy() 200 | { 201 | Spline spline = transform.parent.GetComponent(); 202 | spline.CurveDestroyed(this); 203 | } 204 | 205 | void DrawGuideLine() 206 | { 207 | float step = 1f/ guideLines.Count; 208 | 209 | for (int i = 0; i < guideLines.Count; i++) 210 | { 211 | GuideLine line = guideLines[i]; 212 | line.SetPositions(GetPoint(step * i), GetPoint(step * (i + 1))); 213 | } 214 | } 215 | 216 | public void GuidelineSelected() 217 | { 218 | Selection.objects = new GameObject[4]{p0.gameObject, p1.gameObject, p2.gameObject, p3.gameObject}; 219 | foreach (GuideLine g in _guideLines) 220 | g.SetSelected(true); 221 | } 222 | 223 | public void UpdateGizmos() 224 | { 225 | bool flag = false; 226 | GameObject[] cps = new GameObject[4]{p0.gameObject, p1.gameObject, p2.gameObject, p3.gameObject}; 227 | foreach (GameObject cp in cps) 228 | { 229 | if (!Selection.Contains(cp)) 230 | { 231 | flag = true; 232 | break; 233 | } 234 | } 235 | 236 | if (flag) 237 | { 238 | foreach (GuideLine g in _guideLines) 239 | g.SetSelected(false); 240 | } 241 | 242 | } 243 | public void ControlPointDeselected() 244 | { 245 | // If entire segment was highlighted, this will clear it 246 | foreach (GuideLine g in _guideLines) 247 | g.SetSelected(false); 248 | } 249 | 250 | GuideLine CreateGuideLineSegment() 251 | { 252 | GameObject segment = new GameObject(); 253 | 254 | segment.transform.SetParent(guideLine); 255 | 256 | GuideLine line = segment.AddComponent(); 257 | 258 | return line; 259 | } 260 | 261 | // ----------------------------------------------------------------------------------- 262 | 263 | public float GetLength() 264 | { 265 | return curveLength; 266 | } 267 | 268 | public SplineData GetData(float d) 269 | { 270 | float alpha = d / curveLength; 271 | 272 | SplineData data = new SplineData(); 273 | data.Position = GetPoint(alpha); 274 | data.Tangent = GetTangent(alpha); 275 | data.Normal = GetNormal(alpha, Vector3.up); 276 | 277 | return data; 278 | } 279 | 280 | public Vector3 GetEndPosition() 281 | { 282 | return p3.position; 283 | } 284 | 285 | public Vector3 GetEndTangent() 286 | { 287 | return GetTangent(1); 288 | } 289 | 290 | public Vector3 GetEndOrientation() 291 | { 292 | return GetOrientation(1, Vector3.up).eulerAngles; 293 | } 294 | 295 | public Vector3 GetStartOrientation() 296 | { 297 | return GetOrientation(0, Vector3.up).eulerAngles; 298 | } 299 | 300 | public Vector3 GetStartPosition() 301 | { 302 | return p0.position; 303 | } 304 | 305 | public Vector3 GetStartTangent() 306 | { 307 | return GetTangent(0); 308 | } 309 | 310 | public Vector3 GetStartNormal() 311 | { 312 | return GetNormal(0, Vector3.up); 313 | } 314 | 315 | public Vector3 GetEndNormal() 316 | { 317 | return GetNormal(1, Vector3.up); 318 | } 319 | 320 | // ----------------------------------------------------------------------------------- 321 | Vector3 GetPoint(float t) 322 | { 323 | float alpha = 1f - t; 324 | float alpha_2 = alpha * alpha; 325 | float t_2 = t * t; 326 | 327 | return p0.position * (alpha_2 * alpha) + 328 | p1.position * (3f * alpha_2 * t) + 329 | p2.position * (3f * alpha * t_2) + 330 | p3.position * (t_2 * t); 331 | } 332 | 333 | Vector3 GetTangent(float t) 334 | { 335 | float alpha = 1f - t; 336 | float alpha_2 = alpha * alpha; 337 | float t_2 = t * t; 338 | 339 | Vector3 tangent = p0.position * (-alpha_2) + 340 | p1.position * (3f * alpha_2 - 2 * alpha) + 341 | p2.position * (-3f * t_2 + 2 * t) + 342 | p3.position * (t_2); 343 | 344 | return tangent.normalized; 345 | } 346 | 347 | Vector3 GetNormal(float t, Vector3 up) 348 | { 349 | Vector3 tangent = GetTangent(t); 350 | Vector3 binormal = Vector3.Cross(up, tangent).normalized; 351 | 352 | return Vector3.Cross(tangent, binormal); 353 | } 354 | 355 | Quaternion GetOrientation(float t, Vector3 up) 356 | { 357 | Vector3 tangent = GetTangent(t); 358 | Vector3 normal = GetNormal(t, up); 359 | 360 | return Quaternion.LookRotation(tangent, normal); 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/BezierCurve.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 444c78818f09246db96c41b7f8eb3aa5 3 | timeCreated: 1504308214 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/ControlPoint.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public enum POINT_TYPE { NONE, P0, P1, P2, P3 } 6 | 7 | [ExecuteInEditMode] 8 | [System.Serializable] 9 | public class ControlPoint : MonoBehaviour 10 | { 11 | public Transform PrimaryControlPoint; 12 | 13 | public POINT_TYPE Type; 14 | private BezierCurve _bezierCurve; 15 | BezierCurve bezierCurve 16 | { 17 | get 18 | { 19 | if (_bezierCurve == null) 20 | _bezierCurve = transform.parent.GetComponent(); 21 | 22 | return _bezierCurve; 23 | } 24 | set 25 | { 26 | _bezierCurve = value; 27 | } 28 | } 29 | 30 | Vector3 gizmoSize = new Vector3(0.3f, 0.3f, 0.3f); 31 | float sphereRadius = 0.25f; 32 | 33 | Vector3 origin; 34 | 35 | public void SetType(POINT_TYPE _type) 36 | { 37 | Type = _type; 38 | } 39 | 40 | void OnDrawGizmos() 41 | { 42 | // TODO: This updates highlighted line correctly, but seems like over kill for every CP to call ... 43 | bezierCurve.UpdateGizmos(); 44 | 45 | if (PrimaryControlPoint != null) 46 | { 47 | Gizmos.color = UTIL.GIZMO_CONTROL_POINT; 48 | Gizmos.DrawLine(transform.position, PrimaryControlPoint.position); 49 | } 50 | if (Type == POINT_TYPE.P0) 51 | { 52 | Gizmos.color = UTIL.GIZMO_PASTEL_ORANGE; 53 | Gizmos.DrawCube(transform.position, gizmoSize); 54 | } 55 | else if (Type == POINT_TYPE.P3) 56 | { 57 | Gizmos.color = UTIL.GIZMO_PASTEL_ORANGE; 58 | Gizmos.DrawCube(transform.position, gizmoSize); 59 | } 60 | else 61 | { 62 | Gizmos.color = UTIL.GIZMO_CONTROL_POINT; 63 | Gizmos.DrawSphere(transform.position, sphereRadius); 64 | } 65 | } 66 | 67 | void OnDrawGizmosSelected() 68 | { 69 | Gizmos.color = UTIL.GIZMO_HIGHLIGHT_LINE; 70 | if (Type == POINT_TYPE.P0 || Type == POINT_TYPE.P3) 71 | Gizmos.DrawWireCube(transform.position, gizmoSize); 72 | else 73 | Gizmos.DrawWireSphere(transform.position, sphereRadius); 74 | } 75 | 76 | void Update() 77 | { 78 | Vector3 position = transform.position; 79 | 80 | if (position != origin) 81 | { 82 | origin = position; 83 | bezierCurve.UpdateControlPoints(this); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/ControlPoint.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fde19be6ab3a9442eb997fcbbae08121 3 | timeCreated: 1504380480 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/GuideLine.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | [System.Serializable] 7 | public class GuideLine : MonoBehaviour 8 | { 9 | [SerializeField] 10 | Vector3 start; 11 | [SerializeField] 12 | Vector3 end; 13 | 14 | [SerializeField] 15 | private BezierCurve _parent; 16 | 17 | BezierCurve parent 18 | { 19 | get 20 | { 21 | if (_parent == null) 22 | _parent = transform.parent.parent.GetComponent(); 23 | 24 | return _parent; 25 | } 26 | 27 | set 28 | { 29 | _parent = value; 30 | } 31 | } 32 | 33 | bool isSelected; 34 | 35 | public void SetPositions(Vector3 s, Vector3 e) 36 | { 37 | start = s; 38 | end = e; 39 | } 40 | 41 | void OnDrawGizmos() 42 | { 43 | if (isSelected) 44 | Gizmos.color = UTIL.GIZMO_HIGHLIGHT_LINE; 45 | else 46 | Gizmos.color = UTIL.GIZMO_LINE; 47 | 48 | float epsilon = 0.01f; 49 | Vector3 deltaUp = new Vector3(0, epsilon, 0); 50 | Vector3 deltaDown = new Vector3(0, -epsilon, 0); 51 | Gizmos.DrawLine(start, end); 52 | Gizmos.DrawLine(start + deltaUp, end + deltaUp); 53 | Gizmos.DrawLine(start + deltaDown, end + deltaDown); 54 | } 55 | 56 | void OnDrawGizmosSelected() 57 | { 58 | // Only send message if GuideLine was selected directly, not as part of the heirarchy 59 | if (Selection.objects.Length == 1 && (Selection.objects[0] as GameObject) == gameObject) 60 | { 61 | parent.GuidelineSelected(); 62 | } 63 | } 64 | 65 | public Vector3 GetStart() 66 | { 67 | return start; 68 | } 69 | 70 | public Vector3 GetEnd() 71 | { 72 | return end; 73 | } 74 | 75 | public float GetDistance() 76 | { 77 | return Vector3.Distance(start, end); 78 | } 79 | 80 | public void SetSelected(bool flag) 81 | { 82 | isSelected = flag; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/GuideLine.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82459e5b24980440e96ef37df6dcffcc 3 | timeCreated: 1504639954 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/SVGHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using System.IO; 6 | using System.Text.RegularExpressions; 7 | 8 | 9 | public static class SVGHandler 10 | { 11 | // SVG state variables 12 | static int widthSVG = -1; 13 | static int heightSVG = -1; 14 | static Vector2 scaleSVG = new Vector2(1, 1); 15 | 16 | public static void ConvertToSplines(string filePath) 17 | { 18 | var paths = ParseFile(filePath); 19 | 20 | foreach (var path in paths) 21 | { 22 | ParsePath(path); 23 | } 24 | 25 | // Reset state for next SVG path. 26 | widthSVG = -1; 27 | heightSVG = -1; 28 | scaleSVG = new Vector2(1, 1); 29 | } 30 | 31 | static SplineGenerator CreateSpline() 32 | { 33 | var prefab = (GameObject)Resources.Load("Prefabs/Spline", typeof(GameObject)); 34 | return GameObject.Instantiate(prefab).GetComponent(); 35 | } 36 | 37 | // Extract all paths from SVG file. 38 | static List ParseFile(string filePath) 39 | { 40 | Regex fullPathReg = new Regex(@"\s*"); 41 | Regex partialPathReg = new Regex(@"\s* paths = new List(); 44 | StreamReader reader = new StreamReader(filePath); 45 | 46 | string line = " "; 47 | Match m; 48 | 49 | while(!reader.EndOfStream) 50 | { 51 | line += " " + reader.ReadLine(); 52 | 53 | if (scaleSVG.x == 1 && scaleSVG.y == 1 && tryMatch(UTIL.scaleReg, line, out m)) 54 | { 55 | scaleSVG.x = float.Parse(m.Groups[1].ToString()); 56 | scaleSVG.y = float.Parse(m.Groups[2].ToString()); 57 | } 58 | 59 | if (widthSVG < 0 && tryMatch(UTIL.widthReg, line, out m)) 60 | widthSVG = int.Parse(m.Groups[1].ToString()); 61 | 62 | if (heightSVG < 0 && tryMatch(UTIL.heightReg, line, out m)) 63 | heightSVG = int.Parse(m.Groups[1].ToString()); 64 | 65 | m = fullPathReg.Match(line); 66 | 67 | if (m.Success) 68 | { 69 | paths.Add(m.Groups[1].ToString()); 70 | line = " "; 71 | } 72 | else 73 | { 74 | // Check if line contains start of path - if not, throw away 75 | m = partialPathReg.Match(line); 76 | if (!m.Success) 77 | { 78 | line = " "; 79 | } 80 | } 81 | } 82 | 83 | reader.Close(); 84 | 85 | return paths; 86 | } 87 | 88 | public static void ParsePath(string path) 89 | { 90 | Match m; 91 | List coords = null; 92 | 93 | Vector3 currentPoint = Vector3.zero; 94 | Vector3 startPoint = Vector3.zero; 95 | 96 | SplineGenerator spline = null; 97 | 98 | while (path.Length > 0) 99 | { 100 | if (spline == null) 101 | spline = CreateSpline(); 102 | 103 | if (tryMatch(UTIL.moveToAbs, ref path, out coords)) 104 | { 105 | var vectors = floatXYToAbsVectors(coords); 106 | 107 | if (spline.GetComponent().Size() == 0) 108 | spline.transform.position = vectors[0]; 109 | 110 | currentPoint = spline.AbsoluteMoveTo(vectors, currentPoint); 111 | startPoint = currentPoint; 112 | } 113 | else if (tryMatch(UTIL.moveToRel, ref path, out coords)) 114 | { 115 | var vectors = floatXYToRelVectors(coords); 116 | 117 | if (spline.GetComponent().Size() == 0) 118 | spline.transform.position = vectors[0] + currentPoint; 119 | 120 | currentPoint = spline.RelativeMoveTo(vectors, currentPoint); 121 | startPoint = currentPoint; 122 | } 123 | else if (tryMatch(UTIL.horzLineAbs, ref path, out coords)) 124 | { 125 | var vectors = floatXToAbsVectors(coords, currentPoint.y, false); 126 | 127 | currentPoint = spline.AbsoluteLineTo(vectors, currentPoint); 128 | } 129 | else if (tryMatch(UTIL.horzLineRel, ref path, out coords)) 130 | { 131 | var vectors = floatXToRelVectors(coords, 0); 132 | 133 | currentPoint = spline.RelativeLineTo(vectors, currentPoint); 134 | } 135 | else if (tryMatch(UTIL.vertLineAbs, ref path, out coords)) 136 | { 137 | var vectors = floatYToAbsVectors(coords, currentPoint.x); 138 | 139 | currentPoint = spline.AbsoluteLineTo(vectors, currentPoint); 140 | } 141 | else if (tryMatch(UTIL.vertLineRel, ref path, out coords)) 142 | { 143 | var vectors = floatYToRelVectors(coords, 0); 144 | 145 | currentPoint = spline.RelativeLineTo(vectors, currentPoint); 146 | } 147 | else if (tryMatch(UTIL.lineToAbs, ref path, out coords)) 148 | { 149 | var vectors = floatXYToAbsVectors(coords); 150 | 151 | currentPoint = spline.AbsoluteLineTo(vectors, currentPoint); 152 | } 153 | else if (tryMatch(UTIL.lineToRel, ref path, out coords)) 154 | { 155 | var vectors = floatXYToRelVectors(coords); 156 | 157 | currentPoint = spline.RelativeLineTo(vectors, currentPoint); 158 | } 159 | else if (tryMatch(UTIL.curveAbsZ, ref path, out coords)) 160 | { 161 | var vectors = floatXYToAbsVectors(coords); 162 | 163 | if (vectors.Count % 3 == 0) 164 | { 165 | currentPoint = spline.AbsoluteCurve(vectors, currentPoint); 166 | currentPoint = spline.AbsoluteLineTo(new List{startPoint}, currentPoint); 167 | } 168 | else 169 | { 170 | vectors.Add(startPoint); 171 | currentPoint = spline.AbsoluteCurve(vectors, currentPoint); 172 | } 173 | 174 | startPoint = currentPoint; 175 | spline = null; 176 | } 177 | else if (tryMatch(UTIL.curveRelZ, ref path, out coords)) 178 | { 179 | var vectors = floatXYToRelVectors(coords); 180 | 181 | if (vectors.Count % 3 == 0) 182 | { 183 | currentPoint = spline.RelativeCurve(vectors, currentPoint); 184 | currentPoint = spline.AbsoluteLineTo(new List{startPoint}, currentPoint); 185 | } 186 | else 187 | { 188 | vectors.Add(startPoint - currentPoint); 189 | currentPoint = spline.RelativeCurve(vectors, currentPoint); 190 | } 191 | 192 | startPoint = currentPoint; 193 | spline = null; 194 | } 195 | else if (tryMatch(UTIL.curveAbs, ref path, out coords)) 196 | { 197 | var vectors = floatXYToAbsVectors(coords); 198 | 199 | currentPoint = spline.AbsoluteCurve(vectors, currentPoint); 200 | } 201 | else if (tryMatch(UTIL.curveRel, ref path, out coords)) 202 | { 203 | var vectors = floatXYToRelVectors(coords); 204 | 205 | currentPoint = spline.RelativeCurve(vectors, currentPoint); 206 | } 207 | else if (tryMatch(UTIL.smoothCurveAbs, ref path, out coords)) 208 | { 209 | var vectors = floatXYToAbsVectors(coords); 210 | 211 | currentPoint = spline.AbsoluteSmoothCurve(vectors, currentPoint); 212 | } 213 | else if (tryMatch(UTIL.smoothCurveRel, ref path, out coords)) 214 | { 215 | var vectors = floatXYToRelVectors(coords); 216 | 217 | currentPoint = spline.RelativeSmoothCurve(vectors, currentPoint); 218 | } 219 | else if (tryMatch(UTIL.quadAbs, ref path, out coords)) 220 | { 221 | var vectors = floatXYToAbsVectors(coords); 222 | 223 | currentPoint = spline.AbsoluteQuad(vectors, currentPoint); 224 | } 225 | else if (tryMatch(UTIL.quadRel, ref path, out coords)) 226 | { 227 | var vectors = floatXYToRelVectors(coords); 228 | 229 | currentPoint = spline.RelativeQuad(vectors, currentPoint); 230 | } 231 | else if (tryMatch(UTIL.smoothQuadAbs, ref path, out coords)) 232 | { 233 | var vectors = floatXYToAbsVectors(coords); 234 | 235 | currentPoint = spline.AbsoluteSmoothQuad(vectors, currentPoint); 236 | } 237 | else if (tryMatch(UTIL.smoothQuadRel, ref path, out coords)) 238 | { 239 | var vectors = floatXYToRelVectors(coords); 240 | 241 | currentPoint = spline.RelativeSmoothQuad(vectors, currentPoint); 242 | } 243 | else if (tryMatch(UTIL.arcToAbs, ref path, out coords)) 244 | { 245 | //TODO: Invert coords 5 & 6 246 | currentPoint = spline.AbsoluteArc(coords, currentPoint); 247 | } 248 | else if (tryMatch(UTIL.arcToRel, ref path, out coords)) 249 | { 250 | //TODO: Invert coords 5 & 6 251 | currentPoint = spline.RelativeArc(coords, currentPoint); 252 | } 253 | else if (tryMatch(UTIL.endPath, path, out m)) 254 | { 255 | spline.ClosePath(); 256 | spline = null; 257 | path = m.Groups[1].ToString(); 258 | } 259 | else 260 | { 261 | Debug.Log("Couldn't Match: " + path); 262 | path = ""; 263 | } 264 | } 265 | } 266 | 267 | static bool tryMatch(Regex regex, string input, out Match match) 268 | { 269 | match = regex.Match(input); 270 | 271 | return match.Success; 272 | } 273 | 274 | static bool tryMatch(Regex reg, ref string path, out List coords) 275 | { 276 | Match m = reg.Match(path); 277 | 278 | coords = m.Success ? Input2Floats(m.Groups[1].ToString()) : null; 279 | path = m.Success ? m.Groups[2].ToString() : path; 280 | 281 | return m.Success; 282 | } 283 | 284 | // First splits on commas. 285 | // Then breaks apart numbers where +/- sign was separation point. 286 | static List Input2Floats(string inputs) 287 | { 288 | var result = new List(); 289 | 290 | string[] tokens = inputs.Split(new char[] {',', ' ', '\t'}); 291 | 292 | foreach (string t in tokens) 293 | { 294 | int start = 0; 295 | 296 | for (int i = 0; i < t.Length; ++i) 297 | { 298 | if (i > 0 && (t[i] == '-' && t[i - 1] != 'e') || (t[i] == '+' && t[i - 1] != 'e')) 299 | { 300 | result.Add(float.Parse(t.Substring(start, i - start))); 301 | start = i; 302 | } 303 | } 304 | 305 | if (start < t.Length) 306 | { 307 | result.Add(float.Parse(t.Substring(start, t.Length - start))); 308 | } 309 | } 310 | 311 | return result; 312 | } 313 | 314 | static List floatXToAbsVectors(List inputs, float y, bool shouldInvert = true) 315 | { 316 | var result = new List(); 317 | 318 | for (int i = 0; i < inputs.Count; ++i) 319 | result.Add(new Vector3(inputs[i] * scaleSVG.x, (shouldInvert ? invertAbs(y) : y) * scaleSVG.y)); 320 | 321 | return result; 322 | } 323 | 324 | static List floatXToRelVectors(List inputs, float y) 325 | { 326 | var result = new List(); 327 | 328 | for (int i = 0; i < inputs.Count; ++i) 329 | result.Add(new Vector3(inputs[i] * scaleSVG.x, invertRel(y) * scaleSVG.y )); 330 | 331 | return result; 332 | } 333 | 334 | static List floatYToAbsVectors(List inputs, float x) 335 | { 336 | var result = new List(); 337 | 338 | for (int i = 0; i < inputs.Count; ++i) 339 | result.Add(new Vector3(x * scaleSVG.x, invertAbs(inputs[i]) * scaleSVG.y)); 340 | 341 | return result; 342 | } 343 | 344 | static List floatYToRelVectors(List inputs, float x) 345 | { 346 | var result = new List(); 347 | 348 | for (int i = 0; i < inputs.Count; ++i) 349 | result.Add(new Vector3(x * scaleSVG.x, invertRel(inputs[i]) * scaleSVG.y)); 350 | 351 | return result; 352 | } 353 | 354 | static List floatXYToAbsVectors(List inputs) 355 | { 356 | var result = new List(); 357 | 358 | for (int i = 0; i < inputs.Count; i += 2) 359 | { 360 | if (i + 1 == inputs.Count) 361 | { 362 | Debug.Log("Incorrect number of arguments"); 363 | break; 364 | } 365 | 366 | result.Add(new Vector3(inputs[i] * scaleSVG.x, invertAbs(inputs[i + 1]) * scaleSVG.y)); 367 | } 368 | 369 | return result; 370 | } 371 | 372 | static List floatXYToRelVectors(List inputs) 373 | { 374 | var result = new List(); 375 | 376 | for (int i = 0; i < inputs.Count; i += 2) 377 | { 378 | if (i + 1 == inputs.Count) 379 | { 380 | Debug.Log("Incorrect number of arguments"); 381 | break; 382 | } 383 | 384 | result.Add(new Vector3(inputs[i] * scaleSVG.x, invertRel(inputs[i + 1]) * scaleSVG.y)); 385 | } 386 | 387 | return result; 388 | } 389 | 390 | // Invert y-axis since it points down in SVG files. 391 | static float invertAbs(float y) 392 | { 393 | return (heightSVG > 0) ? heightSVG - y : -y; 394 | } 395 | 396 | static float invertRel(float y) 397 | { 398 | return -y; 399 | } 400 | } 401 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/SVGHandler.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fc7b90057a3b5467994a3eedadfefa7b 3 | timeCreated: 1521101104 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/Spline.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | [ExecuteInEditMode] 6 | [System.Serializable] 7 | public class Spline : MonoBehaviour 8 | { 9 | #region Public Properties 10 | 11 | [SerializeField] 12 | private GameObject _curvePrefab; 13 | GameObject curvePrefab 14 | { 15 | get 16 | { 17 | if (_curvePrefab == null) 18 | _curvePrefab = (GameObject)Resources.Load("Prefabs/BezierCurve", typeof(GameObject)); 19 | 20 | return _curvePrefab; 21 | } 22 | } 23 | 24 | #endregion 25 | 26 | [Tooltip("The number of subdivisons in each curve. A higher number means smoother curves, but at a performance cost.")] 27 | [Range(1, 100)]public int NumSubDivisions = 10; 28 | 29 | [SerializeField] 30 | List curves; 31 | int _numSubDivisions; 32 | [SerializeField] 33 | double splineLength; 34 | 35 | void Awake() 36 | { 37 | if (curves == null) 38 | curves = new List(); 39 | } 40 | 41 | #region Public API 42 | 43 | // Called when number of subdivisions is adjusted in editor window 44 | public void UpdateNumberSubDivisions() 45 | { 46 | splineLength = 0; 47 | 48 | if (_numSubDivisions != NumSubDivisions) 49 | { 50 | foreach (BezierCurve curve in curves) 51 | { 52 | curve.UpdateNumberSubDivisions(NumSubDivisions); 53 | splineLength += curve.GetLength(); 54 | } 55 | 56 | _numSubDivisions = NumSubDivisions; 57 | } 58 | } 59 | 60 | // Called when user clicks GUI Add Gizmo 61 | public void AddPoint(bool atStart) 62 | { 63 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 64 | 65 | int numCurves = curves.Count; 66 | 67 | if (numCurves > 0) 68 | { 69 | if (atStart) 70 | { 71 | BezierCurve next = curves[0]; 72 | Vector3 anchor = next.GetStartPosition(); 73 | curve.Init(NumSubDivisions, anchor, atStart, transform); 74 | 75 | next.SetPrev(curve); 76 | curve.SetNext(next); 77 | } 78 | else 79 | { 80 | BezierCurve prev = curves[numCurves - 1]; 81 | Vector3 anchor = prev.GetEndPosition(); 82 | curve.Init(NumSubDivisions, anchor, atStart, transform); 83 | 84 | prev.SetNext(curve); 85 | curve.SetPrev(prev); 86 | } 87 | } 88 | else 89 | { 90 | curve.Init(NumSubDivisions, Vector3.zero, atStart, transform); 91 | } 92 | 93 | if (atStart) 94 | curves.Insert(0, curve); 95 | else 96 | curves.Add(curve); 97 | 98 | splineLength += curve.GetLength(); 99 | } 100 | 101 | public void AddAbsoluteSmoothPoint(Vector3 end) 102 | { 103 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 104 | 105 | int numCurves = curves.Count; 106 | 107 | if (numCurves > 0) 108 | { 109 | BezierCurve prev = curves[numCurves - 1]; 110 | Vector3 anchor = prev.GetEndPosition(); 111 | Vector3 control1 = (prev.p2.position - prev.p3.position) * -1 + prev.p3.position; 112 | 113 | curve.Init(NumSubDivisions, anchor, control1, control1, end, transform); 114 | 115 | prev.SetNext(curve); 116 | curve.SetPrev(prev); 117 | } 118 | else 119 | { 120 | Vector3 p = transform.position; 121 | curve.Init(NumSubDivisions, p, end, transform); 122 | } 123 | 124 | curves.Add(curve); 125 | splineLength += curve.GetLength(); 126 | } 127 | 128 | public void AddAbsolutePoint(Vector3 end) 129 | { 130 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 131 | 132 | int numCurves = curves.Count; 133 | 134 | if (numCurves > 0) 135 | { 136 | 137 | BezierCurve prev = curves[numCurves - 1]; 138 | Vector3 anchor = prev.GetEndPosition(); 139 | curve.Init(NumSubDivisions, anchor, end, transform); 140 | 141 | prev.SetNext(curve); 142 | curve.SetPrev(prev); 143 | } 144 | else 145 | { 146 | curve.Init(NumSubDivisions, transform.position, end, transform); 147 | } 148 | 149 | curves.Add(curve); 150 | splineLength += curve.GetLength(); 151 | } 152 | 153 | public void AddAbsolutePoint(Vector3 control1, Vector3 control2, Vector3 end) 154 | { 155 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 156 | 157 | int numCurves = curves.Count; 158 | 159 | if (numCurves > 0) 160 | { 161 | BezierCurve prev = curves[numCurves - 1]; 162 | Vector3 anchor = prev.GetEndPosition(); 163 | curve.Init(NumSubDivisions, anchor, control1, control2, end, transform); 164 | 165 | prev.SetNext(curve); 166 | curve.SetPrev(prev); 167 | } 168 | else 169 | { 170 | Vector3 p = transform.position; 171 | curve.Init(NumSubDivisions, p, control1, control2, end, transform); 172 | } 173 | 174 | curves.Add(curve); 175 | splineLength += curve.GetLength(); 176 | } 177 | 178 | // For Smooth Curve command 179 | public void AddAbsolutePoint(Vector3 control2, Vector3 end) 180 | { 181 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 182 | 183 | int numCurves = curves.Count; 184 | 185 | if (numCurves > 0) 186 | { 187 | BezierCurve prev = curves[numCurves - 1]; 188 | Vector3 anchor = prev.GetEndPosition(); 189 | Vector3 control1 = (prev.p2.position - prev.p3.position) * -1 + prev.p3.position; 190 | 191 | curve.Init(NumSubDivisions, anchor, control1, control2, end, transform); 192 | 193 | prev.SetNext(curve); 194 | curve.SetPrev(prev); 195 | } 196 | else 197 | { 198 | Vector3 p = transform.position; 199 | curve.Init(NumSubDivisions, p, p, control2, end, transform); 200 | } 201 | 202 | curves.Add(curve); 203 | splineLength += curve.GetLength(); 204 | } 205 | 206 | public void AddRelativePoint(Vector3 end) 207 | { 208 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 209 | 210 | int numCurves = curves.Count; 211 | 212 | if (numCurves > 0) 213 | { 214 | BezierCurve prev = curves[numCurves - 1]; 215 | Vector3 anchor = prev.GetEndPosition(); 216 | curve.Init(NumSubDivisions, anchor, anchor + end, transform); 217 | 218 | prev.SetNext(curve); 219 | curve.SetPrev(prev); 220 | } 221 | else 222 | { 223 | curve.Init(NumSubDivisions, transform.position, transform.position + end, transform); 224 | } 225 | 226 | curves.Add(curve); 227 | splineLength += curve.GetLength(); 228 | } 229 | 230 | public void AddRelativeSmoothPoint(Vector3 end) 231 | { 232 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 233 | 234 | int numCurves = curves.Count; 235 | 236 | if (numCurves > 0) 237 | { 238 | BezierCurve prev = curves[numCurves - 1]; 239 | Vector3 anchor = prev.GetEndPosition(); 240 | Vector3 control1 = (prev.p2.position - prev.p3.position) * -1; 241 | 242 | curve.Init(NumSubDivisions, anchor, anchor + control1, anchor + control1, anchor + end, transform); 243 | 244 | prev.SetNext(curve); 245 | curve.SetPrev(prev); 246 | } 247 | else 248 | { 249 | Vector3 p = transform.position; 250 | curve.Init(NumSubDivisions, p, p + end, transform); 251 | } 252 | 253 | curves.Add(curve); 254 | splineLength += curve.GetLength(); 255 | } 256 | 257 | public void AddRelativePoint(Vector3 control1, Vector3 control2, Vector3 end) 258 | { 259 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 260 | 261 | int numCurves = curves.Count; 262 | 263 | if (numCurves > 0) 264 | { 265 | 266 | BezierCurve prev = curves[numCurves - 1]; 267 | Vector3 anchor = prev.GetEndPosition(); 268 | curve.Init(NumSubDivisions, anchor, anchor + control1, anchor + control2, anchor + end, transform); 269 | 270 | prev.SetNext(curve); 271 | curve.SetPrev(prev); 272 | } 273 | else 274 | { 275 | Vector3 p = transform.position; 276 | curve.Init(NumSubDivisions, p, p + control1, p + control2, p + end, transform); 277 | } 278 | 279 | curves.Add(curve); 280 | splineLength += curve.GetLength(); 281 | } 282 | 283 | // For Smooth Curve command 284 | public void AddRelativePoint(Vector3 control2, Vector3 end) 285 | { 286 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 287 | 288 | int numCurves = curves.Count; 289 | 290 | if (numCurves > 0) 291 | { 292 | BezierCurve prev = curves[numCurves - 1]; 293 | Vector3 anchor = prev.GetEndPosition(); 294 | Vector3 control1 = (prev.p2.position - prev.p3.position) * -1; 295 | 296 | curve.Init(NumSubDivisions, anchor, anchor + control1, anchor + control2, anchor + end, transform); 297 | 298 | prev.SetNext(curve); 299 | curve.SetPrev(prev); 300 | } 301 | else 302 | { 303 | Vector3 p = transform.position; 304 | curve.Init(NumSubDivisions, p, p, p + control2, p + end, transform); 305 | } 306 | 307 | curves.Add(curve); 308 | splineLength += curve.GetLength(); 309 | } 310 | 311 | public void RemovePoint(bool atStart) 312 | { 313 | // If only one curve in spline, don't remove it 314 | // TODO: hide minus gizmos with one curve 315 | if (curves.Count == 1) 316 | return; 317 | 318 | BezierCurve curve = atStart ? curves[0] : curves[curves.Count - 1]; 319 | 320 | splineLength -= curve.GetLength(); 321 | 322 | Object.DestroyImmediate(curve.gameObject); 323 | } 324 | 325 | public void ClosePath() 326 | { 327 | int numCurves = curves.Count; 328 | 329 | if (numCurves == 0) 330 | { 331 | Debug.Log("Error: Cannot close empty path."); 332 | return; 333 | } 334 | 335 | BezierCurve curve = GameObject.Instantiate(curvePrefab).GetComponent(); 336 | 337 | BezierCurve startCurve = curves[0]; 338 | BezierCurve endCurve = curves[curves.Count - 1]; 339 | 340 | curve.Init(NumSubDivisions, endCurve.GetEndPosition(), startCurve.GetStartPosition(), transform); 341 | curves.Add(curve); 342 | 343 | splineLength += curve.GetLength(); 344 | 345 | endCurve.SetNext(curve); 346 | curve.SetPrev(endCurve); 347 | } 348 | 349 | public int Size() 350 | { 351 | return curves.Count; 352 | } 353 | 354 | #endregion 355 | 356 | // Called by curves when Control Point/Position adjusted 357 | public void UpdateSplineLength() 358 | { 359 | splineLength = 0; 360 | 361 | foreach(var curve in curves) 362 | splineLength += curve.GetLength(); 363 | } 364 | 365 | public void CurveDestroyed(BezierCurve curve) 366 | { 367 | int index = curves.IndexOf(curve); 368 | 369 | if (index == -1) 370 | { 371 | Debug.Log("Tried to remove curve that wasn't there"); 372 | return; 373 | } 374 | 375 | bool first = index == 0; 376 | bool last = index == curves.Count - 1; 377 | BezierCurve prev = first ? null : curves[index - 1]; 378 | BezierCurve next = last ? null : curves[index + 1]; 379 | 380 | if (!first) 381 | prev.SetNext(next); 382 | if (!last) 383 | next.SetPrev(prev); 384 | 385 | curves.Remove(curve); 386 | } 387 | 388 | public SplineData NextDataPoint(double dist) 389 | { 390 | float d = (float)(dist % splineLength); 391 | 392 | foreach (var curve in curves) 393 | { 394 | if (d < curve.GetLength()) 395 | return curve.GetData(d); 396 | 397 | d -= curve.GetLength(); 398 | } 399 | 400 | return curves[0].GetData(0); 401 | } 402 | 403 | // TODO: Remove this for better solution 404 | void HardReset() 405 | { 406 | curves.RemoveRange(0, curves.Count); 407 | 408 | foreach(Transform t in transform) 409 | { 410 | if (t.tag == "BezierCurve") 411 | { 412 | curves.Add(t.GetComponent()); 413 | } 414 | } 415 | } 416 | 417 | #region Start and End Accessors 418 | 419 | public Vector3 EndPosition() 420 | { 421 | int count = curves.Count; 422 | if (count == 0) 423 | return Vector3.zero; 424 | 425 | return curves[count - 1].GetEndPosition(); 426 | } 427 | 428 | Vector3 EndTangent() 429 | { 430 | int count = curves.Count; 431 | if (count == 0) 432 | return Vector3.zero; 433 | 434 | return curves[count - 1].GetEndTangent(); 435 | } 436 | Vector3 EndNormal() 437 | { 438 | int count = curves.Count; 439 | if (count == 0) 440 | return Vector3.zero; 441 | 442 | return curves[count - 1].GetEndNormal(); 443 | } 444 | 445 | public Vector3 EndDirection() 446 | { 447 | int count = curves.Count; 448 | if (count == 0) 449 | return Vector3.zero; 450 | 451 | Vector3 e = curves[count - 1].GetEndPosition(); 452 | Vector3 s = curves[count - 1].GetStartPosition(); 453 | 454 | return (e - s).normalized; 455 | } 456 | 457 | Vector3 EndOrientation() 458 | { 459 | int count = curves.Count; 460 | if (count == 0) 461 | return Vector3.zero; 462 | 463 | return curves[count - 1].GetEndOrientation(); 464 | } 465 | 466 | public Vector3 StartPosition() 467 | { 468 | int count = curves.Count; 469 | if (count == 0) 470 | return Vector3.zero; 471 | 472 | return curves[0].GetStartPosition(); 473 | } 474 | 475 | public Vector3 StartDirection() 476 | { 477 | int count = curves.Count; 478 | if (count == 0) 479 | return Vector3.zero; 480 | 481 | Vector3 e = curves[0].GetEndPosition(); 482 | Vector3 s = curves[0].GetStartPosition(); 483 | 484 | return (s - e).normalized; 485 | } 486 | 487 | Vector3 StartOrientation() 488 | { 489 | int count = curves.Count; 490 | if (count == 0) 491 | return Vector3.zero; 492 | 493 | return curves[0].GetStartOrientation(); 494 | } 495 | 496 | Vector3 StartTanget() 497 | { 498 | int count = curves.Count; 499 | if (count == 0) 500 | return Vector3.zero; 501 | 502 | return curves[0].GetStartTangent(); 503 | } 504 | 505 | Vector3 StartNormal() 506 | { 507 | int count = curves.Count; 508 | if (count == 0) 509 | return Vector3.zero; 510 | 511 | return curves[0].GetStartNormal(); 512 | } 513 | 514 | #endregion 515 | 516 | } 517 | 518 | // ---------------------------------------------------------------------- 519 | 520 | [System.Serializable] 521 | public struct SplineData 522 | { 523 | public Vector3 Position; 524 | public Vector3 Tangent; 525 | public Vector3 Normal; 526 | } 527 | 528 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/Spline.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 151e32a270d9c40d2b240476503593ff 3 | timeCreated: 1504309290 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/SplineAnimation.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class SplineAnimation : MonoBehaviour 6 | { 7 | public float Speed = 10.0f; 8 | public bool OrientToPath = true; 9 | public Spline Spline; 10 | 11 | double distanceTraveled; 12 | 13 | void Start() 14 | { 15 | distanceTraveled = 0; 16 | } 17 | 18 | void Update() 19 | { 20 | distanceTraveled += Time.deltaTime * Speed; 21 | 22 | SplineData data = Spline.NextDataPoint(distanceTraveled); 23 | 24 | transform.position = data.Position; 25 | 26 | if (OrientToPath) 27 | { 28 | // For some reason calling SetLookRotation directly on transform.localRotation doesn't update anything 29 | Quaternion rot = Quaternion.LookRotation(data.Tangent, data.Normal); 30 | transform.localRotation = rot; 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/SplineAnimation.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d823548bf5a274d8b96d9aef306496fd 3 | timeCreated: 1504665617 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/SplineGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class SplineGenerator : MonoBehaviour 6 | { 7 | Spline _spline; 8 | Spline spline 9 | { 10 | get 11 | { 12 | if (_spline == null) 13 | _spline = GetComponent(); 14 | 15 | return _spline; 16 | } 17 | set 18 | { 19 | _spline = value; 20 | } 21 | } 22 | 23 | public Vector3 AbsoluteMoveTo(List vectors, Vector3 currentPoint) 24 | { 25 | if (vectors.Count == 0) 26 | { 27 | Debug.Log("Error: Bad Number of inputs to 'Absolute Move To' "); 28 | return currentPoint; 29 | } 30 | 31 | Vector3 current = vectors[0]; 32 | vectors.RemoveAt(0); 33 | 34 | if (vectors.Count > 0) 35 | return AbsoluteLineTo(vectors, current); 36 | 37 | return current; 38 | } 39 | 40 | public Vector3 RelativeMoveTo(List vectors, Vector3 currentPoint) 41 | { 42 | if (vectors.Count == 0) 43 | { 44 | Debug.Log("Error: Bad Number of inputs to 'Relative Move To' "); 45 | return currentPoint; 46 | } 47 | 48 | Vector3 current = vectors[0] + currentPoint; 49 | vectors.RemoveAt(0); 50 | 51 | if (vectors.Count > 0) 52 | return RelativeLineTo(vectors, current); 53 | 54 | return current; 55 | } 56 | 57 | public Vector3 AbsoluteLineTo(List vectors, Vector3 currentPoint) 58 | { 59 | for (int i = 0; i < vectors.Count; ++i) 60 | spline.AddAbsolutePoint(vectors[i]); 61 | 62 | return vectors[vectors.Count - 1]; 63 | } 64 | 65 | public Vector3 RelativeLineTo(List vectors, Vector3 currentPoint) 66 | { 67 | for (int i = 0; i < vectors.Count; ++i) 68 | spline.AddRelativePoint(vectors[i]); 69 | 70 | return vectors[vectors.Count - 1] + currentPoint; 71 | } 72 | 73 | public Vector3 AbsoluteCurve(List vectors, Vector3 currentPoint) 74 | { 75 | for (int i = 0; i < vectors.Count; i += 3) 76 | { 77 | if (i + 2 >= vectors.Count) 78 | { 79 | Debug.Log("Error: Bad number of inputs to Curve command."); 80 | break; 81 | } 82 | 83 | spline.AddAbsolutePoint(vectors[i], vectors[i + 1], vectors[i + 2]); 84 | } 85 | 86 | return vectors[vectors.Count - 1]; 87 | } 88 | 89 | public Vector3 RelativeCurve(List vectors, Vector3 currentPoint) 90 | { 91 | for (int i = 0; i < vectors.Count; i += 3) 92 | { 93 | if (i + 2 >= vectors.Count) 94 | { 95 | Debug.Log("Error: Bad number of inputs to curve command."); 96 | break; 97 | } 98 | 99 | spline.AddRelativePoint(vectors[i], vectors[i + 1], vectors[i + 2]); 100 | } 101 | 102 | return vectors[vectors.Count - 1] + currentPoint; 103 | } 104 | 105 | public Vector3 AbsoluteSmoothCurve(List vectors, Vector3 currentPoint) 106 | { 107 | for (int i = 0; i < vectors.Count; i += 2) 108 | { 109 | if (i + 1 >= vectors.Count) 110 | { 111 | Debug.Log("Error: Bad number of inputs to Smooth Curve command."); 112 | break; 113 | } 114 | 115 | spline.AddAbsolutePoint(vectors[i], vectors[i + 1]); 116 | } 117 | 118 | return vectors[vectors.Count - 1]; 119 | } 120 | 121 | public Vector3 RelativeSmoothCurve(List vectors, Vector3 currentPoint) 122 | { 123 | for (int i = 0; i < vectors.Count; i += 2) 124 | { 125 | if (i + 1 >= vectors.Count) 126 | { 127 | Debug.Log("Error: Bad number of inputs to smooth curve command."); 128 | break; 129 | } 130 | 131 | spline.AddRelativePoint(vectors[i], vectors[i + 1]); 132 | } 133 | 134 | return vectors[vectors.Count - 1] + currentPoint; 135 | } 136 | 137 | public Vector3 AbsoluteArc(List inputs, Vector3 currentPoint) 138 | { 139 | Vector3 endPoint = currentPoint; 140 | 141 | int i = 0; 142 | while (i < inputs.Count) 143 | { 144 | if (i + 6 >= inputs.Count) 145 | { 146 | if (i + 5 >= inputs.Count) 147 | { 148 | Debug.Log("Error: Bad number of inputs to Arc command."); 149 | break; 150 | } 151 | else 152 | { 153 | // TODO: Verify if this is correct - seems to be able to skip x-rotation argument 154 | endPoint = new Vector3(inputs[i + 4], inputs[i + 5]); 155 | spline.AddAbsolutePoint(endPoint); 156 | 157 | i += 6; 158 | continue; 159 | } 160 | } 161 | 162 | //float rx = inputs[i]; 163 | //float ry = inputs[i + 1]; 164 | //float theta = inputs[i + 2]; 165 | //bool largeAngleFlag = (int)inputs[i + 3] == 1; 166 | //bool sweepFlag = (int)inputs[i + 4] == 1; 167 | 168 | endPoint = new Vector3(inputs[i + 5], inputs[i + 6]); 169 | 170 | spline.AddAbsolutePoint(endPoint); 171 | i += 7; 172 | } 173 | 174 | return endPoint; 175 | } 176 | 177 | public Vector3 RelativeArc(List inputs, Vector3 currentPoint) 178 | { 179 | Vector3 endPoint = currentPoint; 180 | 181 | int i = 0; 182 | while (i < inputs.Count) 183 | { 184 | if (i + 6 >= inputs.Count) 185 | { 186 | if (i + 5 >= inputs.Count) 187 | { 188 | Debug.Log("Error: Bad number of inputs to Arc command."); 189 | break; 190 | } 191 | else 192 | { 193 | // TODO: Verify if this is correct - seems to be able to skip x-rotation argument 194 | endPoint = new Vector3(inputs[i + 4], inputs[i + 5]) + endPoint; 195 | spline.AddRelativePoint(endPoint); 196 | 197 | i += 6; 198 | continue; 199 | } 200 | } 201 | 202 | // float rx = inputs[i]; 203 | // float ry = inputs[i + 1]; 204 | // float theta = inputs[i + 2]; 205 | // bool largeAngleFlag = (int)inputs[i + 3] == 1; 206 | // bool sweepFlag = (int)inputs[i + 4] == 1; 207 | 208 | endPoint = new Vector3(inputs[i + 5], inputs[i + 6]) + endPoint; 209 | 210 | spline.AddRelativePoint(endPoint); 211 | i += 7; 212 | } 213 | 214 | return endPoint; 215 | } 216 | 217 | public Vector3 AbsoluteQuad(List vectors, Vector3 currentPoint) 218 | { 219 | for (int i = 0; i < vectors.Count; i += 2) 220 | { 221 | if (i + 1 >= vectors.Count) 222 | { 223 | Debug.Log("Error: Bad number of inputs to Absolute Quadratic command."); 224 | break; 225 | } 226 | 227 | spline.AddAbsolutePoint(vectors[i], vectors[i], vectors[i + 1]); 228 | } 229 | 230 | return vectors[vectors.Count - 1]; 231 | } 232 | 233 | public Vector3 RelativeQuad(List vectors, Vector3 currentPoint) 234 | { 235 | for (int i = 0; i < vectors.Count; i += 2) 236 | { 237 | if (i + 1 >= vectors.Count) 238 | { 239 | Debug.Log("Error: Bad number of inputs to Absolute Quadratic command."); 240 | break; 241 | } 242 | 243 | spline.AddRelativePoint(vectors[i], vectors[i], vectors[i + 1]); 244 | } 245 | 246 | return vectors[vectors.Count - 1] + currentPoint; 247 | } 248 | 249 | public Vector3 AbsoluteSmoothQuad(List vectors, Vector3 currentPoint) 250 | { 251 | // TODO: When previous command isn't Q or T, control point assumed to be point 252 | for (int i = 0; i < vectors.Count; ++i) 253 | spline.AddAbsoluteSmoothPoint(vectors[i]); 254 | 255 | return vectors[vectors.Count - 1]; 256 | } 257 | 258 | public Vector3 RelativeSmoothQuad(List vectors, Vector3 currentPoint) 259 | { 260 | // TODO: When previous command isn't Q or T, control point assumed to be point 261 | for (int i = 0; i < vectors.Count; ++i) 262 | spline.AddRelativeSmoothPoint(vectors[i]); 263 | 264 | return vectors[vectors.Count - 1] + currentPoint; 265 | } 266 | 267 | public void ClosePath() 268 | { 269 | spline.ClosePath(); 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/SplineGenerator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a031f955f3aaf45dcad76563006acf5d 3 | timeCreated: 1521424209 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/SplineGizmos.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | [ExecuteInEditMode] 7 | [System.Serializable] 8 | public class SplineGizmos : MonoBehaviour 9 | { 10 | #region Constants 11 | 12 | private Vector3 colliderSizeMinus = new Vector3(1.65f, 0.8f, 0.75f); 13 | private Vector3 colliderSizePlus = new Vector3(1.65f, 1.65f, 0.75f); 14 | 15 | Vector3 gizmoSizeX = new Vector3(1.5f, 0.5f, 0.25f); 16 | Vector3 gizmoSizeY = new Vector3(0.5f, 1.5f, 0.25f); 17 | Vector3 gizmoOffset = new Vector3(0, 0.8f, 0); 18 | 19 | #endregion 20 | 21 | [SerializeField][HideInInspector] 22 | private BoxCollider _addEndGizmo; 23 | BoxCollider addEndGizmo 24 | { 25 | get 26 | { 27 | if (_addEndGizmo == null) 28 | _addEndGizmo = CreateGizmoDetector(colliderSizePlus); 29 | 30 | return _addEndGizmo; 31 | } 32 | } 33 | 34 | [SerializeField][HideInInspector] 35 | private BoxCollider _addStartGizmo; 36 | BoxCollider addStartGizmo 37 | { 38 | get 39 | { 40 | if (_addStartGizmo == null) 41 | _addStartGizmo = CreateGizmoDetector(colliderSizePlus); 42 | 43 | return _addStartGizmo; 44 | } 45 | } 46 | 47 | [SerializeField][HideInInspector] 48 | private BoxCollider _removeEndGizmo; 49 | BoxCollider removeEndGizmo 50 | { 51 | get 52 | { 53 | if (_removeEndGizmo == null) 54 | _removeEndGizmo = CreateGizmoDetector(colliderSizeMinus); 55 | 56 | return _removeEndGizmo; 57 | } 58 | } 59 | 60 | [SerializeField][HideInInspector] 61 | private BoxCollider _removeStartGizmo; 62 | BoxCollider removeStartGizmo 63 | { 64 | get 65 | { 66 | if (_removeStartGizmo == null) 67 | _removeStartGizmo = CreateGizmoDetector(colliderSizeMinus); 68 | 69 | return _removeStartGizmo; 70 | } 71 | } 72 | 73 | [HideInInspector][SerializeField] 74 | private Spline _spline; 75 | Spline spline 76 | { 77 | get 78 | { 79 | if (_spline == null) 80 | _spline = GetComponent(); 81 | 82 | return _spline; 83 | } 84 | 85 | set 86 | { 87 | _spline = value; 88 | } 89 | } 90 | 91 | Vector3 addStartGizmoPosition; 92 | Vector3 addEndGizmoPosition; 93 | Vector3 removeStartGizmoPosition; 94 | Vector3 removeEndGizmoPosition; 95 | 96 | BoxCollider CreateGizmoDetector(Vector3 size) 97 | { 98 | GameObject detector = new GameObject(); 99 | 100 | detector.hideFlags = HideFlags.HideInHierarchy; 101 | detector.transform.SetParent(transform); 102 | 103 | BoxCollider box = detector.AddComponent(); 104 | box.size = size; 105 | box.isTrigger = true; 106 | 107 | return box; 108 | } 109 | 110 | void OnDrawGizmos() 111 | { 112 | UpdateGizmoPositions(); 113 | 114 | Gizmos.color = UTIL.GIZMO_LINE; 115 | 116 | DrawGizmoPlus(addStartGizmoPosition); 117 | DrawGizmoPlus(addEndGizmoPosition); 118 | DrawGizmoMinus(removeStartGizmoPosition); 119 | DrawGizmoMinus(removeEndGizmoPosition); 120 | } 121 | 122 | void OnDrawGizmosSelected() 123 | { 124 | RaycastGizmos(); 125 | } 126 | 127 | void UpdateGizmoPositions() 128 | { 129 | Vector3 end = spline.EndPosition(); 130 | Vector3 start = spline.StartPosition(); 131 | Vector3 endDir = spline.EndDirection(); 132 | Vector3 startDir = spline.StartDirection(); 133 | 134 | // Update Gizmo positions 135 | addEndGizmoPosition = end + endDir * 2 + gizmoOffset; 136 | addStartGizmoPosition = start + startDir * 2 + gizmoOffset; 137 | removeEndGizmoPosition = end + endDir * 2 - gizmoOffset; 138 | removeStartGizmoPosition = start + startDir * 2 - gizmoOffset; 139 | 140 | // Update collision box positions 141 | addEndGizmo.transform.position = addEndGizmoPosition; 142 | addStartGizmo.transform.position = addStartGizmoPosition; 143 | removeEndGizmo.transform.position = removeEndGizmoPosition; 144 | removeStartGizmo.transform.position = removeStartGizmoPosition; 145 | } 146 | 147 | void DrawGizmoPlus(Vector3 center) 148 | { 149 | Gizmos.DrawCube(center, gizmoSizeX); 150 | Gizmos.DrawCube(center, gizmoSizeY); 151 | } 152 | 153 | void DrawGizmoMinus(Vector3 center) 154 | { 155 | Gizmos.DrawCube(center, gizmoSizeX); 156 | } 157 | 158 | // Check to see which/if user clicked on a Gizmo - call appropriate function. 159 | void RaycastGizmos() 160 | { 161 | Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); 162 | RaycastHit hitData = new RaycastHit(); 163 | 164 | if (addEndGizmo.Raycast(ray, out hitData, 200)) 165 | { 166 | spline.AddPoint(false); 167 | } 168 | else if (addStartGizmo.Raycast(ray, out hitData, 200)) 169 | { 170 | spline.AddPoint(true); 171 | } 172 | else if (removeEndGizmo.Raycast(ray, out hitData, 200)) 173 | { 174 | spline.RemovePoint(false); 175 | } 176 | else if (removeStartGizmo.Raycast(ray, out hitData, 200)) 177 | { 178 | spline.RemovePoint(true); 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/SplineGizmos.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 02c7671b7bea34a94960b09ce64c86c6 3 | timeCreated: 1521838867 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/UTIL.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | using System.Text.RegularExpressions; 6 | 7 | public static class UTIL 8 | { 9 | 10 | #region EDITOR COLORS 11 | 12 | public static Color GIZMO_PASTEL_ORANGE = new Color(0.996f, 0.502f, 0.263f); 13 | public static Color GIZMO_HIGHLIGHT_LINE = new Color(0.996f, 0.698f, 0.263f); 14 | public static Color GIZMO_LINE = new Color(0.176f, 0.667f, 0.494f); 15 | public static Color GIZMO_CONTROL_POINT = new Color(0.204f, 0.427f, 0.647f); 16 | 17 | #endregion 18 | 19 | #region SVG REGEX 20 | // TODO: Generalize case where last arg is Z 21 | static string command = @"^\s*{0}\s*([0-9e.\+\-,\s]+)\s*(.*)"; 22 | static string commandZ = @"^\s*{0}\s*([0-9e.\+\-,\s]+)\s*[Zz]\s*(.*)"; 23 | 24 | public static Regex widthReg = new Regex(@"width\s*=\s*""\s*([0-9.]+)px\s*"""); 25 | public static Regex heightReg = new Regex(@"height\s*=\s*""\s*([0-9.]+)px\s*"""); 26 | 27 | public static Regex scaleReg = new Regex(@"scale\(([0-9.\-\+\s]+),([0-9.\-\+\s]+)\)"); 28 | 29 | public static Regex moveToAbs = new Regex(string.Format(command, @"M")); 30 | public static Regex moveToRel = new Regex(string.Format(command, @"m")); 31 | public static Regex horzLineAbs = new Regex(string.Format(command, @"H")); 32 | public static Regex horzLineRel = new Regex(string.Format(command, @"h")); 33 | public static Regex vertLineAbs = new Regex(string.Format(command, @"V")); 34 | public static Regex vertLineRel = new Regex(string.Format(command, @"v")); 35 | public static Regex lineToAbs = new Regex(string.Format(command, @"L")); 36 | public static Regex lineToRel = new Regex(string.Format(command, @"l")); 37 | public static Regex curveAbs = new Regex(string.Format(command, @"C")); 38 | public static Regex curveRel = new Regex(string.Format(command, @"c")); 39 | public static Regex curveAbsZ = new Regex(string.Format(commandZ, @"C")); 40 | public static Regex curveRelZ = new Regex(string.Format(commandZ, @"c")); 41 | public static Regex smoothCurveAbs = new Regex(string.Format(command, @"S")); 42 | public static Regex smoothCurveRel = new Regex(string.Format(command, @"s")); 43 | public static Regex quadAbs = new Regex(string.Format(command, @"Q")); 44 | public static Regex quadRel = new Regex(string.Format(command, @"q")); 45 | public static Regex smoothQuadAbs = new Regex(string.Format(command, @"T")); 46 | public static Regex smoothQuadRel = new Regex(string.Format(command, @"t")); 47 | public static Regex arcToAbs = new Regex(string.Format(command, @"A")); 48 | public static Regex arcToRel = new Regex(string.Format(command, @"a")); 49 | public static Regex endPath = new Regex(@"^\s*[Zz]\s*(.*)"); 50 | 51 | #endregion 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Assets/Resources/Scripts/UTIL.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1484eb6d5257f4d0bb717724e7546d8a 3 | timeCreated: 1513651287 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/SVGs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 58bac0a347188425faa3c81f74432d05 3 | folderAsset: yes 4 | timeCreated: 1521410265 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/SVGs/ash_tree.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 831e1b26758594ca6be49d872d964770 3 | timeCreated: 1521513992 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/avengers.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 139 | 140 | -------------------------------------------------------------------------------- /Assets/SVGs/avengers.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4b6f3c95f21af4393af82edc84f8abad 3 | timeCreated: 1521510136 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/disney_and_mickey.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 47 | 48 | -------------------------------------------------------------------------------- /Assets/SVGs/disney_and_mickey.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 27a6b65359e234d4f9fd9acdda55a636 3 | timeCreated: 1521503998 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/floral_design.svg: -------------------------------------------------------------------------------- 1 | 2 | red backwards Floral Design 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | image/svg+xml 85 | 86 | Layer 1 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | -------------------------------------------------------------------------------- /Assets/SVGs/floral_design.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 214d6564e26bd4baea49dfd815d4c24a 3 | timeCreated: 1521326179 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/fox_head.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Assets/SVGs/fox_head.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cbe0cd58c081f4d9d8dfc326e507211c 3 | timeCreated: 1521412220 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/gnu_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.12, written by Peter Selinger 2001-2015 9 | 10 | 12 | 191 | 197 | 201 | 204 | 212 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /Assets/SVGs/gnu_logo.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7c08ac292ccec4ce7ae635db08358266 3 | timeCreated: 1521412220 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/nz_flag.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Assets/SVGs/nz_flag.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a89f77bff87bc4750b6462acbed7fd90 3 | timeCreated: 1521316550 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/palm_tree.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5135d4ff8333c424ba2312a32f6aca26 3 | timeCreated: 1521513992 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/tower_bridge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 50 | 51 | -------------------------------------------------------------------------------- /Assets/SVGs/tower_bridge.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6ca48707c9daf4ca590e04844b8ccbf5 3 | timeCreated: 1521514580 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/uk_map.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 88 | 89 | -------------------------------------------------------------------------------- /Assets/SVGs/uk_map.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b0c05a3c8b59f47c1bc0e56578e0c4bf 3 | timeCreated: 1521510711 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/SVGs/welsh_dragon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 51 | 52 | -------------------------------------------------------------------------------- /Assets/SVGs/welsh_dragon.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: db100a5dcbf8444e3a5640a1173b0a5a 3 | timeCreated: 1521513992 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e2f7aa6eff17c49e7b02bd05bd833e4f 3 | folderAsset: yes 4 | timeCreated: 1504309507 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Scenes/Demo.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Assets/Scenes/Demo.unity -------------------------------------------------------------------------------- /Assets/Scenes/Demo.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 13eb0a404b69a45a7b026bbde7109679 3 | timeCreated: 1504309495 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Images/DisneySpline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Images/DisneySpline.gif -------------------------------------------------------------------------------- /Images/Floral_Design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Images/Floral_Design.png -------------------------------------------------------------------------------- /Images/GNU_Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Images/GNU_Logo.png -------------------------------------------------------------------------------- /Images/SplineDemo1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Images/SplineDemo1.gif -------------------------------------------------------------------------------- /Images/SplineEditorDemo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Images/SplineEditorDemo1.png -------------------------------------------------------------------------------- /Images/SplineEditorDemo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/Images/SplineEditorDemo2.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Shealyn Hindenlang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2017.1.1f1 2 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shealynntate/Unity_Splines/04b8850997e54832e6ea56d52f5110213d2da644/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity Splines 2 | 3 | Creates bezier spline curves directly in Unity using a GUI interface that mimics the Adobe pen tool. You 4 | can also import SVG files and the program with convert the path into Unity splines.
5 | 6 | By simply adding an animation script to a GameObject and selecting the spline, the object will animate along the curve. 7 | 8 | ![Spline Demo](https://raw.githubusercontent.com/Shealynntate/Unity_Splines/master/Images/SplineDemo1.gif) 9 | 10 | ## Usage 11 | --- 12 | 13 | To animate a GameObject, simply add the *SplineAnimation.cs* script to the object and add the spline to the public field in the inspector. You can then set the move speed and whether or not you want the object to orient itself along the path. 14 |
15 | By attaching a particle system to the object, you can create arbitrary particle trails. 16 | 17 | ![Disney](https://raw.githubusercontent.com/Shealynntate/Unity_Splines/master/Images/DisneySpline.gif) 18 | 19 |
20 | Using the *Spline Editor* Menu you can use any SVG file that's imported into your project. 21 | 22 | ![Spline Editor Demo 1](https://raw.githubusercontent.com/Shealynntate/Unity_Splines/master/Images/SplineEditorDemo1.png) 23 | ![Spline Editor Demo 2](https://raw.githubusercontent.com/Shealynntate/Unity_Splines/master/Images/SplineEditorDemo2.png) 24 | 25 | Here are a few more examples of paths imported from SVG files. 26 | ![GNU](https://raw.githubusercontent.com/Shealynntate/Unity_Splines/master/Images/GNU_Logo.png) 27 | ![Floral Design](https://raw.githubusercontent.com/Shealynntate/Unity_Splines/master/Images/Floral_Design.png) 28 | 29 | ### Note 30 | --- 31 | This project is a work in progress. Some svg commands aren't yet implemented 32 | and the Spline Editor Window feature set is minimal at the moment. 33 | 34 | --------------------------------------------------------------------------------