Installed Surge, fixed compile errors, moved a bunch of external stuff into folder

This commit is contained in:
2025-09-10 10:53:04 +02:00
parent a3649c65b0
commit 52bd7ef585
433 changed files with 10589 additions and 4 deletions

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ee8affbccac6549ac82fb8f39c805b85
folderAsset: yes
timeCreated: 1500598980
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 848bc5a07520549dfbc8f3e76b14f33d
folderAsset: yes
timeCreated: 1500598980
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,127 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Node
m_Shader: {fileID: 4800000, guid: 11970eb7b004b42a88ab68ab6772c39f, type: 3}
m_ShaderKeywords: _EMISSION
m_LightmapFlags: 1
m_CustomRenderQueue: 8792
stringTagMap: {}
m_SavedProperties:
serializedVersion: 2
m_TexEnvs:
- first:
name: _BumpMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailAlbedoMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailMask
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailNormalMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _EmissionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MainTex
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MetallicGlossMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _OcclusionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _ParallaxMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- first:
name: _BumpScale
second: 1
- first:
name: _Cutoff
second: 0.5
- first:
name: _DetailNormalMapScale
second: 1
- first:
name: _DstBlend
second: 0
- first:
name: _GlossMapScale
second: 1
- first:
name: _Glossiness
second: 0.5
- first:
name: _GlossyReflections
second: 1
- first:
name: _Metallic
second: 0
- first:
name: _Mode
second: 0
- first:
name: _OcclusionStrength
second: 1
- first:
name: _Parallax
second: 0.02
- first:
name: _SmoothnessTextureChannel
second: 0
- first:
name: _SpecularHighlights
second: 1
- first:
name: _SrcBlend
second: 1
- first:
name: _UVSec
second: 0
- first:
name: _ZWrite
second: 1
m_Colors:
- first:
name: _Color
second: {r: 1, g: 1, b: 1, a: 0}
- first:
name: _EmissionColor
second: {r: 0, g: 0, b: 0, a: 1}

View File

@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 1642fbcacc9dc42ed934b98457781f23
timeCreated: 1479356539
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Art/Materials/Node.mat
uploadId: 467433

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 30cf75c7ac7044e7e926279230158d65
folderAsset: yes
timeCreated: 1500598981
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 958d750a1fed14c4287b588b02d25610
folderAsset: yes
timeCreated: 1500598981
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ef5ff669963e0470599f2a05b6612d19
folderAsset: yes
timeCreated: 1500598981
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,127 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Node
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: _EMISSION
m_LightmapFlags: 1
m_CustomRenderQueue: -1
stringTagMap: {}
m_SavedProperties:
serializedVersion: 2
m_TexEnvs:
- first:
name: _BumpMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailAlbedoMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailMask
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailNormalMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _EmissionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MainTex
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MetallicGlossMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _OcclusionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _ParallaxMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- first:
name: _BumpScale
second: 1
- first:
name: _Cutoff
second: 0.5
- first:
name: _DetailNormalMapScale
second: 1
- first:
name: _DstBlend
second: 0
- first:
name: _GlossMapScale
second: 1
- first:
name: _Glossiness
second: 0.5
- first:
name: _GlossyReflections
second: 1
- first:
name: _Metallic
second: 0
- first:
name: _Mode
second: 0
- first:
name: _OcclusionStrength
second: 1
- first:
name: _Parallax
second: 0.02
- first:
name: _SmoothnessTextureChannel
second: 0
- first:
name: _SpecularHighlights
second: 1
- first:
name: _SrcBlend
second: 1
- first:
name: _UVSec
second: 0
- first:
name: _ZWrite
second: 1
m_Colors:
- first:
name: _Color
second: {r: 0.7, g: 0.7, b: 0.7, a: 1}
- first:
name: _EmissionColor
second: {r: 0, g: 0, b: 0, a: 1}

View File

@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 2e1a4aa1789a64bf1ad83e97f3ec44d7
timeCreated: 1483156177
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Art/Models/Node/Materials/Node.mat
uploadId: 467433

View File

@@ -0,0 +1,84 @@
fileFormatVersion: 2
guid: eae229cde7c374059a09c8052360682c
timeCreated: 1483156177
licenseType: Store
ModelImporter:
serializedVersion: 19
fileIDToRecycleName:
100000: //RootNode
400000: //RootNode
2300000: //RootNode
3300000: //RootNode
4300000: Node
9500000: //RootNode
materials:
importMaterials: 1
materialName: 0
materialSearch: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
motionNodeName:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
clipAnimations: []
isReadable: 1
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
importBlendShapes: 1
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
optimizeMeshForGPU: 1
keepQuads: 0
weldVertices: 1
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVPackMargin: 4
useFileScale: 1
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
importAnimation: 1
copyAvatar: 0
humanDescription:
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
rootMotionBoneName:
hasTranslationDoF: 0
lastHumanDescriptionAvatarSource: {instanceID: 0}
animationType: 0
humanoidOversampling: 1
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Art/Models/Node/Node.fbx
uploadId: 467433

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 310ca64957859452682f4f8b755d00e3
folderAsset: yes
timeCreated: 1500598981
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 920f79e699daa4471bc705a40d5ea68a
folderAsset: yes
timeCreated: 1500598981
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,127 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: ScaleNode
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: _EMISSION
m_LightmapFlags: 1
m_CustomRenderQueue: -1
stringTagMap: {}
m_SavedProperties:
serializedVersion: 2
m_TexEnvs:
- first:
name: _BumpMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailAlbedoMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailMask
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailNormalMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _EmissionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MainTex
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MetallicGlossMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _OcclusionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _ParallaxMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- first:
name: _BumpScale
second: 1
- first:
name: _Cutoff
second: 0.5
- first:
name: _DetailNormalMapScale
second: 1
- first:
name: _DstBlend
second: 0
- first:
name: _GlossMapScale
second: 1
- first:
name: _Glossiness
second: 0.5
- first:
name: _GlossyReflections
second: 1
- first:
name: _Metallic
second: 0
- first:
name: _Mode
second: 0
- first:
name: _OcclusionStrength
second: 1
- first:
name: _Parallax
second: 0.02
- first:
name: _SmoothnessTextureChannel
second: 0
- first:
name: _SpecularHighlights
second: 1
- first:
name: _SrcBlend
second: 1
- first:
name: _UVSec
second: 0
- first:
name: _ZWrite
second: 1
m_Colors:
- first:
name: _Color
second: {r: 0.7, g: 0.7, b: 0.7, a: 1}
- first:
name: _EmissionColor
second: {r: 0, g: 0, b: 0, a: 1}

View File

@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 0ac95597f20c94c12a751f4ee6918ecc
timeCreated: 1483123098
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Art/Models/ScaleNode/Materials/ScaleNode.mat
uploadId: 467433

View File

@@ -0,0 +1,87 @@
fileFormatVersion: 2
guid: c0de5c847168f47b48791e9f1912e7c0
timeCreated: 1483123098
licenseType: Store
ModelImporter:
serializedVersion: 19
fileIDToRecycleName:
100000: //RootNode
100002: ScaleJoint
400000: //RootNode
400002: ScaleJoint
2300000: //RootNode
3300000: //RootNode
4300000: Node
9500000: //RootNode
13700000: //RootNode
materials:
importMaterials: 1
materialName: 0
materialSearch: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
motionNodeName:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
animationCompression: 3
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
clipAnimations: []
isReadable: 1
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
importBlendShapes: 1
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
optimizeMeshForGPU: 1
keepQuads: 0
weldVertices: 1
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVPackMargin: 4
useFileScale: 1
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
importAnimation: 0
copyAvatar: 0
humanDescription:
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
rootMotionBoneName:
hasTranslationDoF: 0
lastHumanDescriptionAvatarSource: {instanceID: 0}
animationType: 0
humanoidOversampling: 1
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Art/Models/ScaleNode/ScaleNode.fbx
uploadId: 467433

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ebfbee500b6ab435b94f495a201f83a7
folderAsset: yes
timeCreated: 1500598980
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
/// </summary>
Shader "Invisible"
{
Subshader
{
Pass
{
GLSLPROGRAM
#ifdef VERTEX
void main() {}
#endif
#ifdef FRAGMENT
void main() {}
#endif
ENDGLSL
}
}
Subshader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct v2f
{
fixed4 position : SV_POSITION;
};
v2f vert()
{
v2f o;
o.position = fixed4(0,0,0,0);
return o;
}
fixed4 frag() : COLOR
{
return fixed4(0,0,0,0);
}
ENDCG
}
}
}

View File

@@ -0,0 +1,16 @@
fileFormatVersion: 2
guid: 11970eb7b004b42a88ab68ab6772c39f
timeCreated: 1482204536
licenseType: Store
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Art/Shaders/Invisible.shader
uploadId: 467433

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 274948d5adb104b28a8d42ee1308cee0
folderAsset: yes
timeCreated: 1500598980
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Forces pivot mode to center so an anchor's pivot is always correct while adjusting a spline.
///
/// </summary>
using UnityEditor;
using UnityEngine;
namespace Pixelplacement
{
[CustomEditor(typeof(SplineAnchor))]
public class SplineAnchorEditor : UnityEditor.Editor
{
//Scene GUI:
void OnSceneGUI ()
{
//ensure pivot is used so anchor selection has a proper transform origin:
if (Tools.pivotMode == PivotMode.Center)
{
Tools.pivotMode = PivotMode.Pivot;
}
}
//Gizmos:
[DrawGizmo(GizmoType.Selected)]
static void RenderCustomGizmo(Transform objectTransform, GizmoType gizmoType)
{
if (objectTransform.parent != null)
{
SplineEditor.RenderCustomGizmo(objectTransform.parent, gizmoType);
}
}
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 15d4e254e3652404797dcee644ec6a84
timeCreated: 1483388323
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Editor/SplineAnchorEditor.cs
uploadId: 467433

View File

@@ -0,0 +1,136 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Draws all controls for a spline.
///
/// </summary>
using UnityEditor;
using UnityEngine;
namespace Pixelplacement
{
[CustomEditor(typeof(Spline))]
public class SplineEditor : UnityEditor.Editor
{
//Private Variables
Spline _target;
//Init:
void OnEnable ()
{
_target = target as Spline;
}
//Inspector:
public override void OnInspectorGUI ()
{
//draw:
DrawDefaultInspector ();
DrawAddButton ();
}
//Gizmo Overload:
[DrawGizmo(GizmoType.Selected)]
public static void RenderCustomGizmo (Transform objectTransform, GizmoType gizmoType)
{
DrawTools (objectTransform);
}
//Scene GUI:
void OnSceneGUI ()
{
DrawTools ((target as Spline).transform);
}
//Draw Methods:
void DrawAddButton ()
{
if (GUILayout.Button ("Extend"))
{
Undo.RegisterCreatedObjectUndo (_target.AddAnchors (1) [0], "Extend Spline");
}
}
static void DrawTools (Transform target)
{
Spline spline = target.GetComponent<Spline> ();
if (spline == null) return;
if (target.transform.childCount == 0) return;
//set primary draw color:
Handles.color = spline.SecondaryColor;
for (int i = 0; i < spline.Anchors.Length; i++)
{
//refs:
Quaternion lookRotation = Quaternion.identity;
SplineAnchor currentAnchor = spline.Anchors[i];
//scale geometry:
currentAnchor.InTangent.localScale = Vector3.one * (spline.toolScale * 1.3f);
currentAnchor.OutTangent.localScale = Vector3.one * (spline.toolScale * 1.3f);
currentAnchor.Anchor.localScale = Vector3.one * (spline.toolScale * 2.1f);
if (spline.toolScale > 0)
{
//draw persistent identifiers that face the scene view camera and only draw if the corrosponding tangent is active:
if (currentAnchor.OutTangent.gameObject.activeSelf)
{
//connection:
Handles.DrawDottedLine (currentAnchor.Anchor.position, currentAnchor.OutTangent.position, 3);
//indicators:
if (SceneView.currentDrawingSceneView != null)
{
lookRotation = Quaternion.LookRotation ((SceneView.currentDrawingSceneView.camera.transform.position - currentAnchor.OutTangent.position).normalized);
Handles.CircleHandleCap (0, currentAnchor.OutTangent.position, lookRotation, spline.toolScale * .65f, EventType.Repaint);
Handles.CircleHandleCap (0, currentAnchor.OutTangent.position, lookRotation, spline.toolScale * .25f, EventType.Repaint);
}
}
if (currentAnchor.InTangent.gameObject.activeSelf)
{
//connection:
Handles.DrawDottedLine (currentAnchor.Anchor.position, currentAnchor.InTangent.position, 3);
//indicators:
if (SceneView.currentDrawingSceneView != null)
{
lookRotation = Quaternion.LookRotation ((SceneView.currentDrawingSceneView.camera.transform.position - currentAnchor.InTangent.position).normalized);
Handles.CircleHandleCap (0, currentAnchor.InTangent.position, lookRotation, spline.toolScale * .65f, EventType.Repaint);
Handles.CircleHandleCap (0, currentAnchor.InTangent.position, lookRotation, spline.toolScale * .25f, EventType.Repaint);
}
}
//anchor tools:
if (SceneView.currentDrawingSceneView != null)
{
lookRotation = Quaternion.LookRotation ((SceneView.currentDrawingSceneView.camera.transform.position - currentAnchor.Anchor.position).normalized);
Handles.CircleHandleCap (0, currentAnchor.Anchor.position, lookRotation, spline.toolScale, EventType.Repaint);
}
//identify path origin:
if (spline.direction == SplineDirection.Forward && i == 0 || spline.direction == SplineDirection.Backwards && i == spline.Anchors.Length - 1)
{
Handles.CircleHandleCap (0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .8f, EventType.Repaint);
Handles.CircleHandleCap (0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .75f, EventType.Repaint);
Handles.CircleHandleCap (0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .5f, EventType.Repaint);
Handles.CircleHandleCap (0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .45f, EventType.Repaint);
Handles.CircleHandleCap (0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .25f, EventType.Repaint);
}
}
}
//draw spline:
for (int i = 0; i < spline.Anchors.Length - 1; i++)
{
SplineAnchor startAnchor = spline.Anchors[i];
SplineAnchor endAnchor = spline.Anchors[i+1];
Handles.DrawBezier (startAnchor.Anchor.position, endAnchor.Anchor.position, startAnchor.OutTangent.position, endAnchor.InTangent.position, spline.color, null, 2);
}
}
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: bf584abde32dd4d28abdf7112e4cd744
timeCreated: 1483123495
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Editor/SplineEditor.cs
uploadId: 467433

View File

@@ -0,0 +1,38 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Forces pivot mode to center so an anchor's pivot is always correct while adjusting a spline.
///
/// </summary>
using UnityEditor;
using UnityEngine;
namespace Pixelplacement
{
[CustomEditor(typeof(SplineTangent))]
public class SplineTangentEditor : UnityEditor.Editor
{
//Scene GUI:
void OnSceneGUI ()
{
//ensure pivot is used so anchor selection has a proper transform origin:
if (Tools.pivotMode == PivotMode.Center)
{
Tools.pivotMode = PivotMode.Pivot;
}
}
//Gizmos:
[DrawGizmo(GizmoType.Selected)]
static void RenderCustomGizmo(Transform objectTransform, GizmoType gizmoType)
{
if (objectTransform.parent != null && objectTransform.parent.parent != null)
{
SplineEditor.RenderCustomGizmo(objectTransform.parent.parent, gizmoType);
}
}
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: def6dcf256e22a049928f540963d59f0
timeCreated: 1532464219
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Editor/SplineTangentEditor.cs
uploadId: 467433

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 76cb8730de7f6dc4196915f9f2ca0eb6
folderAsset: yes
timeCreated: 1505174723
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,105 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Methods for evaluating curves.
///
/// </summary>
using UnityEngine;
namespace Pixelplacement
{
public static class BezierCurves
{
//Quadratic Bezier:
public static Vector3 GetPoint (Vector3 startPosition, Vector3 controlPoint, Vector3 endPosition, float percentage)
{
percentage = Mathf.Clamp01 (percentage);
float oneMinusT = 1f - percentage;
return oneMinusT * oneMinusT * startPosition + 2f * oneMinusT * percentage * controlPoint + percentage * percentage * endPosition;
}
public static Vector3 GetFirstDerivative (Vector3 startPoint, Vector3 controlPoint, Vector3 endPosition, float percentage)
{
percentage = Mathf.Clamp01 (percentage);
return 2f * (1f - percentage) * (controlPoint - startPoint) + 2f * percentage * (endPosition - controlPoint);
}
//Cubic Bezier:
public static Vector3 GetPoint (Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, float percentage, bool evenDistribution, int distributionSteps)
{
if (evenDistribution)
{
int maxPoint = distributionSteps + 1;
float[] arcLengths = new float[maxPoint];
Vector3 previousPoint = Locate(startPosition, endPosition, startTangent, endTangent, 0);
float sum = 0;
//store arc lengths:
for (int i = 1; i < maxPoint; i++)
{
Vector3 p = Locate(startPosition, endPosition, startTangent, endTangent, i / (float)maxPoint);
sum += Vector3.Distance(previousPoint, p);
arcLengths[i] = sum;
previousPoint = p;
}
float targetLength = percentage * arcLengths[distributionSteps];
//search:
int low = 0;
int high = distributionSteps;
int index = 0;
while (low < high)
{
index = low + (((high - low) / 2) | 0);
if (arcLengths[index] < targetLength)
{
low = index + 1;
}
else
{
high = index;
}
}
//adjust:
if (arcLengths[index] > targetLength)
{
index--;
}
float lengthBefore = arcLengths[index];
//interpolate or use as is:
if (lengthBefore == targetLength)
{
return Locate(startPosition, endPosition, startTangent, endTangent, index / distributionSteps);
}
else
{
return Locate(startPosition, endPosition, startTangent, endTangent, (index + (targetLength - lengthBefore) / (arcLengths[index + 1] - lengthBefore)) / distributionSteps);
}
}
return Locate(startPosition, endPosition, startTangent, endTangent, percentage);
}
public static Vector3 GetFirstDerivative (Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, float percentage)
{
percentage = Mathf.Clamp01 (percentage);
float oneMinusT = 1f - percentage;
return 3f * oneMinusT * oneMinusT * (startTangent - startPosition) + 6f * oneMinusT * percentage * (endTangent - startTangent) + 3f * percentage * percentage * (endPosition - endTangent);
}
private static Vector3 Locate(Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, float percentage)
{
percentage = Mathf.Clamp01(percentage);
float oneMinusT = 1f - percentage;
return oneMinusT * oneMinusT * oneMinusT * startPosition + 3f * oneMinusT * oneMinusT * percentage * startTangent + 3f * oneMinusT * percentage * percentage * endTangent + percentage * percentage * percentage * endPosition;
}
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 09965dbc9fd354a369b626ee0e9ba143
timeCreated: 1482974494
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Objects/BezierCurves.cs
uploadId: 467433

View File

@@ -0,0 +1,29 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Holds details of a spline's curve.
///
/// </summary>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Pixelplacement
{
public struct CurveDetail
{
//Public Variables:
public int currentCurve;
public float currentCurvePercentage;
//Constructor:
public CurveDetail (int currentCurve, float currentCurvePercentage)
{
this.currentCurve = currentCurve;
this.currentCurvePercentage = currentCurvePercentage;
}
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 5612bd02e9949884bbed28239455d20e
timeCreated: 1505174773
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Objects/CurveDetail.cs
uploadId: 467433

View File

@@ -0,0 +1,527 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Creates and manages splines.
///
/// </summary>
using UnityEngine;
using System.Collections.Generic;
using System;
namespace Pixelplacement
{
public enum SplineDirection { Forward, Backwards }
[ExecuteInEditMode]
public class Spline : MonoBehaviour
{
//Public Events:
public event Action OnSplineChanged;
//Private Classes
private class SplineReparam
{
//Public Variables:
public float length;
public float percentage;
//Constructors:
public SplineReparam(float length, float percentage)
{
this.length = length;
this.percentage = percentage;
}
}
//Public Variables:
public Color color = Color.yellow;
[Range(0, 1)] public float toolScale = .1f;
public TangentMode defaultTangentMode;
public SplineDirection direction;
public bool loop;
public SplineFollower[] followers;
//Private Variables:
private SplineAnchor[] _anchors;
private int _curveCount;
private int _previousAnchorCount;
private int _previousChildCount;
private bool _wasLooping;
private bool _previousLoopChoice;
private bool _anchorsChanged;
private SplineDirection _previousDirection;
private float _curvePercentage = 0;
private int _operatingCurve = 0;
private float _currentCurve = 0;
private int _previousLength;
private int _slicesPerCurve = 10;
private List<SplineReparam> _splineReparams = new List<SplineReparam>();
private bool _lengthDirty = true;
//Public Properties:
public float Length
{
get;
private set;
}
public SplineAnchor[] Anchors
{
get
{
//if loop is toggled make sure we reset anchors:
if (loop != _wasLooping)
{
_previousAnchorCount = -1;
_wasLooping = loop;
}
if (!loop)
{
if (transform.childCount != _previousAnchorCount || transform.childCount == 0)
{
_anchors = GetComponentsInChildren<SplineAnchor>();
_previousAnchorCount = transform.childCount;
}
return _anchors;
}
else
{
if (transform.childCount != _previousAnchorCount || transform.childCount == 0)
{
//for a loop we need an array whose last element is the first element:
_anchors = GetComponentsInChildren<SplineAnchor>();
Array.Resize(ref _anchors, _anchors.Length + 1);
_anchors[_anchors.Length - 1] = _anchors[0];
_previousAnchorCount = transform.childCount;
}
return _anchors;
}
}
}
public Color SecondaryColor
{
get
{
Color secondaryColor = Color.Lerp(color, Color.black, .2f);
return secondaryColor;
}
}
//Init:
void Reset()
{
//if we don't have at least 2 anchors, fix it:
if (Anchors.Length < 2)
{
AddAnchors(2 - Anchors.Length);
}
}
//Loop:
void Update()
{
//place followers (if supplied and something relavent changed):
if (followers != null && followers.Length > 0 && Anchors.Length >= 2)
{
bool needToUpdate = false;
//was anything else changed?
if (_anchorsChanged || _previousChildCount != transform.childCount || direction != _previousDirection || loop != _previousLoopChoice)
{
_previousChildCount = transform.childCount;
_previousLoopChoice = loop;
_previousDirection = direction;
_anchorsChanged = false;
needToUpdate = true;
}
//were any followers moved?
for (int i = 0; i < followers.Length; i++)
{
if (followers[i].WasMoved || needToUpdate)
{
followers[i].UpdateOrientation(this);
}
}
}
//manage anchors:
bool anchorChanged = false;
if (Anchors.Length > 1)
{
for (int i = 0; i < Anchors.Length; i++)
{
//if this spline has changed notify and wipe cached percentage:
if (Anchors[i].Changed)
{
anchorChanged = true;
Anchors[i].Changed = false;
_anchorsChanged = true;
}
//if this isn't a loop then the first and last tangents are unnecessary:
if (!loop)
{
//turn first tangent off:
if (i == 0)
{
Anchors[i].SetTangentStatus(false, true);
continue;
}
//turn last tangent off:
if (i == Anchors.Length - 1)
{
Anchors[i].SetTangentStatus(true, false);
continue;
}
//turn both tangents on:
Anchors[i].SetTangentStatus(true, true);
}
else
{
//all tangents are needed in a loop:
Anchors[i].SetTangentStatus(true, true);
}
}
}
//length changed:
if (_previousLength != Anchors.Length || anchorChanged)
{
HangleLengthChange();
_previousLength = Anchors.Length;
}
}
//Event Handlers:
private void HangleLengthChange()
{
_lengthDirty = true;
//fire event:
OnSplineChanged?.Invoke();
}
//Private Methods:
private float Reparam(float percent)
{
if (_lengthDirty) CalculateLength();
//TODO: consider optimization of reversing this if the percent is > .5f to go in either direction:
for (int i = 0; i < _splineReparams.Count; i++)
{
float currentPercentage = _splineReparams[i].length / Length;
if (currentPercentage == percent)
{
return _splineReparams[i].percentage;
}
if (currentPercentage > percent)
{
float fromP = _splineReparams[i - 1].length / Length;
float toP = currentPercentage;
//slide scale to 0:
float maxAdjusted = toP - fromP;
float percentAdjusted = percent - fromP;
//find out percentage:
float inBetweenPercentage = percentAdjusted / maxAdjusted;
float location = Mathf.Lerp(_splineReparams[i - 1].percentage, _splineReparams[i].percentage, inBetweenPercentage);
return location;
}
}
return 0;
}
//Public Methods:
/// <summary>
/// Calculates the length of this spline and puts the result into the Length property.
/// </summary>
public void CalculateLength()
{
//prep:
int totalSlices = (Anchors.Length - 1) * _slicesPerCurve;
Length = 0;
_splineReparams.Clear();
//initial entries:
_splineReparams.Add(new SplineReparam(0, 0));
//find spline length:
for (int i = 1; i < totalSlices + 1; i++)
{
//percent ends:
float percent = i / (float)totalSlices;
float previousPercent = (i - 1) / (float)totalSlices;
//position ends:
Vector3 start = GetPosition(previousPercent, false);
Vector3 end = GetPosition(percent, false);
//length:
float distance = Vector3.Distance(start, end);
Length += distance;
//reparameterization cache:
_splineReparams.Add(new SplineReparam(Length, percent));
}
_lengthDirty = false;
return;
}
/// <summary>
/// Get the up vector at a percentage along the spline.
/// </summary>
public Vector3 Up(float percentage, bool normalized = true)
{
Quaternion lookRotation = Quaternion.LookRotation(GetDirection(percentage, normalized));
return lookRotation * Vector3.up;
}
/// <summary>
/// Get the right vector at a percentage along the spline.
/// </summary>
public Vector3 Right(float percentage, bool normalized = true)
{
Quaternion lookRotation = Quaternion.LookRotation(GetDirection(percentage, normalized));
return lookRotation * Vector3.right;
}
/// <summary>
/// Get the forward vector at a percentage along the spline - this is simply a wrapper for the direction since they are the same thing.
/// </summary>
public Vector3 Forward(float percentage, bool normalized = true)
{
return GetDirection(percentage, normalized);
}
/// <summary>
/// Returns a facing vector at the given percentage along the spline to allow content to properly orient along the spline.
/// </summary>
public Vector3 GetDirection(float percentage, bool normalized = true)
{
if (normalized) percentage = Reparam(percentage);
//get direction:
CurveDetail curveDetail = GetCurve(percentage);
//avoid an error in editor usage where this index can be -1:
if (curveDetail.currentCurve < 0) return Vector3.zero;
SplineAnchor startAnchor = Anchors[curveDetail.currentCurve];
SplineAnchor endAnchor = Anchors[curveDetail.currentCurve + 1];
return BezierCurves.GetFirstDerivative(startAnchor.Anchor.position, endAnchor.Anchor.position, startAnchor.OutTangent.position, endAnchor.InTangent.position, curveDetail.currentCurvePercentage).normalized;
}
/// <summary>
/// Returns a position on the spline at the given percentage.
/// </summary>
public Vector3 GetPosition(float percentage, bool normalized = true)
{
if (normalized) percentage = Reparam(percentage);
//evaluate curve:
CurveDetail curveDetail = GetCurve(percentage);
//avoid an error in editor usage where this index can be -1:
if (curveDetail.currentCurve < 0) return Vector3.zero;
SplineAnchor startAnchor = Anchors[curveDetail.currentCurve];
SplineAnchor endAnchor = Anchors[curveDetail.currentCurve + 1];
return BezierCurves.GetPoint(startAnchor.Anchor.position, endAnchor.Anchor.position, startAnchor.OutTangent.position, endAnchor.InTangent.position, curveDetail.currentCurvePercentage, true, 100);
}
/// <summary>
/// Returns a position on the spline at the given percentage with a relative offset.
/// </summary>
public Vector3 GetPosition(float percentage, Vector3 relativeOffset, bool normalized = true)
{
if (normalized) percentage = Reparam(percentage);
//get position and look rotation:
Vector3 position = GetPosition(percentage);
Quaternion lookRotation = Quaternion.LookRotation(GetDirection(percentage));
//get each axis at the current position:
Vector3 up = lookRotation * Vector3.up;
Vector3 right = lookRotation * Vector3.right;
Vector3 forward = lookRotation * Vector3.forward;
//translate position:
Vector3 offset = position + right * relativeOffset.x;
offset += up * relativeOffset.y;
offset += forward * relativeOffset.z;
return offset;
}
/// <summary>
/// Given a world point and a number of divisions (think resolution) this returns the closest point on the spline.
/// </summary>
public float ClosestPoint(Vector3 point, int divisions = 100)
{
//make sure we have at least one division:
if (divisions <= 0) divisions = 1;
//variables:
float shortestDistance = float.MaxValue;
Vector3 position = Vector3.zero;
Vector3 offset = Vector3.zero;
float closestPercentage = 0;
float percentage = 0;
float distance = 0;
//iterate spline and find the closest point on the spline to the provided point:
for (float i = 0; i < divisions + 1; i++)
{
percentage = i / divisions;
position = GetPosition(percentage);
offset = position - point;
distance = offset.sqrMagnitude;
//if this point is closer than any others so far:
if (distance < shortestDistance)
{
shortestDistance = distance;
closestPercentage = percentage;
}
}
return closestPercentage;
}
/// <summary>
/// Makes a spline longer.
/// </summary>
public GameObject[] AddAnchors(int count)
{
//refs:
GameObject anchorTemplate = Resources.Load("Anchor") as GameObject;
//create return array:
GameObject[] returnObjects = new GameObject[count];
for (int i = 0; i < count; i++)
{
//previous anchor refs:
Transform previousPreviousAnchor = null;
Transform previousAnchor = null;
if (Anchors.Length == 1)
{
previousPreviousAnchor = transform;
previousAnchor = Anchors[0].transform;
}
else if (Anchors.Length > 1)
{
previousPreviousAnchor = Anchors[Anchors.Length - 2].transform;
previousAnchor = Anchors[Anchors.Length - 1].transform;
}
//create a new anchor:
GameObject newAnchor = Instantiate<GameObject>(anchorTemplate);
newAnchor.name = newAnchor.name.Replace("(Clone)", "");
SplineAnchor anchor = newAnchor.GetComponent<SplineAnchor>();
anchor.tangentMode = defaultTangentMode;
newAnchor.transform.parent = transform;
newAnchor.transform.rotation = Quaternion.LookRotation(transform.forward);
//tilt tangents for variety as we add new anchors:
//anchor.Tilt (new Vector3 (0, 0, 0));
anchor.InTangent.Translate(Vector3.up * .5f);
anchor.OutTangent.Translate(Vector3.up * -.5f);
//position new anchor:
if (previousPreviousAnchor != null && previousAnchor != null)
{
//determine direction for next placement:
Vector3 direction = (previousAnchor.position - previousPreviousAnchor.position).normalized;
if (direction == Vector3.zero) direction = transform.forward;
//place from the previous anchor in the correct direction:
newAnchor.transform.position = previousAnchor.transform.position + (direction * 1.5f);
}
else
{
newAnchor.transform.localPosition = Vector3.zero;
}
//catalog this new anchor for return:
returnObjects[i] = newAnchor;
}
return returnObjects;
}
/// <summary>
/// Gets the current curve at the percentage.
/// </summary>
public CurveDetail GetCurve(float percentage)
{
//clamp or loop percentage:
if (loop)
{
percentage = Mathf.Repeat(percentage, 1);
}
else
{
percentage = Mathf.Clamp01(percentage);
}
//curve identification and evaluation:
if (Anchors.Length == 2)
{
//direction reversed?
if (direction == SplineDirection.Backwards)
{
percentage = 1 - percentage;
}
//simply evaluate the curve since there is only one:
return new CurveDetail(0, percentage);
}
else
{
//figure out which curve we are operating on from the spline and a percentage along it:
_curveCount = Anchors.Length - 1;
_currentCurve = _curveCount * percentage;
if ((int)_currentCurve == _curveCount)
{
_currentCurve = _curveCount - 1;
_curvePercentage = 1;
}
else
{
_curvePercentage = _currentCurve - (int)_currentCurve;
}
_currentCurve = (int)_currentCurve;
_operatingCurve = (int)_currentCurve;
//direction reversed?
if (direction == SplineDirection.Backwards)
{
_curvePercentage = 1 - _curvePercentage;
_operatingCurve = (_curveCount - 1) - _operatingCurve;
}
return new CurveDetail(_operatingCurve, _curvePercentage);
}
}
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: f1ec11ed173ba4d8d99e75c4bf174d82
timeCreated: 1483123464
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Objects/Spline.cs
uploadId: 467433

View File

@@ -0,0 +1,268 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Interface for a spline's anchor and tangents.
///
/// </summary>
using UnityEngine;
using System.Collections;
namespace Pixelplacement
{
public enum TangentMode {Mirrored, Aligned, Free}
[ExecuteInEditMode]
public class SplineAnchor : MonoBehaviour
{
//Public Variables:
public TangentMode tangentMode;
//Public Properties:
public bool RenderingChange
{
get; set;
}
public bool Changed
{
get; set;
}
public Transform Anchor
{
get
{
if (!_initialized) Initialize();
return _anchor;
}
private set
{
_anchor = value;
}
}
public Transform InTangent
{
get
{
if (!_initialized) Initialize();
return _inTangent;
}
private set
{
_inTangent = value;
}
}
public Transform OutTangent
{
get
{
if (!_initialized) Initialize();
return _outTangent;
}
private set
{
_outTangent = value;
}
}
//Private Variables:
bool _initialized;
[SerializeField][HideInInspector] Transform _masterTangent;
[SerializeField][HideInInspector] Transform _slaveTangent;
TangentMode _previousTangentMode;
Vector3 _previousInPosition;
Vector3 _previousOutPosition;
Vector3 _previousAnchorPosition;
Bounds _skinnedBounds;
Transform _anchor;
Transform _inTangent;
Transform _outTangent;
//Init:
void Awake ()
{
Initialize ();
}
//Loop:
void Update ()
{
//don't let an anchor scale:
transform.localScale = Vector3.one;
//initialization:
if (!_initialized)
{
Initialize ();
}
//override any skinned mesh bounds changes:
Anchor.localPosition = Vector3.zero;
//has the anchor moved?
if (_previousAnchorPosition != transform.position)
{
Changed = true;
RenderingChange = true;
_previousAnchorPosition = transform.position;
}
//run a tangent operation if mode has changed:
if (_previousTangentMode != tangentMode)
{
Changed = true;
RenderingChange = true;
TangentChanged ();
_previousTangentMode = tangentMode;
}
//detect tangent movements:
if (InTangent.localPosition != _previousInPosition)
{
Changed = true;
RenderingChange = true;
_previousInPosition = InTangent.localPosition;
_masterTangent = InTangent;
_slaveTangent = OutTangent;
TangentChanged ();
return;
}
if (OutTangent.localPosition != _previousOutPosition)
{
Changed = true;
RenderingChange = true;
_previousOutPosition = OutTangent.localPosition;
_masterTangent = OutTangent;
_slaveTangent = InTangent;
TangentChanged ();
return;
}
}
//Private Methods:
void TangentChanged ()
{
//calculate tangent positions:
switch (tangentMode)
{
case TangentMode.Free:
break;
case TangentMode.Mirrored:
Vector3 mirroredOffset = _masterTangent.position - transform.position;
_slaveTangent.position = transform.position - mirroredOffset;
break;
case TangentMode.Aligned:
float distance = Vector3.Distance (_slaveTangent.position, transform.position);
Vector3 alignedOffset = (_masterTangent.position - transform.position).normalized;
_slaveTangent.position = transform.position - (alignedOffset * distance);
break;
}
//cache tangent positions:
_previousInPosition = InTangent.localPosition;
_previousOutPosition = OutTangent.localPosition;
}
//Private Methods:
void Initialize ()
{
_initialized = true;
//grabs references:
InTangent = transform.GetChild (0);
OutTangent = transform.GetChild (1);
Anchor = transform.GetChild (2);
//prepopulate master and slave tangents:
_masterTangent = InTangent;
_slaveTangent = OutTangent;
//hide some things to reduce clutter:
Anchor.hideFlags = HideFlags.HideInHierarchy;
foreach (var item in GetComponentsInChildren<Renderer>())
{
if (Application.isEditor)
{
item.sharedMaterial.hideFlags = HideFlags.HideInInspector;
}
else
{
Destroy(item);
}
}
foreach (var item in GetComponentsInChildren<MeshFilter>())
{
if (Application.isEditor)
{
item.hideFlags = HideFlags.HideInInspector;
}
else
{
Destroy(item);
}
}
foreach (var item in GetComponentsInChildren<MeshRenderer>())
{
if (Application.isEditor)
{
item.hideFlags = HideFlags.HideInInspector;
}
else
{
Destroy(item);
}
}
foreach (var item in GetComponentsInChildren<SkinnedMeshRenderer>())
{
if (Application.isEditor)
{
item.hideFlags = HideFlags.HideInInspector;
}
}
//synchronize status variables:
_previousTangentMode = tangentMode;
_previousInPosition = InTangent.localPosition;
_previousOutPosition = OutTangent.localPosition;
_previousAnchorPosition = transform.position;
}
//Public Methods:
public void SetTangentStatus (bool inStatus, bool outStatus)
{
InTangent.gameObject.SetActive (inStatus);
OutTangent.gameObject.SetActive (outStatus);
}
public void Tilt (Vector3 angles)
{
//save current rotation and rotate as requested:
Quaternion rotation = transform.localRotation;
transform.Rotate (angles);
//get world position of tangents:
Vector3 inPosition = InTangent.position;
Vector3 outPosition = OutTangent.position;
//reverse rotation and set tangent positions:
//transform.localRotation = rotation;
InTangent.position = inPosition;
OutTangent.position = outPosition;
}
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 486ab05eb713a42cbb73a3d0cadf09ed
timeCreated: 1483118697
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Objects/SplineAnchor.cs
uploadId: 467433

View File

@@ -0,0 +1,65 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Used for easily attaching objects to a spline for inspector usage.
///
/// </summary>
using UnityEngine;
using System.Collections;
namespace Pixelplacement
{
[System.Serializable]
public class SplineFollower
{
//Public Variables:
public Transform target;
public float percentage = -1;
public bool faceDirection;
//Public Properties:
public bool WasMoved
{
get
{
if (percentage != _previousPercentage || faceDirection != _previousFaceDirection) {
_previousPercentage = percentage;
_previousFaceDirection = faceDirection;
return true;
} else {
return false;
}
}
}
//Private Variables:
float _previousPercentage;
bool _previousFaceDirection;
bool _detached;
//Public Methods:
public void UpdateOrientation (Spline spline)
{
if (target == null) return;
//clamp percentage:
if (!spline.loop) percentage = Mathf.Clamp01 (percentage);
//look in direction of spline?
if (faceDirection)
{
if (spline.direction == SplineDirection.Forward)
{
target.LookAt (target.position + spline.GetDirection (percentage));
}else{
target.LookAt (target.position - spline.GetDirection (percentage));
}
}
target.position = spline.GetPosition (percentage);
}
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 484db4cb0f8e7f24b8e7012ba84c9e47
timeCreated: 1485806915
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Objects/SplineFollower.cs
uploadId: 467433

View File

@@ -0,0 +1,19 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// A helper for allowing correct selection in the scene view instead of choosing the prefab root which is normal Unity operation.
///
/// </summary>
using UnityEngine;
using System.Collections;
namespace Pixelplacement
{
[SelectionBase]
public class SplineTangent : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 5980d28f81eb545d78e1d84e1449a10f
timeCreated: 1483149639
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Objects/SplineTangent.cs
uploadId: 467433

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 7c8d4f0ed438f4034b2a58cd18d03486
folderAsset: yes
timeCreated: 1500598979
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,299 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1000013506235850}
m_IsPrefabParent: 1
--- !u!1 &1000010923298536
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4000012482932774}
- component: {fileID: 33000014224897370}
- component: {fileID: 23000013987882740}
- component: {fileID: 114000010166402902}
m_Layer: 0
m_Name: OutTangent
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1000013118930838
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4000012704102164}
m_Layer: 0
m_Name: ScaleJoint
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1000013281444082
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4000012395411742}
- component: {fileID: 33000012835484144}
- component: {fileID: 23000011320280670}
- component: {fileID: 114000013738431472}
m_Layer: 0
m_Name: InTangent
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1000013506235850
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4000011036911136}
- component: {fileID: 33000010540804998}
- component: {fileID: 137000011316136332}
- component: {fileID: 114000013814947972}
m_Layer: 0
m_Name: Anchor
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4000011036911136
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000013506235850}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 4000012395411742}
- {fileID: 4000012482932774}
- {fileID: 4000012704102164}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &4000012395411742
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000013281444082}
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -0.5}
m_LocalScale: {x: 0.22958507, y: 0.22958507, z: 0.22958507}
m_Children: []
m_Father: {fileID: 4000011036911136}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &4000012482932774
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000010923298536}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0.5}
m_LocalScale: {x: 0.22958507, y: 0.22958507, z: 0.22958507}
m_Children: []
m_Father: {fileID: 4000011036911136}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &4000012704102164
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000013118930838}
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.22958507, y: 0.22958507, z: 0.22958507}
m_Children: []
m_Father: {fileID: 4000011036911136}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!23 &23000011320280670
MeshRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000013281444082}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_MotionVectors: 0
m_LightProbeUsage: 0
m_ReflectionProbeUsage: 0
m_Materials:
- {fileID: 2100000, guid: 1642fbcacc9dc42ed934b98457781f23, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingOrder: 0
--- !u!23 &23000013987882740
MeshRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000010923298536}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_MotionVectors: 0
m_LightProbeUsage: 0
m_ReflectionProbeUsage: 0
m_Materials:
- {fileID: 2100000, guid: 1642fbcacc9dc42ed934b98457781f23, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingOrder: 0
--- !u!33 &33000010540804998
MeshFilter:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000013506235850}
m_Mesh: {fileID: 4300000, guid: c0de5c847168f47b48791e9f1912e7c0, type: 3}
--- !u!33 &33000012835484144
MeshFilter:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000013281444082}
m_Mesh: {fileID: 4300000, guid: eae229cde7c374059a09c8052360682c, type: 3}
--- !u!33 &33000014224897370
MeshFilter:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000010923298536}
m_Mesh: {fileID: 4300000, guid: eae229cde7c374059a09c8052360682c, type: 3}
--- !u!114 &114000010166402902
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000010923298536}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5980d28f81eb545d78e1d84e1449a10f, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &114000013738431472
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000013281444082}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5980d28f81eb545d78e1d84e1449a10f, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &114000013814947972
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000013506235850}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 486ab05eb713a42cbb73a3d0cadf09ed, type: 3}
m_Name:
m_EditorClassIdentifier:
tangentMode: 0
m_masterTangent: {fileID: 0}
m_slaveTangent: {fileID: 0}
--- !u!137 &137000011316136332
SkinnedMeshRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000013506235850}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_MotionVectors: 0
m_LightProbeUsage: 0
m_ReflectionProbeUsage: 0
m_Materials:
- {fileID: 2100000, guid: 1642fbcacc9dc42ed934b98457781f23, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingOrder: 0
serializedVersion: 2
m_Quality: 0
m_UpdateWhenOffscreen: 0
m_SkinnedMotionVectors: 0
m_Mesh: {fileID: 4300000, guid: c0de5c847168f47b48791e9f1912e7c0, type: 3}
m_Bones: []
m_BlendShapeWeights: []
m_RootBone: {fileID: 4000012704102164}
m_AABB:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_DirtyAABB: 0

View File

@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 547111b175c2e4cb2a897b91a214e96a
timeCreated: 1483163090
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Resources/Anchor.prefab
uploadId: 467433

View File

@@ -0,0 +1,133 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: SplineRenderer
m_Shader: {fileID: 200, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: _EMISSION
m_LightmapFlags: 1
m_CustomRenderQueue: -1
stringTagMap: {}
m_SavedProperties:
serializedVersion: 2
m_TexEnvs:
- first:
name: _BumpMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailAlbedoMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailMask
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailNormalMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _EmissionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MainTex
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MetallicGlossMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _OcclusionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _ParallaxMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- first:
name: _BumpScale
second: 1
- first:
name: _Cutoff
second: 0.5
- first:
name: _DetailNormalMapScale
second: 1
- first:
name: _DstBlend
second: 0
- first:
name: _GlossMapScale
second: 1
- first:
name: _Glossiness
second: 0.5
- first:
name: _GlossyReflections
second: 1
- first:
name: _InvFade
second: 1
- first:
name: _Metallic
second: 0
- first:
name: _Mode
second: 0
- first:
name: _OcclusionStrength
second: 1
- first:
name: _Parallax
second: 0.02
- first:
name: _SmoothnessTextureChannel
second: 0
- first:
name: _SpecularHighlights
second: 1
- first:
name: _SrcBlend
second: 1
- first:
name: _UVSec
second: 0
- first:
name: _ZWrite
second: 1
m_Colors:
- first:
name: _Color
second: {r: 1, g: 1, b: 1, a: 1}
- first:
name: _EmissionColor
second: {r: 0, g: 0, b: 0, a: 1}
- first:
name: _TintColor
second: {r: 0.5, g: 0.5, b: 0.5, a: 0.5}

View File

@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: c492a9eeac69b435ba250b40e3c07897
timeCreated: 1483511030
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Resources/SplineRenderer.mat
uploadId: 467433

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 98ae5ed9b5e8c42128c33270aeed0053
folderAsset: yes
timeCreated: 1500598980
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,96 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Forces a referenced particle system to flow along this spline. To optimize performance limit Max Particles to just what is necessary. Particle speed along the path is determined by Start Lifetime.
///
/// </summary>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pixelplacement;
[ExecuteInEditMode]
[RequireComponent (typeof (Spline))]
public class SplineControlledParticleSystem : MonoBehaviour
{
//Public Variables:
public float startRadius;
public float endRadius;
//Private Variables:
[SerializeField] ParticleSystem _particleSystem = null;
Spline _spline;
ParticleSystem.Particle[] _particles;
const float _previousDiff = .01f;
//Init:
void Awake ()
{
_spline = GetComponent<Spline> ();
}
//Loops:
void LateUpdate ()
{
if (_particleSystem == null) return;
if (_particles == null) _particles = new ParticleSystem.Particle[_particleSystem.main.maxParticles];
int aliveParticlesCount = _particleSystem.GetParticles (_particles);
for (int i = 0; i < aliveParticlesCount; i++)
{
//get calculation pieces:
float seedMax = Mathf.Pow(10, _particles[i].randomSeed.ToString().Length);
float seedAsPercent = _particles[i].randomSeed / seedMax;
float travelPercentage = 1 - (_particles[i].remainingLifetime / _particles[i].startLifetime);
//bypass issue while running at edit time when particles haven't reached the spline end:
if (_spline.GetDirection(travelPercentage, false) == Vector3.zero) continue;
//get a direction off our current point on the path - rotating by 1080 results in better distribution since Unity's randomSeed for particles favors lower numbers:
Vector3 offshootDirection = Quaternion.AngleAxis(1080 * seedAsPercent, -_spline.GetDirection(travelPercentage, false)) * _spline.Up(travelPercentage);
Vector3 previousOffshootDirection = Quaternion.AngleAxis(1080 * seedAsPercent, -_spline.GetDirection(travelPercentage - _previousDiff, false)) * _spline.Up(travelPercentage - _previousDiff, false);
//cache our positions:
Vector3 position = _spline.GetPosition(travelPercentage, false);
//cache a previous position for velocity if possible:
Vector3 lastPosition = position;
if (travelPercentage - .01f >= 0) lastPosition = _spline.GetPosition(travelPercentage - _previousDiff, false);
//decide how far to offshoot from the spline based on where we are between the start and end radius:
float offset = Mathf.Lerp(startRadius, endRadius, travelPercentage);
float previousOffset = Mathf.Lerp(startRadius, endRadius, travelPercentage - _previousDiff);
//place particles depending on simulation space:
Vector3 currentPosition = Vector3.zero;
Vector3 previousPosition = Vector3.zero;
switch (_particleSystem.main.simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
currentPosition = _particleSystem.transform.InverseTransformPoint(position + offshootDirection * offset);
previousPosition = _particleSystem.transform.InverseTransformPoint(lastPosition + previousOffshootDirection * previousOffset);
break;
case ParticleSystemSimulationSpace.World:
case ParticleSystemSimulationSpace.Custom:
currentPosition = position + offshootDirection * offset;
previousPosition = position + previousOffshootDirection * previousOffset;
break;
}
//apply:
_particles[i].position = currentPosition;
_particles[i].velocity = currentPosition - previousPosition;
}
//apply the particle changes back to the system:
_particleSystem.SetParticles (_particles, _particles.Length);
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 390cd5d7e4c3ca3459339daddc886b38
timeCreated: 1505006763
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Utilities/SplineControlledParticleSystem.cs
uploadId: 467433

View File

@@ -0,0 +1,122 @@
/// <summary>
/// SURGE FRAMEWORK
/// Author: Bob Berkebile
/// Email: bobb@pixelplacement.com
///
/// Renders a spline by interfacing with an attached LineRenderer.
///
/// </summary>
using UnityEngine;
using System.Collections;
namespace Pixelplacement
{
[ExecuteInEditMode]
[RequireComponent (typeof (LineRenderer))]
[RequireComponent (typeof (Spline))]
public class SplineRenderer : MonoBehaviour
{
//Public Variables:
public int segmentsPerCurve = 25;
[Range (0,1)] public float startPercentage;
[Range (0,1)] public float endPercentage = 1;
//Private Variables:
LineRenderer _lineRenderer;
Spline _spline;
bool _initialized;
int _previousAnchorsLength;
int _previousSegmentsPerCurve;
int _vertexCount;
float _previousStart;
float _previousEnd;
//Init:
void Reset ()
{
_lineRenderer = GetComponent<LineRenderer> ();
_initialized = false;
_lineRenderer.startWidth = .03f;
_lineRenderer.endWidth = .03f;
_lineRenderer.startColor = Color.white;
_lineRenderer.endColor = Color.yellow;
_lineRenderer.material = Resources.Load("SplineRenderer") as Material;
}
//Loop:
void Update ()
{
//initialize:
if (!_initialized)
{
//refs:
_lineRenderer = GetComponent<LineRenderer> ();
_spline = GetComponent<Spline> ();
//initial setup:
ConfigureLineRenderer ();
UpdateLineRenderer ();
_initialized = true;
}
//configure line renderer:
if (segmentsPerCurve != _previousSegmentsPerCurve || _previousAnchorsLength != _spline.Anchors.Length)
{
ConfigureLineRenderer ();
UpdateLineRenderer ();
}
if (_spline.Anchors.Length <= 1)
{
_lineRenderer.positionCount = 0;
return;
}
//if any part of the spline is changed update line renderer:
foreach (var item in _spline.Anchors)
{
if (item.RenderingChange)
{
item.RenderingChange = false;
UpdateLineRenderer ();
}
}
//if the range has changed, update:
if (startPercentage != _previousStart || endPercentage != _previousEnd)
{
UpdateLineRenderer ();
//reset:
_previousStart = startPercentage;
_previousEnd = endPercentage;
}
}
//Private Methods:
void UpdateLineRenderer ()
{
if (_spline.Anchors.Length < 2) return;
for (int i = 0; i < _vertexCount; i++)
{
float percentage = i/(float)(_vertexCount - 1);
float sample = Mathf.Lerp (startPercentage, endPercentage, percentage);
_lineRenderer.SetPosition (i, _spline.GetPosition(sample, false));
}
}
void ConfigureLineRenderer ()
{
segmentsPerCurve = Mathf.Max (0, segmentsPerCurve);
_vertexCount = (segmentsPerCurve * (_spline.Anchors.Length - 1)) + 2;
if (Mathf.Sign (_vertexCount) == 1) _lineRenderer.positionCount = _vertexCount;
_previousSegmentsPerCurve = segmentsPerCurve;
_previousAnchorsLength = _spline.Anchors.Length;
}
}
}

View File

@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 59d7ebe8a03344a7a869c5061d6607a0
timeCreated: 1483504895
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 107312
packageName: Surge
packageVersion: 1.0.48
assetPath: Assets/Pixelplacement/Surge/Spline/Utilities/SplineRenderer.cs
uploadId: 467433