This commit is contained in:
corn
2026-06-07 22:59:32 +08:00
commit a62ff7379b
7171 changed files with 10015624 additions and 0 deletions

View File

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

View File

@@ -0,0 +1,45 @@
using UnityEngine;
using System.Collections;
namespace Dreamteck.Splines
{
//This is a blank SplineUser-derived class which you can use to build your custom SplineUser
//You can safely delete any functions that you won't use
//DO NOT ADD Update, LateUpdate or FixedUpdate, use Run, it is automatically called through one of these methods
public class BlankUser : SplineUser
{
#if UNITY_EDITOR
public override void EditorAwake()
{
base.EditorAwake();
//Editor initialization
}
#endif
void Start()
{
//Write initialization code here
}
protected override void LateRun()
{
base.LateRun();
//Code to run every Update/FixedUpdate/LateUpdate
}
protected override void Build()
{
base.Build();
//Build is called after the spline has been sampled.
//Use it for calculations (example: generate mesh geometry, calculate object positions)
}
protected override void PostBuild()
{
base.PostBuild();
//Called on the main thread after Build has finished
//Use it to apply the calculations from Build to GameObjects, Transforms, Meshes, etc.
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 740f49ddb7ee0984b83bd6ab7514b564
timeCreated: 1459692700
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,130 @@
using UnityEngine;
using System.Collections;
using System.Threading;
namespace Dreamteck.Splines
{
[AddComponentMenu("Dreamteck/Splines/Edge Collider Generator")]
[RequireComponent(typeof(EdgeCollider2D))]
public class EdgeColliderGenerator : SplineUser
{
public float offset
{
get { return _offset; }
set
{
if (value != _offset)
{
_offset = value;
Rebuild();
}
}
}
[SerializeField]
[HideInInspector]
private float _offset = 0f;
[SerializeField]
[HideInInspector]
protected EdgeCollider2D edgeCollider;
[SerializeField]
[HideInInspector]
protected Vector2[] vertices = new Vector2[0];
[HideInInspector]
public float updateRate = 0.1f;
protected float lastUpdateTime = 0f;
private bool updateCollider = false;
#if UNITY_EDITOR
public override void EditorAwake()
{
base.EditorAwake();
edgeCollider = GetComponent<EdgeCollider2D>();
Awake();
}
#endif
protected override void Awake()
{
base.Awake();
edgeCollider = GetComponent<EdgeCollider2D>();
}
protected override void Reset()
{
base.Reset();
}
protected override void OnEnable()
{
base.OnEnable();
}
protected override void OnDisable()
{
base.OnDisable();
}
protected override void OnDestroy()
{
base.OnDestroy();
}
protected override void LateRun()
{
base.LateRun();
if (updateCollider)
{
if (edgeCollider != null)
{
if (Time.time - lastUpdateTime >= updateRate)
{
lastUpdateTime = Time.time;
updateCollider = false;
edgeCollider.points = vertices;
}
}
}
}
protected override void Build()
{
base.Build();
if (sampleCount == 0) return;
if (vertices.Length != sampleCount) vertices = new Vector2[sampleCount];
bool hasOffset = offset != 0f;
for (int i = 0; i < sampleCount; i++)
{
GetSample(i, evalResult);
vertices[i] = evalResult.position;
if (hasOffset)
{
Vector2 right = new Vector2(-evalResult.forward.y, evalResult.forward.x).normalized * evalResult.size;
vertices[i] += right * offset;
}
}
}
protected override void PostBuild()
{
base.PostBuild();
if (edgeCollider == null) return;
for(int i = 0; i < vertices.Length; i++) vertices[i] = transform.InverseTransformPoint(vertices[i]);
#if UNITY_EDITOR
if (!Application.isPlaying || updateRate <= 0f)
{
edgeCollider.points = vertices;
} else updateCollider = true;
#else
if(updateRate == 0f) edgeCollider.points = vertices;
else updateCollider = true;
#endif
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: d28d465ca9ef341488ba836962159676
timeCreated: 1523272688
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7417baf45051d9e4b974d45e69811efd, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,166 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
public class BakeMeshWindow : EditorWindow
{
public bool isStatic = true;
public bool copy = false;
public bool removeComputer = false;
public bool permanent = false;
public bool generateLightmapUVs = false;
MeshFilter filter;
MeshGenerator meshGen;
public enum SaveFormat { MeshAsset, OBJ, None }
SaveFormat format = SaveFormat.MeshAsset;
public void Init(MeshGenerator generator)
{
titleContent = new GUIContent("Bake Mesh");
meshGen = generator;
filter = generator.GetComponent<MeshFilter>();
if (EditorPrefs.HasKey("BakeWindow_isStatic")) isStatic = EditorPrefs.GetBool("BakeWindow_isStatic");
if (EditorPrefs.HasKey("BakeWindow_generateLightmapUVs")) generateLightmapUVs = EditorPrefs.GetBool("BakeWindow_generateLightmapUVs");
if (EditorPrefs.HasKey("BakeWindow_copy")) copy = EditorPrefs.GetBool("BakeWindow_copy");
if (EditorPrefs.HasKey("BakeWindow_removeComputer")) removeComputer = EditorPrefs.GetBool("BakeWindow_removeComputer");
if (EditorPrefs.HasKey("BakeWindow_permanent")) permanent = EditorPrefs.GetBool("BakeWindow_permanent");
format = (SaveFormat)EditorPrefs.GetInt("BakeWindow_format", 0);
minSize = new Vector2(340, 220);
maxSize = minSize;
}
void OnDestroy()
{
EditorPrefs.SetBool("BakeWindow_isStatic", isStatic);
EditorPrefs.SetBool("BakeWindow_generateLightmapUVs", generateLightmapUVs);
EditorPrefs.SetBool("BakeWindow_copy", copy);
EditorPrefs.SetBool("BakeWindow_removeComputer", removeComputer);
EditorPrefs.SetBool("BakeWindow_permanent", permanent);
EditorPrefs.SetInt("BakeWindow_format", (int)format);
}
void OnGUI() {
format = (SaveFormat)EditorGUILayout.EnumPopup("Save Format", format);
bool saveMesh = format != SaveFormat.None;
if (format != SaveFormat.None) copy = EditorGUILayout.Toggle("Save without baking", copy);
bool isCopy = format != SaveFormat.None && copy;
switch (format)
{
case SaveFormat.None: EditorGUILayout.HelpBox("Saves the mesh inside the scene for lightmap", MessageType.Info); break;
case SaveFormat.MeshAsset: EditorGUILayout.HelpBox("Saves the mesh as an .asset file inside the project. This makes using the mesh in prefabs and across scenes possible.", MessageType.Info); break;
case SaveFormat.OBJ: EditorGUILayout.HelpBox("Exports the mesh as an OBJ file which can be imported in a third-party modeling application.", MessageType.Info); break;
}
EditorGUILayout.Space();
if (!isCopy)
{
isStatic = EditorGUILayout.Toggle("Make Static", isStatic);
permanent = EditorGUILayout.Toggle("Permanent", permanent);
generateLightmapUVs = EditorGUILayout.Toggle("Generate Lightmap UVs", generateLightmapUVs);
if (permanent)
{
removeComputer = EditorGUILayout.Toggle("Remove SplineComputer", removeComputer);
if (meshGen.spline.subscriberCount > 1 && !isCopy) EditorGUILayout.HelpBox("WARNING: Removing the SplineComputer from this object will cause other SplineUsers to malfunction!", MessageType.Warning);
}
}
string bakeText = "Bake Mesh";
if (saveMesh) bakeText = "Bake & Save Mesh";
if (isCopy) bakeText = "Save Mesh";
if (GUILayout.Button(bakeText))
{
if (permanent)
{
if (!EditorUtility.DisplayDialog("Permanent bake?", "This operation will remove the Mesh Generator. Are you sure you want to continue?", "Yes", "No")) return;
}
string savePath = "";
if (saveMesh)
{
string ext = "asset";
if (format == SaveFormat.OBJ) ext = "obj";
string meshName = "mesh";
if (filter != null) meshName = filter.sharedMesh.name;
savePath = EditorUtility.SaveFilePanel("Save " + meshName, Application.dataPath, meshName + "." + ext, ext);
if (!Directory.Exists(Path.GetDirectoryName(savePath)) || savePath == "")
{
EditorUtility.DisplayDialog("Save error", "Invalid save path. Please select a valid save path and try again", "OK");
return;
}
if (format == SaveFormat.OBJ && !copy && !savePath.StartsWith(Application.dataPath))
{
EditorUtility.DisplayDialog("Save error", "OBJ files can be saved outside of the project folder only when \"Save without baking\" is selected. Please select a directory inside the project in order to save.", "OK");
return;
}
if (format == SaveFormat.MeshAsset && !savePath.StartsWith(Application.dataPath))
{
EditorUtility.DisplayDialog("Save error", "Asset files cannot be saved outside of the project directory. Please select a path inside the project directory.", "OK");
return;
}
}
Undo.RecordObject(meshGen.gameObject, "Bake mesh");
if (!isCopy) Bake();
else
{
UnityEditor.MeshUtility.Optimize(filter.sharedMesh);
Unwrapping.GenerateSecondaryUVSet(filter.sharedMesh);
}
if (saveMesh) SaveMeshFile(savePath);
}
}
void Bake()
{
meshGen.Bake(isStatic, generateLightmapUVs);
if (permanent && !copy)
{
SplineComputer meshGenComputer = meshGen.spline;
if (permanent)
{
meshGenComputer.Unsubscribe(meshGen);
DestroyImmediate(meshGen);
}
if (removeComputer)
{
if(meshGenComputer.GetComponents<Component>().Length == 2) DestroyImmediate(meshGenComputer.gameObject);
else DestroyImmediate(meshGenComputer);
}
}
}
void SaveMeshFile(string savePath)
{
if (format == SaveFormat.None) return;
string relativePath = "";
if(savePath.StartsWith(Application.dataPath)) relativePath = "Assets" + savePath.Substring(Application.dataPath.Length);
if (format == SaveFormat.MeshAsset)
{
if (copy)
{
Mesh assetMesh = Dreamteck.MeshUtility.Copy(filter.sharedMesh);
AssetDatabase.CreateAsset(assetMesh, relativePath);
} else AssetDatabase.CreateAsset(filter.sharedMesh, relativePath);
}
if (format == SaveFormat.OBJ)
{
MeshRenderer renderer = meshGen.GetComponent<MeshRenderer>();
string objString = Dreamteck.MeshUtility.ToOBJString(filter.sharedMesh, renderer.sharedMaterials);
File.WriteAllText(savePath, objString);
if (!copy) DestroyImmediate(filter.sharedMesh);
if (relativePath != "") //Import back the OBJ
{
AssetDatabase.ImportAsset(relativePath, ImportAssetOptions.ForceSynchronousImport);
if (!copy) filter.sharedMesh = AssetDatabase.LoadAssetAtPath<Mesh>(relativePath);
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: befdb339588e28f41aa626b8c6319d06
timeCreated: 1466584092
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(LengthCalculator), true)]
[CanEditMultipleObjects]
public class LengthCalculatorEditor : SplineUserEditor
{
public override void OnInspectorGUI()
{
showAveraging = false;
base.OnInspectorGUI();
}
protected override void BodyGUI()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Length Calculator", EditorStyles.boldLabel);
base.BodyGUI();
LengthCalculator calculator = (LengthCalculator)target;
for (int i = 0; i < targets.Length; i++)
{
LengthCalculator lengthCalc = (LengthCalculator)targets[i];
if (lengthCalc.spline == null) continue;
EditorGUILayout.HelpBox(lengthCalc.spline.name + " Length: " + lengthCalc.length, MessageType.Info);
}
if (targets.Length > 1) return;
SerializedProperty events = serializedObject.FindProperty("lengthEvents");
EditorGUI.BeginChangeCheck();
for (int i = 0; i < events.arraySize; i++)
{
SerializedProperty eventProperty = events.GetArrayElementAtIndex(i);
SerializedProperty onChange = eventProperty.FindPropertyRelative("onChange");
SerializedProperty enabled = eventProperty.FindPropertyRelative("enabled");
SerializedProperty targetLength = eventProperty.FindPropertyRelative("targetLength");
SerializedProperty type = eventProperty.FindPropertyRelative("type");
EditorGUIUtility.labelWidth = 100;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(enabled, new GUIContent(""), GUILayout.Width(20));
EditorGUILayout.PropertyField(targetLength);
EditorGUIUtility.labelWidth = 60;
EditorGUILayout.PropertyField(type);
if (GUILayout.Button("x", GUILayout.Width(20)))
{
Undo.RecordObject(calculator, "Remove Length Event");
ArrayUtility.RemoveAt(ref calculator.lengthEvents, i);
}
EditorGUILayout.EndHorizontal();
EditorGUIUtility.labelWidth = 0;
EditorGUILayout.PropertyField(onChange);
EditorGUILayout.Space();
}
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
if (GUILayout.Button("Add Length Event"))
{
Undo.RecordObject(calculator, "Add Length Event");
ArrayUtility.Add(ref calculator.lengthEvents, new LengthCalculator.LengthEvent());
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4b0cb98d553738f458280b7a6589f63d
timeCreated: 1459595686
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,208 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(MeshGenerator))]
[CanEditMultipleObjects]
public class MeshGenEditor : SplineUserEditor
{
protected bool showSize = true;
protected bool showColor = true;
protected bool showDoubleSided = true;
protected bool showFlipFaces = true;
protected bool showRotation = true;
protected bool showInfo = false;
protected bool showOffset = true;
protected bool showTangents = true;
protected bool showNormalMethod = true;
private int framesPassed = 0;
MeshGenerator[] generators = new MeshGenerator[0];
BakeMeshWindow bakeWindow = null;
protected override void OnSceneGUI()
{
base.OnSceneGUI();
MeshGenerator generator = (MeshGenerator)target;
if (Application.isPlaying) return;
framesPassed++;
if(framesPassed >= 100)
{
framesPassed = 0;
if (generator != null && generator.GetComponent<MeshCollider>() != null) generator.UpdateCollider();
}
}
protected override void OnEnable()
{
base.OnEnable();
generators = new MeshGenerator[targets.Length];
for (int i = 0; i < targets.Length; i++)
{
generators[i] = (MeshGenerator)targets[i];
}
}
public override void OnInspectorGUI()
{
MeshGenerator generator = (MeshGenerator)target;
if (generator.baked)
{
if (SplineEditorGUI.EditorLayoutSelectableButton(new GUIContent("Revert Bake", "Makes the mesh dynamic again and allows editing"), true, true))
{
for (int i = 0; i < generators.Length; i++)
{
generators[i].Unbake();
EditorUtility.SetDirty(generators[i]);
}
}
return;
}
base.OnInspectorGUI();
}
protected override void BodyGUI()
{
base.BodyGUI();
MeshGenerator generator = (MeshGenerator)target;
serializedObject.Update();
SerializedProperty calculateTangents = serializedObject.FindProperty("_calculateTangents");
SerializedProperty size = serializedObject.FindProperty("_size");
SerializedProperty color = serializedObject.FindProperty("_color");
SerializedProperty normalMethod = serializedObject.FindProperty("_normalMethod");
SerializedProperty offset = serializedObject.FindProperty("_offset");
SerializedProperty rotation = serializedObject.FindProperty("_rotation");
SerializedProperty flipFaces = serializedObject.FindProperty("_flipFaces");
SerializedProperty doubleSided = serializedObject.FindProperty("_doubleSided");
EditorGUI.BeginChangeCheck();
if (showTangents)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mesh", EditorStyles.boldLabel);
if (showTangents) EditorGUILayout.PropertyField(calculateTangents, new GUIContent("Calculate Tangents"));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Vertices", EditorStyles.boldLabel);
if (showSize) EditorGUILayout.PropertyField(size, new GUIContent("Size"));
if (showColor) EditorGUILayout.PropertyField(color, new GUIContent("Color"));
if (showNormalMethod) EditorGUILayout.PropertyField(normalMethod, new GUIContent("Normal Method"));
if (showOffset) EditorGUILayout.PropertyField(offset, new GUIContent("Offset"));
if (showRotation) EditorGUILayout.PropertyField(rotation, new GUIContent("Rotation"));
if (showDoubleSided || showFlipFaces)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Faces", EditorStyles.boldLabel);
if (showDoubleSided) EditorGUILayout.PropertyField(doubleSided, new GUIContent("Double-sided"));
if (!generator.doubleSided && showFlipFaces) EditorGUILayout.PropertyField(flipFaces, new GUIContent("Flip Faces"));
}
if (generator.GetComponent<MeshCollider>() != null)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mesh Collider", EditorStyles.boldLabel);
generator.colliderUpdateRate = EditorGUILayout.FloatField("Collider Update Iterval", generator.colliderUpdateRate);
}
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
for (int i = 0; i < generators.Length; i++) generators[i].Rebuild();
}
}
protected override void FooterGUI()
{
base.FooterGUI();
showInfo = EditorGUILayout.Foldout(showInfo, "Info & Components");
if (showInfo)
{
MeshGenerator generator = (MeshGenerator)target;
MeshFilter filter = generator.GetComponent<MeshFilter>();
if (filter == null) return;
MeshRenderer renderer = generator.GetComponent<MeshRenderer>();
string str = "";
if (filter.sharedMesh != null) str = "Vertices: " + filter.sharedMesh.vertexCount + "\r\nTriangles: " + (filter.sharedMesh.triangles.Length / 3);
else str = "No info available";
EditorGUILayout.HelpBox(str, MessageType.Info);
bool showFilter = filter.hideFlags == HideFlags.None;
bool last = showFilter;
showFilter = EditorGUILayout.Toggle("Show Mesh Filter", showFilter);
if (last != showFilter)
{
if (showFilter) filter.hideFlags = HideFlags.None;
else filter.hideFlags = HideFlags.HideInInspector;
}
bool showRenderer = renderer.hideFlags == HideFlags.None;
last = showRenderer;
showRenderer = EditorGUILayout.Toggle("Show Mesh Renderer", showRenderer);
if (last != showRenderer)
{
if (showRenderer) renderer.hideFlags = HideFlags.None;
else renderer.hideFlags = HideFlags.HideInInspector;
}
}
if (generators.Length == 1)
{
if (GUILayout.Button("Bake Mesh"))
{
MeshGenerator generator = (MeshGenerator)target;
bakeWindow = EditorWindow.GetWindow<BakeMeshWindow>();
bakeWindow.Init(generator);
}
}
}
protected override void Awake()
{
MeshGenerator generator = (MeshGenerator)target;
MeshRenderer rend = generator.GetComponent<MeshRenderer>();
if (rend == null) return;
base.Awake();
}
protected override void OnDestroy()
{
MeshGenerator generator = (MeshGenerator)target;
base.OnDestroy();
MeshGenerator gen = (MeshGenerator)target;
if (gen == null) return;
if (gen.GetComponent<MeshCollider>() != null) generator.UpdateCollider();
if (bakeWindow != null) bakeWindow.Close();
}
protected override void OnDelete()
{
base.OnDelete();
MeshGenerator generator = (MeshGenerator)target;
if (generator == null) return;
MeshFilter filter = generator.GetComponent<MeshFilter>();
if (filter != null) filter.hideFlags = HideFlags.None;
MeshRenderer renderer = generator.GetComponent<MeshRenderer>();
if (renderer != null) renderer.hideFlags = HideFlags.None;
}
protected virtual void UVControls(MeshGenerator generator)
{
serializedObject.Update();
SerializedProperty uvMode = serializedObject.FindProperty("_uvMode");
SerializedProperty uvOffset = serializedObject.FindProperty("_uvOffset");
SerializedProperty uvRotation = serializedObject.FindProperty("_uvRotation");
SerializedProperty uvScale = serializedObject.FindProperty("_uvScale");
EditorGUILayout.Space();
EditorGUILayout.LabelField("Uv Coordinates", EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(uvMode, new GUIContent("UV Mode"));
EditorGUILayout.PropertyField(uvOffset, new GUIContent("UV Offset"));
EditorGUILayout.PropertyField(uvRotation, new GUIContent("UV Rotation"));
EditorGUILayout.PropertyField(uvScale, new GUIContent("UV Scale"));
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5853c8e53cbbcea4c86f3dfc39e39f47
timeCreated: 1448044279
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,288 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
[CustomEditor(typeof(Node), true)]
public class NodeEditor : Editor {
private SplineComputer addComp = null;
private int addPoint = 0;
private Node lastnode = null;
private Vector3 position, scale;
private Quaternion rotation;
private int[] availablePoints;
bool connectionsOpen = false, settingsOpen = false;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
Node node = (Node)target;
if (addComp != null)
{
string[] pointNames = new string[availablePoints.Length];
for (int i = 0; i < pointNames.Length; i++)
{
pointNames[i] = "Point " + (availablePoints[i] + 1);
}
if (availablePoints.Length > 0) addPoint = EditorGUILayout.Popup("Link point", addPoint, pointNames);
else EditorGUILayout.LabelField("No Points Available");
if (GUILayout.Button("Cancel"))
{
addComp = null;
addPoint = 0;
}
if (addPoint >= 0 && availablePoints.Length > addPoint)
{
if (node.HasConnection(addComp, availablePoints[addPoint])) EditorGUILayout.HelpBox("Connection already exists (" + addComp.name + "," + availablePoints[addPoint], MessageType.Error);
else if (GUILayout.Button("Link"))
{
AddConnection(addComp, availablePoints[addPoint]);
}
}
}
else
{
SplineEditorGUI.BeginContainerBox(ref connectionsOpen, "Connections");
if (connectionsOpen) ConnectionsGUI();
SplineEditorGUI.EndContainerBox();
Rect rect = GUILayoutUtility.GetLastRect();
SplineComputer[] addComps;
SplineComputer lastComp = addComp;
bool dragged = DreamteckEditorGUI.DropArea<SplineComputer>(rect, out addComps);
if (dragged && addComps.Length > 0) SelectComputer(addComps[0]);
if (lastComp != addComp) SceneView.RepaintAll();
SplineEditorGUI.BeginContainerBox(ref settingsOpen, "Settings");
if (settingsOpen) SettingsGUI();
SplineEditorGUI.EndContainerBox();
}
}
void SettingsGUI()
{
Node node = (Node)target;
node.transformNormals = EditorGUILayout.Toggle("Transform Normals", node.transformNormals);
node.transformSize = EditorGUILayout.Toggle("Transform Size", node.transformSize);
node.transformTangents = EditorGUILayout.Toggle("Transform Tangents", node.transformTangents);
EditorGUI.BeginChangeCheck();
node.type = (Node.Type)EditorGUILayout.EnumPopup("Node type", node.type);
if (EditorGUI.EndChangeCheck())
{
SceneView.RepaintAll();
node.UpdateConnectedComputers();
}
}
void ConnectionsGUI()
{
Node node = (Node)target;
Node.Connection[] connections = node.GetConnections();
EditorGUILayout.Space();
if (connections.Length > 0)
{
for (int i = 0; i < connections.Length; i++)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(connections[i].spline.name + " at point " + (connections[i].pointIndex+1));
if (GUILayout.Button("Select", GUILayout.Width(70)))
{
Selection.activeGameObject = connections[i].spline.gameObject;
}
if (SplineEditorGUI.EditorLayoutSelectableButton(new GUIContent("Swap Tangents"), connections[i].spline.type == Spline.Type.Bezier, connections[i].invertTangents))
{
connections[i].invertTangents = !connections[i].invertTangents;
node.UpdateConnectedComputers();
SceneView.RepaintAll();
}
if (GUILayout.Button("x", GUILayout.Width(20)))
{
Undo.RecordObject(node, "Remove connection");
Undo.RecordObject(connections[i].spline, "Remove node");
connections[i].spline.DisconnectNode(connections[i].pointIndex);
node.RemoveConnection(connections[i].spline, connections[i].pointIndex);
}
EditorGUILayout.EndHorizontal();
}
}
else EditorGUILayout.HelpBox("Drag & Drop SplineComputers here to link their points.", MessageType.Info);
}
void OnEnable()
{
lastnode = ((Node)target);
lastnode.EditorMaintainConnections();
connectionsOpen = EditorPrefs.GetBool("Dreamteck.Splines.Editor.NodeEditor.connectionsOpen");
settingsOpen = EditorPrefs.GetBool("Dreamteck.Splines.Editor.NodeEditor.settingsOpen");
}
private void OnDisable()
{
EditorPrefs.SetBool("Dreamteck.Splines.Editor.NodeEditor.connectionsOpen", connectionsOpen);
EditorPrefs.SetBool("Dreamteck.Splines.Editor.NodeEditor.settingsOpen", settingsOpen);
}
void OnDestroy()
{
if (Application.isEditor && !Application.isPlaying)
{
if (((Node)target) == null)
{
Node.Connection[] connections = lastnode.GetConnections();
for(int i = 0; i < connections.Length; i++)
{
if (connections[i].spline == null) continue;
Undo.RecordObject(connections[i].spline, "Delete node connections");
}
lastnode.ClearConnections();
}
}
}
void SelectComputer(SplineComputer comp)
{
addComp = comp;
if (addComp != null) availablePoints = GetAvailablePoints(addComp);
SceneView.RepaintAll();
Repaint();
}
void AddConnection(SplineComputer computer, int pointIndex)
{
Node node = (Node)target;
Node.Connection[] connections = node.GetConnections();
if (EditorUtility.DisplayDialog("Link point?", "Add point " + (pointIndex+1) + " to connections?", "Yes", "No"))
{
Undo.RecordObject(addComp, "Add connection");
Undo.RecordObject(node, "Add Connection");
if (connections.Length == 0)
{
switch (EditorUtility.DisplayDialogComplex("Align node to point?", "This is the first connection for the node, would you like to snap or align the node's Transform the spline point.", "No", "Snap", "Snap and Align"))
{
case 1: SplinePoint point = addComp.GetPoint(pointIndex);
node.transform.position = point.position;
break;
case 2:
SplineSample result = addComp.Evaluate(pointIndex);
node.transform.position = result.position;
node.transform.rotation = result.rotation;
break;
}
}
computer.ConnectNode(node, pointIndex);
addComp = null;
addPoint = 0;
SceneView.RepaintAll();
Repaint();
}
}
int[] GetAvailablePoints(SplineComputer computer)
{
List<int> indices = new List<int>();
for (int i = 0; i < computer.pointCount; i++)
{
if (computer.GetNode(i) != null) continue;
indices.Add(i);
}
return indices.ToArray();
}
protected virtual void OnSceneGUI()
{
Node node = (Node)target;
Node.Connection[] connections = node.GetConnections();
#if DREAMTECK_SPLINES
for (int i = 0; i < connections.Length; i++) SplineDrawer.DrawSplineComputer(connections[i].spline, 0.0, 1.0, 0.5f);
#endif
bool update = false;
if (position != node.transform.position)
{
position = node.transform.position;
update = true;
}
if(scale != node.transform.localScale){
scale = node.transform.localScale;
update = true;
}
if (rotation != node.transform.rotation)
{
rotation = node.transform.rotation;
update = true;
}
if(update) node.UpdateConnectedComputers();
if (addComp == null)
{
if (connections.Length > 0)
{
bool bezier = false;
for (int i = 0; i < connections.Length; i++)
{
if (connections[i].spline == null) continue;
if (connections[i].spline.type == Spline.Type.Bezier)
{
bezier = true;
continue;
}
}
if (bezier && node.type == Node.Type.Smooth)
{
if (connections[0].spline != null)
{
SplinePoint point = node.GetPoint(0, true);
Handles.DrawDottedLine(node.transform.position, point.tangent, 6f);
Handles.DrawDottedLine(node.transform.position, point.tangent2, 6f);
Vector3 lastPos = point.tangent;
bool setPoint = false;
point.SetTangentPosition(Handles.PositionHandle(point.tangent, node.transform.rotation));
if (lastPos != point.tangent) setPoint = true;
lastPos = point.tangent2;
point.SetTangent2Position(Handles.PositionHandle(point.tangent2, node.transform.rotation));
if (lastPos != point.tangent2) setPoint = true;
if (setPoint)
{
node.SetPoint(0, point, true);
node.UpdateConnectedComputers();
}
}
}
}
return;
}
SplinePoint[] points = addComp.GetPoints();
Transform camTransform = SceneView.currentDrawingSceneView.camera.transform;
#if DREAMTECK_SPLINES
SplineDrawer.DrawSplineComputer(addComp, 0.0, 1.0, 0.5f);
#endif
TextAnchor originalAlignment = GUI.skin.label.alignment;
Color originalColor = GUI.skin.label.normal.textColor;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUI.skin.label.normal.textColor = addComp.editorPathColor;
for (int i = 0; i < availablePoints.Length; i++)
{
if (addComp.isClosed && i == points.Length - 1) break;
Handles.Label(points[i].position + Camera.current.transform.up * HandleUtility.GetHandleSize(points[i].position) * 0.3f, (i + 1).ToString());
if (SplineEditorHandles.CircleButton(points[availablePoints[i]].position, Quaternion.LookRotation(-camTransform.forward, camTransform.up), HandleUtility.GetHandleSize(points[availablePoints[i]].position) * 0.1f, 2f, addComp.editorPathColor))
{
AddConnection(addComp, availablePoints[i]);
break;
}
}
GUI.skin.label.alignment = originalAlignment;
GUI.skin.label.normal.textColor = originalColor;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 29b7ad072e04e6341bbda1d04593b91f
timeCreated: 1459107704
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,356 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
[CustomEditor(typeof(ObjectBender), true)]
[CanEditMultipleObjects]
public class ObjectBenderEditor : SplineUserEditor
{
List<int> selected = new List<int>();
Vector2 scroll = Vector2.zero;
bool generatedUvs = false;
protected override void Awake()
{
ObjectBender bender = (ObjectBender)target;
if(!Application.isPlaying) bender.UpdateReferences();
base.Awake();
}
void PropertyEditor(ObjectBender.BendProperty[] properties)
{
if (selected.Count == 0) return;
int applyRotationCount = 0, applyScaleCount = 0, enableCount = 0, bendMeshCount = 0, bendColliderCount = 0, bendSplineCount = 0;
bool showMesh = false, showCollider = false, showSpline = false;
float colliderUpdateRate = 0f;
for(int i = 0; i < selected.Count; i++)
{
ObjectBender.BendProperty property = properties[selected[i]];
if (property.enabled) enableCount++;
if (property.applyRotation) applyRotationCount++;
if (property.applyScale) applyScaleCount++;
if (property.bendMesh) bendMeshCount++;
if (property.bendCollider) bendColliderCount++;
if (property.bendSpline) bendSplineCount++;
if (property.filter != null) showMesh = true;
if (property.collider != null) showCollider = true;
if (property.splineComputer != null) showSpline = true;
colliderUpdateRate += property.colliderUpdateRate;
}
bool enabled = enableCount == selected.Count;
bool applyRotation = applyRotationCount == selected.Count;
bool applyScale = applyScaleCount == selected.Count;
bool bendMesh = bendMeshCount == selected.Count;
bool bendCollider = bendColliderCount == selected.Count;
bool bendSpline = bendSplineCount == selected.Count;
colliderUpdateRate /= selected.Count;
bool lastEnabled = enabled, lastApplyRotation = applyRotation, lastApplyScale = applyScale, lastBendMesh = bendMesh, lastBendCollider = bendCollider, lastBendSpline = bendSpline;
float lastColliderUpdateRate = colliderUpdateRate;
EditorGUIUtility.labelWidth = 90;
EditorGUI.BeginChangeCheck();
GUI.color = Color.white;
EditorGUILayout.BeginVertical(GUI.skin.box, GUILayout.Width(EditorGUIUtility.currentViewWidth - 50));
EditorGUILayout.BeginHorizontal();
enabled = EditorGUILayout.Toggle(enabled, GUILayout.Width(20));
if (selected.Count == 1) EditorGUILayout.LabelField(properties[selected[0]].transform.transform.name);
else EditorGUILayout.LabelField("Multiple objects");
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginVertical();
applyRotation = EditorGUILayout.Toggle("Apply rotation", applyRotation);
applyScale = EditorGUILayout.Toggle("Apply scale", applyScale);
if (showSpline) bendSpline = EditorGUILayout.Toggle("Bend Spline", bendSpline);
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
if (showMesh)
{
bendMesh = EditorGUILayout.Toggle("Bend Mesh", bendMesh);
if (bendMesh)
{
if (showCollider)
{
bendCollider = EditorGUILayout.Toggle("Bend Collider", bendCollider);
if (bendCollider)
{
EditorGUI.indentLevel++;
colliderUpdateRate = EditorGUILayout.FloatField("Update Rate", colliderUpdateRate);
EditorGUI.indentLevel--;
}
}
else GUI.Label(new Rect(EditorGUIUtility.currentViewWidth / 2f - 25, 40, EditorGUIUtility.currentViewWidth / 2f - 30, 22), "No Mesh Colliders Available");
}
}
else EditorGUILayout.LabelField("No Meshes Available");
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
if (EditorGUI.EndChangeCheck())
{
for(int i = 0; i < selected.Count; i++)
{
if (lastEnabled != enabled) properties[selected[i]].enabled = enabled;
if (lastApplyRotation != applyRotation) properties[selected[i]].applyRotation = applyRotation;
if (lastApplyScale != applyScale) properties[selected[i]].applyScale = applyScale;
if (bendMesh != lastBendMesh) properties[selected[i]].bendMesh = bendMesh;
if (bendCollider != lastBendCollider) properties[selected[i]].bendCollider = bendCollider;
if (bendSpline != lastBendSpline) properties[selected[i]].bendSpline = bendSpline;
if (lastColliderUpdateRate != colliderUpdateRate) properties[selected[i]].colliderUpdateRate = colliderUpdateRate;
}
}
}
void GetChildCount(Transform parent, ref int count)
{
foreach(Transform child in parent)
{
count++;
GetChildCount(child, ref count);
}
}
public override void OnInspectorGUI()
{
showAveraging = false;
base.OnInspectorGUI();
}
protected override void BodyGUI()
{
base.BodyGUI();
ObjectBender bender = (ObjectBender)target;
serializedObject.Update();
SerializedProperty axis = serializedObject.FindProperty("_axis");
SerializedProperty normalMode = serializedObject.FindProperty("_normalMode");
SerializedProperty forwardMode = serializedObject.FindProperty("_forwardMode");
for (int i = 0; i < targets.Length; i++)
{
ObjectBender objBender = (ObjectBender)targets[i];
int childCount = 0;
GetChildCount(objBender.transform, ref childCount);
if (objBender.bendProperties.Length - 1 != childCount && !Application.isPlaying) objBender.UpdateReferences();
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(axis, new GUIContent("Axis"));
EditorGUILayout.PropertyField(normalMode, new GUIContent("Up Vector"));
if (normalMode.intValue == (int)ObjectBender.NormalMode.Custom)
{
SerializedProperty customNormal = serializedObject.FindProperty("_customNormal");
EditorGUILayout.PropertyField(customNormal, new GUIContent("Custom Up"));
}
EditorGUILayout.PropertyField(forwardMode, new GUIContent("Forward Vector"));
if (forwardMode.intValue == (int)ObjectBender.ForwardMode.Custom)
{
SerializedProperty customForward = serializedObject.FindProperty("_customForward");
EditorGUILayout.PropertyField(customForward, new GUIContent("Custom Forward"));
}
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
for (int i = 0; i < targets.Length; i++)
{
ObjectBender objBender = (ObjectBender)targets[i];
objBender.Rebuild();
}
}
if (targets.Length > 1)
{
EditorGUILayout.LabelField("Object properties unavailable when multiple benders are selected.", EditorStyles.centeredGreyMiniLabel);
return;
}
if (!bender.bend)
{
float scrollHeight = Mathf.Min(bender.bendProperties.Length, 15) * 22;
scroll = EditorGUILayout.BeginScrollView(scroll, GUILayout.Height(scrollHeight+5));
for (int i = 0; i < bender.bendProperties.Length; i++)
{
bool isSelected = selected.Contains(i);
if (!bender.bendProperties[i].enabled)
{
GUI.color = Color.gray;
if (isSelected) GUI.color = Color.Lerp(Color.gray, SplinePrefs.highlightColor, 0.5f);
}
else
{
if (isSelected) GUI.color = SplinePrefs.highlightColor;
else GUI.color = Color.white;
}
GUILayout.Box(bender.bendProperties[i].transform.transform.name, GUILayout.Height(18), GUILayout.Width(EditorGUIUtility.currentViewWidth - 60));
if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition) && Event.current.type == EventType.MouseDown)
{
if (Event.current.control)
{
if (!selected.Contains(i)) selected.Add(i);
}
else if (Event.current.shift && selected.Count > 0)
{
int from = selected[0];
selected.Clear();
if (from < i)
{
for (int n = from; n <= i; n++) selected.Add(n);
}
else
{
for (int n = from; n >= i; n--) selected.Add(n);
}
}
else
{
selected.Clear();
selected.Add(i);
}
Repaint();
SceneView.RepaintAll();
}
GUI.color = Color.white;
}
EditorGUILayout.EndScrollView();
if (selected.Count > 0)
{
PropertyEditor(bender.bendProperties);
}
if (selected.Count > 0)
{
if (Event.current.type == EventType.KeyDown)
{
if (Event.current.keyCode == KeyCode.DownArrow)
{
if (selected.Count > 1)
{
int temp = selected[selected.Count - 1];
selected.Clear();
selected.Add(temp);
}
selected[0]++;
if (selected[0] >= bender.bendProperties.Length) selected[0] = 0;
}
if (Event.current.keyCode == KeyCode.UpArrow)
{
if (selected.Count > 1)
{
int temp = selected[0];
selected.Clear();
selected.Add(temp);
}
selected[0]--;
if (selected[0] < 0) selected[0] = bender.bendProperties.Length - 1;
}
Repaint();
SceneView.RepaintAll();
Event.current.Use();
}
}
}
string editModeText = "Enter Edit Mode";
if (!bender.bend) editModeText = "Bend";
if (GUILayout.Button(editModeText))
{
if (bender.bend) bender.bend = false;
else bender.bend = true;
}
if (bender.bend && !generatedUvs)
{
if (GUILayout.Button("Generate Lightmap UVS"))
{
bender.EditorGenerateLightmapUVs();
generatedUvs = true;
}
}
}
protected override void OnSceneGUI()
{
base.OnSceneGUI();
ObjectBender bender = (ObjectBender)target;
if (selected.Count > 0)
{
Handles.BeginGUI();
for(int i = 0; i < selected.Count; i++)
{
Vector2 screenPosition = HandleUtility.WorldToGUIPoint(bender.bendProperties[selected[i]].transform.transform.position);
DreamteckEditorGUI.Label(new Rect(screenPosition.x - 120 + bender.bendProperties[selected[i]].transform.transform.name.Length * 4, screenPosition.y, 120, 25), bender.bendProperties[selected[i]].transform.transform.name);
}
Handles.EndGUI();
}
for(int i = 0; i < bender.bendProperties.Length; i++)
{
if(bender.bendProperties[i].bendSpline && bender.bendProperties[i].splineComputer != null)
{
SplineDrawer.DrawSplineComputer(bender.bendProperties[i].splineComputer, 0.0, 1.0, 0.2f);
}
}
//Draw bounds
if (bender.bend) return;
TS_Bounds bound = bender.GetBounds();
Vector3 a = bender.transform.TransformPoint(bound.min);
Vector3 b = bender.transform.TransformPoint(new Vector3(bound.max.x, bound.min.y, bound.min.z));
Vector3 c = bender.transform.TransformPoint(new Vector3(bound.max.x, bound.min.y, bound.max.z));
Vector3 d = bender.transform.TransformPoint(new Vector3(bound.min.x, bound.min.y, bound.max.z));
Vector3 e = bender.transform.TransformPoint(new Vector3(bound.min.x, bound.max.y, bound.min.z));
Vector3 f = bender.transform.TransformPoint(new Vector3(bound.max.x, bound.max.y, bound.min.z));
Vector3 g = bender.transform.TransformPoint(new Vector3(bound.max.x, bound.max.y, bound.max.z));
Vector3 h = bender.transform.TransformPoint(new Vector3(bound.min.x, bound.max.y, bound.max.z));
Handles.color = Color.gray;
Handles.DrawLine(a, b);
Handles.DrawLine(b, c);
Handles.DrawLine(c, d);
Handles.DrawLine(d, a);
Handles.DrawLine(e, f);
Handles.DrawLine(f, g);
Handles.DrawLine(g, h);
Handles.DrawLine(h, e);
Handles.DrawLine(a, e);
Handles.DrawLine(b, f);
Handles.DrawLine(c, g);
Handles.DrawLine(d, h);
Vector3 r = bender.transform.right;
Vector3 fr = bender.transform.forward;
switch (bender.axis)
{
case ObjectBender.Axis.Z: Handles.color = Color.blue; Handles.DrawLine(r + b, r + c); break;
case ObjectBender.Axis.X: Handles.color = Color.red; Handles.DrawLine(b - fr, a - fr); break;
case ObjectBender.Axis.Y: Handles.color = Color.green; Handles.DrawLine(b- fr + r, f - fr + r); break;
}
}
protected override void OnDestroy()
{
SplineUser user = (SplineUser)target;
if (Application.isEditor && !Application.isPlaying)
{
if (user == null) OnDelete(); //The object or the component is being deleted
else if (user.spline != null)
{
if(!generatedUvs) user.Rebuild();
}
}
SplineComputerEditor.hold = false;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 09a7b4cd1afdfcd48b026eef6eef39db
timeCreated: 1463257593
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,183 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
using Dreamteck.Splines;
[CustomEditor(typeof(ObjectController))]
[CanEditMultipleObjects]
public class ObjectControllerEditor : SplineUserEditor
{
protected override void BodyGUI()
{
base.BodyGUI();
ObjectController user = (ObjectController)target;
serializedObject.Update();
SerializedProperty objectMethod = serializedObject.FindProperty("_objectMethod");
SerializedProperty retainPrefabInstancesInEditor = serializedObject.FindProperty("_retainPrefabInstancesInEditor");
SerializedProperty spawnCount = serializedObject.FindProperty("_spawnCount");
SerializedProperty delayedSpawn = serializedObject.FindProperty("delayedSpawn");
SerializedProperty spawnDelay = serializedObject.FindProperty("spawnDelay");
SerializedProperty iteration = serializedObject.FindProperty("_iteration");
SerializedProperty applyRotation = serializedObject.FindProperty("_applyRotation");
SerializedProperty minRotation = serializedObject.FindProperty("_minRotation");
SerializedProperty maxRotation = serializedObject.FindProperty("_maxRotation");
SerializedProperty applyScale = serializedObject.FindProperty("_applyScale");
SerializedProperty minScaleMultiplier = serializedObject.FindProperty("_minScaleMultiplier");
SerializedProperty maxScaleMultiplier = serializedObject.FindProperty("_maxScaleMultiplier");
SerializedProperty objectPositioning = serializedObject.FindProperty("_objectPositioning");
SerializedProperty evaluateOffset = serializedObject.FindProperty("_evaluateOffset");
SerializedProperty offsetUseWorldCoords = serializedObject.FindProperty("_offsetUseWorldCoords");
SerializedProperty minOffset = serializedObject.FindProperty("_minOffset");
SerializedProperty maxOffset = serializedObject.FindProperty("_maxOffset");
SerializedProperty shellOffset = serializedObject.FindProperty("_shellOffset");
SerializedProperty rotateByOffset = serializedObject.FindProperty("_rotateByOffset");
SerializedProperty randomSeed = serializedObject.FindProperty("_randomSeed");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(objectMethod, new GUIContent("Object Method"));
if (objectMethod.intValue == (int)ObjectController.ObjectMethod.Instantiate) EditorGUILayout.PropertyField(retainPrefabInstancesInEditor, new GUIContent("Retain Prefab Instances"));
if (objectMethod.intValue == (int)ObjectController.ObjectMethod.Instantiate)
{
bool objectsChanged = false;
bool hasObj = false;
if (users.Length > 1)
{
EditorGUILayout.HelpBox("Editing unavailable when multiple objects are selected", MessageType.Info);
}
else
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Instantiate Objects", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical();
for (int i = 0; i < user.objects.Length; i++)
{
EditorGUILayout.BeginHorizontal();
user.objects[i] = (GameObject)EditorGUILayout.ObjectField(user.objects[i], typeof(GameObject), true);
if (GUILayout.Button("x", GUILayout.Width(20)))
{
GameObject[] newObjects = new GameObject[user.objects.Length - 1];
for (int n = 0; n < user.objects.Length; n++)
{
if (n < i) newObjects[n] = user.objects[n];
else if (n == i) continue;
else newObjects[n - 1] = user.objects[n];
objectsChanged = true;
}
user.objects = newObjects;
}
if (i > 0)
{
if (GUILayout.Button("▲", GUILayout.Width(20)))
{
GameObject temp = user.objects[i - 1];
user.objects[i - 1] = user.objects[i];
user.objects[i] = temp;
objectsChanged = true;
}
}
if (i < user.objects.Length - 1)
{
if (GUILayout.Button("▼", GUILayout.Width(20)))
{
GameObject temp = user.objects[i + 1];
user.objects[i + 1] = user.objects[i];
user.objects[i] = temp;
objectsChanged = true;
}
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();
GameObject newObj = null;
newObj = (GameObject)EditorGUILayout.ObjectField("Add Object", newObj, typeof(GameObject), true);
if (newObj != null)
{
GameObject[] newObjects = new GameObject[user.objects.Length + 1];
user.objects.CopyTo(newObjects, 0);
newObjects[newObjects.Length - 1] = newObj;
user.objects = newObjects;
objectsChanged = true;
}
for (int i = 0; i < user.objects.Length; i++)
{
if (user.objects[i] != null)
{
hasObj = true;
break;
}
}
}
int lastSpawnCount = spawnCount.intValue;
if (hasObj) EditorGUILayout.PropertyField(spawnCount, new GUIContent("Spawn Count"));
else spawnCount.intValue = 0;
if (lastSpawnCount != spawnCount.intValue) objectsChanged = true;
EditorGUILayout.PropertyField(delayedSpawn, new GUIContent("Delayed Spawn"));
if (delayedSpawn.boolValue) EditorGUILayout.PropertyField(spawnDelay, new GUIContent("Spawn Delay"));
int lastIteration = iteration.intValue;
EditorGUILayout.PropertyField(iteration, new GUIContent("Iteration"));
if (lastIteration != iteration.intValue) objectsChanged = true;
if (objectsChanged)
{
serializedObject.ApplyModifiedProperties();
user.Clear();
user.Spawn();
}
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Transform", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(applyRotation, new GUIContent("Apply Rotation"));
if (user.applyRotation)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(minRotation, new GUIContent("Min. Rotation Offset"));
EditorGUILayout.PropertyField(maxRotation, new GUIContent("Max. Rotation Offset"));
EditorGUI.indentLevel--;
}
EditorGUILayout.PropertyField(applyScale, new GUIContent("Apply Scale"));
if (user.applyScale)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(minScaleMultiplier, new GUIContent("Min. Scale Multiplier"));
EditorGUILayout.PropertyField(maxScaleMultiplier, new GUIContent("Max. Scale Multiplier"));
EditorGUI.indentLevel--;
}
EditorGUILayout.PropertyField(objectPositioning, new GUIContent("Object Positioning"));
EditorGUILayout.PropertyField(evaluateOffset, new GUIContent("Evaluate Offset"));
if (offsetUseWorldCoords.boolValue)
{
minOffset.vector3Value = EditorGUILayout.Vector3Field("Min. Offset", minOffset.vector3Value);
maxOffset.vector3Value = EditorGUILayout.Vector3Field("Max. Offset", maxOffset.vector3Value);
}
else
{
minOffset.vector3Value = EditorGUILayout.Vector2Field("Min. Offset", minOffset.vector3Value);
maxOffset.vector3Value = EditorGUILayout.Vector2Field("Max. Offset", maxOffset.vector3Value);
}
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(offsetUseWorldCoords, new GUIContent("Use World Coords."));
if(minOffset.vector3Value != maxOffset.vector3Value) EditorGUILayout.PropertyField(shellOffset, new GUIContent("Shell"));
EditorGUI.indentLevel--;
EditorGUILayout.PropertyField(rotateByOffset, new GUIContent("Rotate by Offset"));
EditorGUILayout.PropertyField(randomSeed, new GUIContent("Random Seed"));
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4be170f07c25f6840a0370aab63c89af
timeCreated: 1455911715
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,66 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(ParticleController))]
[CanEditMultipleObjects]
public class ParticleControllerEditor : SplineUserEditor
{
protected override void BodyGUI()
{
base.BodyGUI();
ParticleController user = (ParticleController)target;
serializedObject.Update();
SerializedProperty _particleSystem = serializedObject.FindProperty("_particleSystem");
SerializedProperty emitPoint = serializedObject.FindProperty("emitPoint");
SerializedProperty volumetric = serializedObject.FindProperty("volumetric");
SerializedProperty emitFromShell = serializedObject.FindProperty("emitFromShell");
SerializedProperty scale = serializedObject.FindProperty("scale");
SerializedProperty motionType = serializedObject.FindProperty("motionType");
SerializedProperty wrapMode = serializedObject.FindProperty("wrapMode");
SerializedProperty minCycles = serializedObject.FindProperty("minCycles");
SerializedProperty maxCycles = serializedObject.FindProperty("maxCycles");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_particleSystem, new GUIContent("Particle System"));
if (_particleSystem.objectReferenceValue == null)
{
EditorGUILayout.HelpBox("No particle system is assigned", MessageType.Error);
return;
}
EditorGUILayout.PropertyField(emitPoint);
EditorGUILayout.PropertyField(volumetric);
if (volumetric.boolValue)
{
EditorGUILayout.PropertyField(emitFromShell);
EditorGUILayout.PropertyField(scale);
}
EditorGUILayout.PropertyField(motionType);
if(motionType.intValue == (int)ParticleController.MotionType.FollowForward || motionType.intValue == (int)ParticleController.MotionType.FollowBackward)
{
EditorGUILayout.PropertyField(wrapMode);
EditorGUILayout.Space();
EditorGUILayout.LabelField("Path cycles (over " + user._particleSystem.main.startLifetime.constantMax + "s.)", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(minCycles, new GUIContent("Min. Cycles"));
if (minCycles.floatValue < 0f) minCycles.floatValue = 0f;
EditorGUILayout.PropertyField(maxCycles, new GUIContent("Max. Cycles"));
if (maxCycles.floatValue < minCycles.floatValue) maxCycles.floatValue = minCycles.floatValue;
}
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
if (!Application.isPlaying)
{
EditorGUILayout.HelpBox("Particles may not work in the editor preview. Play the game to see the in-game result.", MessageType.Info);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b2fe6a6d8bb85894c96049081f441293
timeCreated: 1455991724
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(PathGenerator), true)]
[CanEditMultipleObjects]
public class PathGeneratorEditor : MeshGenEditor
{
protected override void BodyGUI()
{
base.BodyGUI();
PathGenerator pathGenerator = (PathGenerator)target;
serializedObject.Update();
SerializedProperty slices = serializedObject.FindProperty("_slices");
SerializedProperty shape = serializedObject.FindProperty("_shape");
SerializedProperty shapeExposure = serializedObject.FindProperty("_shapeExposure");
SerializedProperty useShapeCurve = serializedObject.FindProperty("_useShapeCurve");
EditorGUI.BeginChangeCheck();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Geometry", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(slices, new GUIContent("Slices"));
EditorGUILayout.PropertyField(useShapeCurve, new GUIContent("Use Shape Curve"));
if (useShapeCurve.boolValue)
{
if(shape.animationCurveValue == null || shape.animationCurveValue.keys.Length == 0)
{
shape.animationCurveValue = new AnimationCurve();
shape.animationCurveValue.AddKey(new Keyframe(0, 0));
shape.animationCurveValue.AddKey(new Keyframe(1, 0));
}
if (slices.intValue == 1) EditorGUILayout.HelpBox("Slices are set to 1. The curve shape may not be approximated correctly. You can increase the slices in order to fix that.", MessageType.Warning);
EditorGUILayout.PropertyField(shape, new GUIContent("Shape Curve"));
EditorGUILayout.PropertyField(shapeExposure, new GUIContent("Shape Exposure"));
}
if (slices.intValue < 1) slices.intValue = 1;
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
UVControls(pathGenerator);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: fb780cd10e9c18946bf622bab1d979d9
timeCreated: 1454061509
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(PolygonColliderGenerator))]
[CanEditMultipleObjects]
public class PolygonColliderGenEditor : SplineUserEditor
{
protected override void BodyGUI()
{
base.BodyGUI();
PolygonColliderGenerator generator = (PolygonColliderGenerator)target;
serializedObject.Update();
SerializedProperty type = serializedObject.FindProperty("_type");
SerializedProperty size = serializedObject.FindProperty("_size");
SerializedProperty offset = serializedObject.FindProperty("_offset");
SerializedProperty updateRate = serializedObject.FindProperty("updateRate");
EditorGUILayout.Space();
EditorGUILayout.LabelField("Polygon", EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(type, new GUIContent("Type"));
if (type.intValue == (int)PolygonColliderGenerator.Type.Path) EditorGUILayout.PropertyField(size, new GUIContent("Size"));
EditorGUILayout.PropertyField(offset, new GUIContent("Offset"));
EditorGUILayout.PropertyField(updateRate);
if (updateRate.floatValue < 0f) updateRate.floatValue = 0f;
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: db08e631e1379c04898db9f7c1414513
timeCreated: 1466252290
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class DistanceWindow : EditorWindow
{
float distance = 0f;
DistanceReceiver rcv;
float length = 0f;
public delegate void DistanceReceiver(float distance);
public void Init(DistanceReceiver receiver, float totalLength)
{
rcv = receiver;
length = totalLength;
titleContent = new GUIContent("Set Distance");
minSize = maxSize = new Vector2(240, 90);
}
private void OnGUI()
{
if (Event.current.type == EventType.KeyDown && (Event.current.keyCode == KeyCode.KeypadEnter || Event.current.keyCode == KeyCode.Return))
{
rcv(distance);
Close();
}
distance = EditorGUILayout.FloatField("Distance", distance);
if (distance < 0f) distance = 0f;
else if (distance > length) distance = length;
if (distance > 0f)
{
EditorGUILayout.LabelField("Press Enter to set.", EditorStyles.centeredGreyMiniLabel);
}
EditorGUILayout.HelpBox("Enter the distance and press Enter. Current spline length: " + length, MessageType.Info);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17ee393449811f045b95ade0241f6d05
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,106 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(SplineFollower), true)]
[CanEditMultipleObjects]
public class SplineFollowerEditor : SplineTracerEditor
{
SplineSample result = new SplineSample();
void OnSetDistance(float distance)
{
for (int i = 0; i < targets.Length; i++)
{
SplineFollower follower = (SplineFollower)targets[i];
double travel = follower.Travel(0.0, distance, Spline.Direction.Forward);
follower.startPosition = travel;
}
}
protected override void BodyGUI()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Following", EditorStyles.boldLabel);
SplineFollower follower = (SplineFollower)target;
serializedObject.Update();
SerializedProperty followMode = serializedObject.FindProperty("followMode");
SerializedProperty wrapMode = serializedObject.FindProperty("wrapMode");
SerializedProperty startPosition = serializedObject.FindProperty("_startPosition");
SerializedProperty autoStartPosition = serializedObject.FindProperty("autoStartPosition");
SerializedProperty follow = serializedObject.FindProperty("follow");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(follow);
EditorGUILayout.PropertyField(followMode);
if (followMode.intValue == (int)SplineFollower.FollowMode.Uniform)
{
SerializedProperty followSpeed = serializedObject.FindProperty("_followSpeed");
EditorGUILayout.PropertyField(followSpeed, new GUIContent("Follow Speed"));
if (followSpeed.floatValue < 0f) followSpeed.floatValue = 0f;
}
else follower.followDuration = EditorGUILayout.FloatField("Follow duration", follower.followDuration);
EditorGUILayout.PropertyField(wrapMode);
if (follower.motion.applyRotation) follower.applyDirectionRotation = EditorGUILayout.Toggle("Face Direction", follower.applyDirectionRotation);
EditorGUILayout.Space();
EditorGUILayout.LabelField("Start Position", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(autoStartPosition, new GUIContent("Project"));
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 100f;
if (!follower.autoStartPosition && !Application.isPlaying)
{
EditorGUILayout.PropertyField(startPosition, new GUIContent("Start Position"));
if(GUILayout.Button("Set Distance", GUILayout.Width(85)))
{
DistanceWindow w = EditorWindow.GetWindow<DistanceWindow>(true);
w.Init(OnSetDistance, follower.CalculateLength());
}
}
else EditorGUILayout.LabelField("Start position", GUILayout.Width(EditorGUIUtility.labelWidth));
EditorGUILayout.EndHorizontal();
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
if (!Application.isPlaying && follower.spline.sampleCount > 0)
{
if (!follower.autoStartPosition)
{
follower.SetPercent(startPosition.floatValue);
if (!follower.follow) SceneView.RepaintAll();
}
}
}
base.BodyGUI();
}
protected override void OnSceneGUI()
{
base.OnSceneGUI();
SplineFollower user = (SplineFollower)target;
if (user == null) return;
if (Application.isPlaying)
{
if (!user.follow) DrawResult(user.modifiedResult);
return;
}
if (user.spline == null) return;
if (user.autoStartPosition)
{
user.spline.Project(result, user.transform.position, user.clipFrom, user.clipTo);
DrawResult(result);
} else if(!user.follow) DrawResult(user.result);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f0ceef9665459454c863f7c9a1de1685
timeCreated: 1454878386
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,446 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(SplineMesh), true)]
[CanEditMultipleObjects]
public class SplineMeshEditor : MeshGenEditor
{
int selected = -1;
SplineMesh.Channel renameChannel = null;
MeshDefinitionWindow definitionWindow = null;
private Mesh GetMeshFromObject(Object obj)
{
SplineMesh user = (SplineMesh)target;
if (!(obj is GameObject)) return null;
GameObject gameObj = (GameObject)obj;
MeshFilter filter = gameObj.GetComponent<MeshFilter>();
Mesh returnMesh = null;
if (filter != null && filter.sharedMesh != null) returnMesh = filter.sharedMesh;
MeshRenderer rend = user.GetComponent<MeshRenderer>();
if (rend == null) return returnMesh;
MeshRenderer meshRend = gameObj.GetComponent<MeshRenderer>();
if (meshRend == null) return returnMesh;
bool found = false;
for (int i = 0; i < meshRend.sharedMaterials.Length; i++)
{
for (int j = 0; j < rend.sharedMaterials.Length; j++)
{
if(meshRend.sharedMaterials[i] == rend.sharedMaterials[j])
{
found = true;
break;
}
}
}
if (!found)
{
if(EditorUtility.DisplayDialog("New Materials", "The added object has one or more materials which are not refrenced by the renderer. Would you like to add them?", "Yes", "No")) {
if(rend.sharedMaterial == AssetDatabase.GetBuiltinExtraResource<Material>("Default-Diffuse.mat"))
{
if (EditorUtility.DisplayDialog("Replace Material", "The renderer is using the default material. Replace it?", "Yes", "No")) rend.sharedMaterials = new Material[0];
}
for (int i = 0; i < meshRend.sharedMaterials.Length; i++) AddMaterial(rend, meshRend.sharedMaterials[i]);
}
}
return returnMesh;
}
void AddMaterial(MeshRenderer target, Material material)
{
for (int i = 0; i < target.sharedMaterials.Length; i++)
{
if (target.sharedMaterials[i] == material) return;
}
Material[] newMaterials = new Material[target.sharedMaterials.Length + 1];
target.sharedMaterials.CopyTo(newMaterials, 0);
newMaterials[newMaterials.Length - 1] = material;
target.sharedMaterials = newMaterials;
}
void OnDuplicateChannel(object index)
{
SplineMesh extruder = (SplineMesh)target;
SplineMesh.Channel source = extruder.GetChannel((int)index);
SplineMesh.Channel newChannel = extruder.AddChannel(source.name);
source.CopyTo(newChannel);
}
void OnRenameChannel(object index)
{
SplineMesh extruder = (SplineMesh)target;
renameChannel = extruder.GetChannel((int)index);
Repaint();
}
void OnDeleteChannel(object index)
{
SplineMesh extruder = (SplineMesh)target;
extruder.RemoveChannel((int)index);
Repaint();
}
void OnMoveChannelUp(object index)
{
SplineMesh extruder = (SplineMesh)target;
extruder.SwapChannels((int)index, ((int)index)-1);
Repaint();
}
void OnMoveChannelDown(object index)
{
SplineMesh extruder = (SplineMesh)target;
extruder.SwapChannels((int)index, ((int)index) + 1);
Repaint();
}
protected override void BodyGUI()
{
showSize = false;
showColor = false;
showDoubleSided = false;
showFlipFaces = false;
base.BodyGUI();
SplineMesh user = (SplineMesh)target;
EditorGUI.BeginChangeCheck();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Uv Coordinates", EditorStyles.boldLabel);
user.uvOffset = EditorGUILayout.Vector2Field("UV Offset", user.uvOffset);
user.uvScale = EditorGUILayout.Vector2Field("UV Scale", user.uvScale);
if (targets.Length > 1)
{
EditorGUILayout.HelpBox("Cannot edit channels when multiple objects are selected", MessageType.Info);
return;
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Channels", EditorStyles.boldLabel);
for (int i = 0; i < user.GetChannelCount(); i++)
{
if (ChannelPanel(user.GetChannel(i), selected == i))
{
if (Event.current.type == EventType.MouseDown)
{
Repaint();
if (Event.current.button == 0)
{
if (selected == i) selected = -1;
else selected = i;
}
else if (Event.current.button == 1)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Rename"), false, OnRenameChannel, i);
menu.AddItem(new GUIContent("Duplicate"), false, OnDuplicateChannel, i);
if (i == 0) menu.AddDisabledItem(new GUIContent("Move Up"));
else menu.AddItem(new GUIContent("Move Up"), false, OnMoveChannelUp, i);
if (i == user.GetChannelCount() - 1) menu.AddDisabledItem(new GUIContent("Move Down"));
else menu.AddItem(new GUIContent("Move Down"), false, OnMoveChannelDown, i);
menu.AddSeparator("");
menu.AddItem(new GUIContent("Delete"), false, OnDeleteChannel, i);
menu.ShowAsContext();
}
}
}
}
if (GUILayout.Button("New Channel")) user.AddChannel("Channel " + (user.GetChannelCount() + 1));
if (EditorGUI.EndChangeCheck()) EditorUtility.SetDirty(user);
}
bool ChannelPanel(SplineMesh.Channel channel, bool open)
{
GUILayout.BeginVertical(EditorStyles.helpBox);
if (renameChannel == channel && Event.current.type == EventType.KeyDown && (Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter))
{
renameChannel = null;
Repaint();
}
if (renameChannel == channel) channel.name = EditorGUILayout.TextField(channel.name);
else EditorGUILayout.LabelField(channel.name, EditorStyles.boldLabel);
if (!open)
{
GUILayout.EndVertical();
return GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition);
}
Rect labelRect = GUILayoutUtility.GetLastRect();
EditorGUI.indentLevel++;
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mesh Objects", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 120f;
EditorGUILayout.BeginVertical();
for (int i = 0; i < channel.GetMeshCount(); i++) MeshRow(channel, i);
Object obj = null;
obj = EditorGUILayout.ObjectField("Add Mesh", obj, typeof(Object), true);
if (obj != null)
{
if (obj is Mesh) channel.AddMesh((Mesh)obj);
else
{
Mesh m = GetMeshFromObject(obj);
if (m != null) channel.AddMesh(m);
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
channel.type = (SplineMesh.Channel.Type)EditorGUILayout.EnumPopup("Type", channel.type);
if (channel.autoCount) EditorGUILayout.TextField("Auto Count: " + channel.count);
else channel.count = EditorGUILayout.IntField("Count", channel.count);
channel.autoCount = EditorGUILayout.Toggle("Auto Count", channel.autoCount);
channel.randomOrder = EditorGUILayout.Toggle("Random Order", channel.randomOrder);
if (channel.randomOrder) channel.randomSeed = EditorGUILayout.IntField("Seed", channel.randomSeed);
EditorGUILayout.EndVertical();
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
float clipFrom = (float)channel.clipFrom;
float clipTo = (float)channel.clipTo;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.MinMaxSlider(new GUIContent("Clip Range:"), ref clipFrom, ref clipTo, 0f, 1f);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
channel.clipFrom = clipFrom;
channel.clipTo = clipTo;
EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(30));
channel.clipFrom = EditorGUILayout.FloatField((float)channel.clipFrom);
channel.clipTo = EditorGUILayout.FloatField((float)channel.clipTo);
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Geometry", EditorStyles.boldLabel);
if(channel.type != SplineMesh.Channel.Type.Place) channel.spacing = EditorGUILayout.Slider("Spacing", (float)channel.spacing, 0f, 1f);
//Offset
channel.minOffset = EditorGUILayout.Vector2Field(channel.randomOffset ? "Offset Min" : "Offset", channel.minOffset);
if(channel.randomOffset) channel.maxOffset = EditorGUILayout.Vector2Field("Offset Max", channel.maxOffset);
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 130f;
channel.randomOffset = EditorGUILayout.Toggle("Randomize Offset", channel.randomOffset);
if (channel.randomOffset) channel.offsetSeed = EditorGUILayout.IntField("Seed", channel.offsetSeed);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
//Rotation
if (channel.type == SplineMesh.Channel.Type.Extrude)
{
Vector3 rot = channel.minRotation;
rot.z = EditorGUILayout.FloatField(channel.randomRotation ? "Rotation Min" : "Rotation", rot.z);
channel.minRotation = rot;
if (channel.randomRotation)
{
rot = channel.maxRotation;
rot.z = EditorGUILayout.FloatField("Rotation Max", rot.z);
channel.maxRotation = rot;
}
}
else
{
channel.minRotation = EditorGUILayout.Vector3Field(channel.randomRotation ? "Rotation Min" : "Rotation", channel.minRotation);
if (channel.randomRotation) channel.maxRotation = EditorGUILayout.Vector3Field("Rotation Max", channel.maxRotation);
}
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 130f;
channel.randomRotation = EditorGUILayout.Toggle("Randomize Rotation", channel.randomRotation);
if (channel.randomRotation) channel.rotationSeed = EditorGUILayout.IntField("Seed", channel.rotationSeed);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
//Scale
if (channel.type == SplineMesh.Channel.Type.Extrude)
{
float lastZ = channel.minScale.z;
Vector3 scale = channel.minScale;
scale = EditorGUILayout.Vector2Field(channel.randomScale ? "Scale Min" : "Scale", scale);
scale += Vector3.forward * lastZ;
channel.minScale = scale;
if (channel.randomScale)
{
lastZ = channel.maxScale.z;
scale = channel.maxScale;
scale = EditorGUILayout.Vector2Field("Scale Max", scale);
scale += Vector3.forward * lastZ;
channel.maxScale = scale;
}
}
else
{
channel.minScale = EditorGUILayout.Vector3Field(channel.randomScale ? "Scale Min" : "Scale", channel.minScale);
if (channel.randomScale) channel.maxScale = EditorGUILayout.Vector3Field("Scale Max", channel.maxScale);
}
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 130f;
channel.randomScale = EditorGUILayout.Toggle("Randomize Scale", channel.randomScale);
if (channel.randomScale) channel.scaleSeed = EditorGUILayout.IntField("Seed", channel.scaleSeed);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
if (channel.randomScale)
{
EditorGUI.indentLevel++;
EditorGUIUtility.labelWidth = 120f;
channel.uniformRandomScale = EditorGUILayout.Toggle("Uniform", channel.uniformRandomScale);
EditorGUIUtility.labelWidth = 0f;
EditorGUI.indentLevel--;
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("UV Coordinates", EditorStyles.boldLabel);
channel.uvOffset = EditorGUILayout.Vector2Field("UV Offset", channel.uvOffset);
channel.uvScale = EditorGUILayout.Vector2Field("UV Scale", channel.uvScale);
//Override
EditorGUILayout.Space();
EditorGUILayout.LabelField("Override", EditorStyles.boldLabel);
channel.overrideNormal = EditorGUILayout.Toggle("Normal", channel.overrideNormal);
if(channel.overrideNormal) channel.customNormal = EditorGUILayout.Vector3Field("Normal", channel.customNormal);
if (channel.type == SplineMesh.Channel.Type.Extrude)
{
channel.overrideUVs = (SplineMesh.Channel.UVOverride)EditorGUILayout.EnumPopup("UVs", channel.overrideUVs);
if(channel.overrideUVs != SplineMesh.Channel.UVOverride.None)
{
}
}
channel.overrideMaterialID = EditorGUILayout.Toggle("Material IDs", channel.overrideMaterialID);
if (channel.overrideMaterialID) channel.targetMaterialID = EditorGUILayout.IntField("Target ID", channel.targetMaterialID);
EditorGUI.indentLevel--;
GUILayout.EndVertical();
return labelRect.Contains(Event.current.mousePosition);
}
void OnDuplicateMesh(object mesh)
{
MeshLink link = (MeshLink)mesh;
link.channel.DuplicateMesh(link.index);
}
void OnDeleteMesh(object mesh)
{
MeshLink link = (MeshLink)mesh;
link.channel.RemoveMesh(link.index);
Repaint();
}
void OnMoveMeshUp(object mesh)
{
MeshLink link = (MeshLink)mesh;
link.channel.SwapMeshes(link.index, link.index - 1);
Repaint();
}
void OnMoveMeshDown(object mesh)
{
MeshLink link = (MeshLink)mesh;
link.channel.SwapMeshes(link.index, link.index + 1);
Repaint();
}
void MeshRow(SplineMesh.Channel channel, int index)
{
SplineMesh.Channel.MeshDefinition definition = channel.GetMesh(index);
EditorGUILayout.BeginHorizontal();
GUILayout.Space(15);
if(definition.mesh == null) GUILayout.Box("NULL", EditorStyles.helpBox, GUILayout.MinWidth(200));
else GUILayout.Box(definition.mesh.name, EditorStyles.helpBox, GUILayout.MinWidth(200));
EditorGUILayout.EndHorizontal();
Rect rect = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)){
if(Event.current.button == 0)
{
definitionWindow = EditorWindow.GetWindow<MeshDefinitionWindow>(true);
definitionWindow.Init((SplineMesh)target, definition);
}
if(Event.current.button == 1)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Duplicate"), false, OnDuplicateMesh, new MeshLink(index, channel));
if (index == 0) menu.AddDisabledItem(new GUIContent("Move Up"));
else menu.AddItem(new GUIContent("Move Up"), false, OnMoveMeshUp, new MeshLink(index, channel));
if (index == channel.GetMeshCount() - 1) menu.AddDisabledItem(new GUIContent("Move Down"));
else menu.AddItem(new GUIContent("Move Down"), false, OnMoveMeshDown, new MeshLink(index, channel));
menu.AddSeparator("");
menu.AddItem(new GUIContent("Delete"), false, OnDeleteMesh, new MeshLink(index, channel));
menu.ShowAsContext();
}
}
}
protected override void OnDestroy()
{
base.OnDestroy();
if (definitionWindow != null) definitionWindow.Close();
}
internal class MeshLink
{
internal int index = 0;
internal SplineMesh.Channel channel;
internal MeshLink(int i, SplineMesh.Channel l)
{
index = i;
channel = l;
}
}
public class MeshDefinitionWindow : EditorWindow
{
internal SplineMesh.Channel.MeshDefinition definition = null;
internal SplineMesh extrude = null;
internal void Init(SplineMesh e, SplineMesh.Channel.MeshDefinition d)
{
minSize = new Vector2(482, 180);
extrude = e;
definition = d;
if(definition.mesh != null) titleContent = new GUIContent("Configure " + definition.mesh.name);
else titleContent = new GUIContent("Configure Mesh");
}
private void OnGUI()
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Geometry", EditorStyles.boldLabel);
definition.mesh = (Mesh)EditorGUILayout.ObjectField(definition.mesh, typeof(Mesh), true);
definition.mirror = (SplineMesh.Channel.MeshDefinition.MirrorMethod)EditorGUILayout.EnumPopup("Mirror", definition.mirror);
definition.offset = EditorGUILayout.Vector2Field("Offset", definition.offset);
definition.rotation = EditorGUILayout.Vector3Field("Rotation", definition.rotation);
definition.scale = EditorGUILayout.Vector3Field("Scale", definition.scale);
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Faces", EditorStyles.boldLabel);
definition.doubleSided = EditorGUILayout.Toggle("Double sided", definition.doubleSided);
if (definition.doubleSided) definition.flipFaces = false;
else definition.flipFaces = EditorGUILayout.Toggle("Flip Faces", definition.flipFaces);
definition.removeInnerFaces = EditorGUILayout.Toggle("Remove Inner Faces", definition.removeInnerFaces);
EditorGUILayout.LabelField("UVs", EditorStyles.boldLabel);
definition.uvOffset = EditorGUILayout.Vector2Field("UV Offset", definition.uvOffset);
definition.uvScale = EditorGUILayout.Vector2Field("UV Scale", definition.uvScale);
definition.uvRotation = EditorGUILayout.Slider("UV Rotation", definition.uvRotation, -180f, 180f);
definition.vertexGroupingMargin = EditorGUILayout.FloatField("Vertex Grouping Margin", definition.vertexGroupingMargin);
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
if (GUI.changed) extrude.Rebuild();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 411935f4b3b0d9b428e92c1b65a2fc16
timeCreated: 1454084824
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,153 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(SplineMorph))]
public class SplineMorphEditor : Editor
{
private string addName = "";
bool rename = false;
int selected = -1;
SplineMorph morph;
private void OnEnable()
{
morph = (SplineMorph)target;
GetAddName();
}
void GetAddName()
{
addName = "Channel " + morph.GetChannelCount();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
Undo.RecordObject(morph, "Edit Morph");
morph.spline = (SplineComputer)EditorGUILayout.ObjectField("Spline", morph.spline, typeof(SplineComputer), true);
morph.space = (SplineComputer.Space)EditorGUILayout.EnumPopup("Space", morph.space);
morph.cycle = EditorGUILayout.Toggle("Runtime Cycle", morph.cycle);
if (morph.cycle)
{
EditorGUI.indentLevel++;
morph.cycleMode = (SplineMorph.CycleMode)EditorGUILayout.EnumPopup("Cycle Wrap", morph.cycleMode);
morph.cycleUpdateMode = (SplineMorph.UpdateMode)EditorGUILayout.EnumPopup("Update Mode", morph.cycleUpdateMode);
morph.cycleDuration = EditorGUILayout.FloatField("Cycle Duration", morph.cycleDuration);
EditorGUI.indentLevel--;
}
int channelCount = morph.GetChannelCount();
if (channelCount > 0)
{
if(morph.spline == null)
{
EditorGUILayout.HelpBox("No spline assigned.", MessageType.Error);
return;
}
if (morph.GetSnapshot(0).Length != morph.spline.pointCount)
{
EditorGUILayout.HelpBox("Recorded morphs require the spline to have " + morph.GetSnapshot(0).Length + ". The spline has " + morph.spline.pointCount, MessageType.Error);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Clear morph states"))
{
if (EditorUtility.DisplayDialog("Clear morph states?", "Do you want to clear all morph states?", "Yes", "No"))
{
morph.Clear();
}
}
string str = "Reduce";
if (morph.GetSnapshot(0).Length > morph.spline.pointCount) str = "Increase";
if (GUILayout.Button(str + " spline points"))
{
if (EditorUtility.DisplayDialog(str + " spline points?", "Do you want to " + str + " the spline points?", "Yes", "No"))
{
morph.spline.SetPoints(morph.GetSnapshot(0), SplineComputer.Space.Local);
}
}
EditorGUILayout.EndHorizontal();
return;
}
}
for (int i = 0; i < channelCount; i++) DrawChannel(i);
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("+", GUILayout.Width(40)))
{
morph.AddChannel(addName);
GetAddName();
}
addName = EditorGUILayout.TextField(addName);
EditorGUILayout.EndHorizontal();
if (GUI.changed) SceneView.RepaintAll();
}
void DrawChannel(int index)
{
SplineMorph.Channel channel = morph.GetChannel(index);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUI.backgroundColor = Color.white;
if (selected == index && rename)
{
if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return) rename = false;
channel.name = EditorGUILayout.TextField(channel.name);
}
else if (index > 0)
{
float weight = morph.GetWeight(index);
float lastWeight = weight;
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(new GUIContent("●", "Capture Snapshot"), GUILayout.Width(22f))) morph.CaptureSnapshot(index);
EditorGUILayout.LabelField(channel.name, GUILayout.Width(EditorGUIUtility.labelWidth));
weight = EditorGUILayout.Slider(weight, 0f, 1f);
EditorGUILayout.EndHorizontal();
if (lastWeight != weight) morph.SetWeight(index, weight);
SplineMorph.Channel.Interpolation lastInterpolation = channel.interpolation;
channel.interpolation = (SplineMorph.Channel.Interpolation)EditorGUILayout.EnumPopup("Interpolation", channel.interpolation);
if (lastInterpolation != channel.interpolation) morph.UpdateMorph();
channel.curve = EditorGUILayout.CurveField("Curve", channel.curve);
}
else
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(new GUIContent("●", "Capture Snapshot"), GUILayout.Width(22f))) morph.CaptureSnapshot(index);
GUILayout.Label(channel.name);
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();
Rect last = GUILayoutUtility.GetLastRect();
if (last.Contains(Event.current.mousePosition))
{
if(Event.current.type == EventType.MouseDown)
{
if (Event.current.button == 0)
{
rename = false;
selected = -1;
Repaint();
}
if (Event.current.button == 1)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Rename"), false, delegate { rename = true; selected = index; });
menu.AddItem(new GUIContent("Delete"), false, delegate
{
morph.SetWeight(index, 0f);
morph.RemoveChannel(index);
selected = -1;
GetAddName();
});
menu.ShowAsContext();
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1be9ae956377fd04384669edabafbd7f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(SplinePositioner), true)]
[CanEditMultipleObjects]
public class SplinePositionerEditor : SplineTracerEditor
{
protected override void BodyGUI()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Positioning", EditorStyles.boldLabel);
serializedObject.Update();
SerializedProperty mode = serializedObject.FindProperty("_mode");
EditorGUI.BeginChangeCheck();
SplinePositioner positioner = (SplinePositioner)target;
EditorGUILayout.PropertyField(mode, new GUIContent("Mode"));
if (positioner.mode == SplinePositioner.Mode.Distance) positioner.position = EditorGUILayout.FloatField("Distance", (float)positioner.position);
else
{
SerializedProperty percent = serializedObject.FindProperty("_result").FindPropertyRelative("percent");
EditorGUILayout.BeginHorizontal();
SerializedProperty position = serializedObject.FindProperty("_position");
double pos = positioner.ClipPercent(percent.floatValue);
EditorGUI.BeginChangeCheck();
pos = EditorGUILayout.Slider("Percent", (float)pos, 0f, 1f);
if (EditorGUI.EndChangeCheck()) position.floatValue = (float)pos;
if (GUILayout.Button("Set Distance", GUILayout.Width(85)))
{
DistanceWindow w = EditorWindow.GetWindow<DistanceWindow>(true);
w.Init(OnSetDistance, positioner.CalculateLength());
}
EditorGUILayout.EndHorizontal();
}
SerializedProperty targetObject = serializedObject.FindProperty("_targetObject");
EditorGUILayout.PropertyField(targetObject, new GUIContent("Target Object"));
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
base.BodyGUI();
}
void OnSetDistance(float distance)
{
for (int i = 0; i < targets.Length; i++)
{
SplinePositioner positioner = (SplinePositioner)targets[i];
double travel = positioner.Travel(0.0, distance, Spline.Direction.Forward);
positioner.position = travel;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7ac70fff277ab9440b800398df5fb37f
timeCreated: 1467621518
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(SplineProjector), true)]
[CanEditMultipleObjects]
public class SplineProjectorEditor : SplineTracerEditor
{
private bool info = false;
public override void OnInspectorGUI()
{
SplineProjector user = (SplineProjector)target;
if (user.mode == SplineProjector.Mode.Accurate)
{
showAveraging = false;
}
else
{
showAveraging = true;
}
base.OnInspectorGUI();
}
protected override void BodyGUI()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Projector", EditorStyles.boldLabel);
serializedObject.Update();
SerializedProperty mode = serializedObject.FindProperty("_mode");
SerializedProperty projectTarget = serializedObject.FindProperty("_projectTarget");
SerializedProperty targetObject = serializedObject.FindProperty("_targetObject");
SerializedProperty autoProject = serializedObject.FindProperty("_autoProject");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(mode, new GUIContent("Mode"));
if (mode.intValue == (int)SplineProjector.Mode.Accurate)
{
SerializedProperty subdivide = serializedObject.FindProperty("_subdivide");
EditorGUILayout.PropertyField(subdivide, new GUIContent("Subdivide"));
}
EditorGUILayout.PropertyField(projectTarget, new GUIContent("Project Target"));
EditorGUILayout.PropertyField(targetObject, new GUIContent("Apply Target"));
GUI.color = Color.white;
EditorGUILayout.PropertyField(autoProject, new GUIContent("Auto Project"));
info = EditorGUILayout.Foldout(info, "Info");
SerializedProperty percent = serializedObject.FindProperty("_result").FindPropertyRelative("percent");
if (info) EditorGUILayout.HelpBox("Projection percent: " + percent.floatValue, MessageType.Info);
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
base.BodyGUI();
}
protected override void OnSceneGUI()
{
base.OnSceneGUI();
for (int i = 0; i < users.Length; i++)
{
SplineProjector user = (SplineProjector)users[i];
if (user.spline == null) return;
if (!user.autoProject) return;
DrawResult(user.result);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2d67d75417f347c4ebff4e77014108eb
timeCreated: 1456327392
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(SplineRenderer), true)]
[CanEditMultipleObjects]
public class SplineRendererEditor : MeshGenEditor
{
protected override void BodyGUI()
{
showDoubleSided = false;
showFlipFaces = false;
showRotation = false;
showNormalMethod = false;
serializedObject.Update();
SerializedProperty slices = serializedObject.FindProperty("_slices");
SerializedProperty autoOrient = serializedObject.FindProperty("autoOrient");
SerializedProperty updateFrameInterval = serializedObject.FindProperty("updateFrameInterval");
base.BodyGUI();
EditorGUI.BeginChangeCheck();
SplineRenderer user = (SplineRenderer)target;
EditorGUILayout.Space();
EditorGUILayout.LabelField("Geometry", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(slices);
if (slices.intValue < 1) slices.intValue = 1;
EditorGUILayout.Space();
EditorGUILayout.LabelField("Render", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(autoOrient);
if (user.autoOrient)
{
EditorGUILayout.PropertyField(updateFrameInterval);
if (updateFrameInterval.intValue < 0) updateFrameInterval.intValue = 0;
}
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
UVControls(user);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 50802729861530b4fa1d9c6a58c5530c
timeCreated: 1454771332
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,156 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(SplineTracer), true)]
public class SplineTracerEditor : SplineUserEditor
{
private bool cameraFoldout = false;
private TransformModuleEditor motionEditor;
private RenderTexture rt;
private Texture2D renderCanvas = null;
private Camera cam;
SplineTracer[] tracers = new SplineTracer[0];
public delegate void DistanceReceiver(float distance);
protected override void OnEnable()
{
base.OnEnable();
SplineTracer tracer = (SplineTracer)target;
motionEditor = new TransformModuleEditor(tracer, this, tracer.motion);
tracers = new SplineTracer[targets.Length];
for (int i = 0; i < tracers.Length; i++) tracers[i] = (SplineTracer)targets[i];
}
private int GetRTWidth()
{
return Mathf.RoundToInt(EditorGUIUtility.currentViewWidth)-50;
}
private int GetRTHeight()
{
return Mathf.RoundToInt(GetRTWidth()/cam.aspect);
}
private void CreateRT()
{
if(rt != null)
{
DestroyImmediate(rt);
DestroyImmediate(renderCanvas);
}
rt = new RenderTexture(GetRTWidth(), GetRTHeight(), 16, RenderTextureFormat.Default, RenderTextureReadWrite.Default);
renderCanvas = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
}
protected override void OnDestroy()
{
base.OnDestroy();
DestroyImmediate(rt);
}
protected override void BodyGUI()
{
base.BodyGUI();
EditorGUILayout.LabelField("Tracing", EditorStyles.boldLabel);
SplineTracer tracer = (SplineTracer)target;
serializedObject.Update();
SerializedProperty useTriggers = serializedObject.FindProperty("useTriggers");
SerializedProperty triggerGroup = serializedObject.FindProperty("triggerGroup");
SerializedProperty direction = serializedObject.FindProperty("_direction");
SerializedProperty physicsMode = serializedObject.FindProperty("_physicsMode");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(useTriggers);
if (useTriggers.boolValue) EditorGUILayout.PropertyField(triggerGroup);
EditorGUILayout.PropertyField(direction, new GUIContent("Direction"));
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(physicsMode, new GUIContent("Physics Mode"));
if(EditorGUI.EndChangeCheck())
{
for (int i = 0; i < tracers.Length; i++) tracers[i].EditorAwake();
}
if (tracer.physicsMode == SplineTracer.PhysicsMode.Rigidbody)
{
Rigidbody rb = tracer.GetComponent<Rigidbody>();
if (rb == null) EditorGUILayout.HelpBox("Assign a Rigidbody component.", MessageType.Error);
else if (rb.interpolation == RigidbodyInterpolation.None && tracer.updateMethod != SplineUser.UpdateMethod.FixedUpdate) EditorGUILayout.HelpBox("Switch to FixedUpdate mode to ensure smooth update for non-interpolated rigidbodies", MessageType.Warning);
}
else if (tracer.physicsMode == SplineTracer.PhysicsMode.Rigidbody2D)
{
Rigidbody2D rb = tracer.GetComponent<Rigidbody2D>();
if (rb == null) EditorGUILayout.HelpBox("Assign a Rigidbody2D component.", MessageType.Error);
else if (rb.interpolation == RigidbodyInterpolation2D.None && tracer.updateMethod != SplineUser.UpdateMethod.FixedUpdate) EditorGUILayout.HelpBox("Switch to FixedUpdate mode to ensure smooth update for non-interpolated rigidbodies", MessageType.Warning);
}
if (tracers.Length == 1)
{
motionEditor.DrawInspector();
cameraFoldout = EditorGUILayout.Foldout(cameraFoldout, "Camera preview");
if (cameraFoldout)
{
if (cam == null)
{
cam = tracer.GetComponentInChildren<Camera>();
}
if (cam != null)
{
if (rt == null || rt.width != GetRTWidth() || rt.height != GetRTHeight()) CreateRT();
GUILayout.Box("", GUILayout.Width(rt.width), GUILayout.Height(rt.height));
RenderTexture prevTarget = cam.targetTexture;
RenderTexture prevActive = RenderTexture.active;
CameraClearFlags lastFlags = cam.clearFlags;
Color lastColor = cam.backgroundColor;
cam.targetTexture = rt;
cam.clearFlags = CameraClearFlags.Color;
cam.backgroundColor = Color.black;
cam.Render();
RenderTexture.active = rt;
renderCanvas.SetPixels(new Color[renderCanvas.width * renderCanvas.height]);
renderCanvas.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
renderCanvas.Apply();
RenderTexture.active = prevActive;
cam.targetTexture = prevTarget;
cam.clearFlags = lastFlags;
cam.backgroundColor = lastColor;
GUI.DrawTexture(GUILayoutUtility.GetLastRect(), renderCanvas, ScaleMode.StretchToFill);
}
else EditorGUILayout.HelpBox("There is no camera attached to the selected object or its children.", MessageType.Info);
}
}
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
for (int i = 0; i < tracers.Length; i++) tracers[i].Rebuild();
}
}
protected override void OnSceneGUI()
{
base.OnSceneGUI();
SplineTracer tracer = (SplineTracer)target;
}
protected void DrawResult(SplineSample result)
{
SplineTracer tracer = (SplineTracer)target;
Handles.color = Color.white;
Handles.DrawLine(tracer.transform.position, result.position);
SplineEditorHandles.DrawSolidSphere(result.position, HandleUtility.GetHandleSize(result.position) * 0.2f);
Handles.color = Color.blue;
Handles.DrawLine(result.position, result.position + result.forward * HandleUtility.GetHandleSize(result.position) * 0.5f);
Handles.color = Color.green;
Handles.DrawLine(result.position, result.position + result.up * HandleUtility.GetHandleSize(result.position) * 0.5f);
Handles.color = Color.red;
Handles.DrawLine(result.position, result.position + result.right * HandleUtility.GetHandleSize(result.position) * 0.5f);
Handles.color = Color.white;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3c6edfe32b7af2542b1eda2ec76580b9
timeCreated: 1495919748
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,340 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
[CustomEditor(typeof(SplineUser), true)]
[CanEditMultipleObjects]
public class SplineUserEditor : Editor
{
protected bool showClip = true;
protected bool showAveraging = true;
protected bool showUpdateMethod = true;
protected bool showMultithreading = true;
bool settings = false;
protected RotationModifierEditor rotationModifierEditor;
protected OffsetModifierEditor offsetModifierEditor;
protected ColorModifierEditor colorModifierEditor;
protected SizeModifierEditor sizeModifierEditor;
protected SplineUser[] users = new SplineUser[0];
protected SerializedObject serializedUsers;
SerializedProperty multithreaded, updateMethod, buildOnAwake, buildOnEnable, autoUpdate, loopSamples, clipFrom, clipTo;
bool doRebuild = false;
protected SerializedProperty spline;
public int editIndex
{
get { return _editIndex; }
set
{
if(value == 0)
{
Debug.LogError("Cannot set edit index to 0. 0 is reserved.");
return;
}
if (value < -1) value = -1;
_editIndex = value;
}
}
private int _editIndex = -1; //0 is reserved for editing clip values
protected GUIContent editButtonContent = new GUIContent("Edit", "Enable edit mode in scene view");
protected virtual void HeaderGUI()
{
SplineUser user = (SplineUser)target;
bool isClosed = true;
bool loopSamples = true;
for (int i = 0; i < users.Length; i++)
{
if (users[i].spline == null) isClosed = false;
else if (!users[i].spline.isClosed) isClosed = false;
else if (!users[i].loopSamples) loopSamples = false;
}
Undo.RecordObject(user, "Inspector Change");
SplineComputer lastSpline = (SplineComputer)spline.objectReferenceValue;
EditorGUILayout.PropertyField(spline);
SplineComputer newSpline = (SplineComputer)spline.objectReferenceValue;
if (lastSpline != (SplineComputer)spline.objectReferenceValue)
{
for (int i = 0; i < users.Length; i++)
{
if (lastSpline != null) lastSpline.Unsubscribe(users[i]);
if (newSpline != null) newSpline.Subscribe(users[i]);
}
user.Rebuild();
}
//if (GUI.changed) serializedObject.ApplyModifiedProperties();
if (user.spline == null) EditorGUILayout.HelpBox("No SplineComputer is referenced. Link a SplineComputer to make this SplineUser work.", MessageType.Error);
if (showClip)
{
float clipFrom = 0f, clipTo = 1f;
clipFrom = this.clipFrom.floatValue;
clipTo = this.clipTo.floatValue;
EditorGUI.BeginChangeCheck();
if (isClosed && loopSamples)
{
EditorGUILayout.BeginHorizontal();
if (EditButton(_editIndex == 0))
{
if (_editIndex == 0) _editIndex = -1;
else _editIndex = 0;
}
EditorGUILayout.BeginVertical();
clipFrom = EditorGUILayout.Slider("Clip From", clipFrom, 0f, 1f);
clipTo = EditorGUILayout.Slider("Clip To", clipTo, 0f, 1f);
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
}
else
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginHorizontal();
if (EditButton(_editIndex == 0))
{
if (_editIndex == 0) _editIndex = -1;
else _editIndex = 0;
}
EditorGUIUtility.labelWidth = 80f;
EditorGUILayout.MinMaxSlider(new GUIContent("Clip Range:"), ref clipFrom, ref clipTo, 0f, 1f);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(30));
clipFrom = EditorGUILayout.FloatField(clipFrom);
clipTo = EditorGUILayout.FloatField(clipTo);
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndHorizontal();
}
if (EditorGUI.EndChangeCheck())
{
this.clipFrom.floatValue = clipFrom;
this.clipTo.floatValue = clipTo;
}
SplineComputerEditor.hold = _editIndex >= 0;
if (isClosed) EditorGUILayout.PropertyField(this.loopSamples, new GUIContent("Loop Samples"));
if (!this.loopSamples.boolValue || !isClosed)
{
if (this.clipFrom.floatValue > this.clipTo.floatValue)
{
float temp = this.clipTo.floatValue;
this.clipTo.floatValue = this.clipFrom.floatValue;
this.clipFrom.floatValue = temp;
}
}
}
settings = EditorGUILayout.Foldout(settings, "Settings");
if (settings)
{
EditorGUI.indentLevel++;
if (showUpdateMethod) EditorGUILayout.PropertyField(updateMethod);
EditorGUILayout.PropertyField(autoUpdate, new GUIContent("Auto Rebuild"));
if (showMultithreading) EditorGUILayout.PropertyField(multithreaded);
EditorGUILayout.PropertyField(buildOnAwake);
EditorGUILayout.PropertyField(buildOnEnable);
EditorGUI.indentLevel--;
}
}
protected virtual void BodyGUI()
{
EditorGUILayout.Space();
}
protected virtual void FooterGUI()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Sample Modifiers", EditorStyles.boldLabel);
if (users.Length == 1)
{
if (offsetModifierEditor != null) offsetModifierEditor.DrawInspector();
if (rotationModifierEditor != null) rotationModifierEditor.DrawInspector();
if (colorModifierEditor != null) colorModifierEditor.DrawInspector();
if (sizeModifierEditor != null) sizeModifierEditor.DrawInspector();
}
else EditorGUILayout.LabelField("Modifiers not available when multiple Spline Users are selected.", EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
}
protected virtual void OnSceneGUI()
{
if (doRebuild) DoRebuild();
SplineUser user = (SplineUser)target;
if (user == null) return;
if (user.spline != null)
{
SplineComputer rootComputer = user.GetComponent<SplineComputer>();
List<SplineComputer> allComputers = user.spline.GetConnectedComputers();
for (int i = 0; i < allComputers.Count; i++)
{
if (allComputers[i] == rootComputer && _editIndex == -1) continue;
if (allComputers[i].alwaysDraw) continue;
SplineDrawer.DrawSplineComputer(allComputers[i], 0.0, 1.0, 0.4f);
}
SplineDrawer.DrawSplineComputer(user.spline);
}
if (_editIndex == 0) SceneClipEdit();
if (offsetModifierEditor != null) offsetModifierEditor.DrawScene();
if (rotationModifierEditor != null) rotationModifierEditor.DrawScene();
if (colorModifierEditor != null) colorModifierEditor.DrawScene();
if (sizeModifierEditor != null) sizeModifierEditor.DrawScene();
}
void SceneClipEdit()
{
if (users.Length > 1) return;
SplineUser user = (SplineUser)target;
if (user.spline == null) return;
Color col = user.spline.editorPathColor;
Undo.RecordObject(user, "Edit Clip Range");
double val = user.clipFrom;
SplineEditorHandles.Slider(user.spline, ref val, col, "Clip From", SplineEditorHandles.SplineSliderGizmo.ForwardTriangle);
if (val != user.clipFrom) user.clipFrom = val;
val = user.clipTo;
SplineEditorHandles.Slider(user.spline, ref val, col, "Clip To", SplineEditorHandles.SplineSliderGizmo.BackwardTriangle);
if (val != user.clipTo) user.clipTo = val;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (doRebuild) DoRebuild();
serializedUsers = new SerializedObject(users);
updateMethod = serializedUsers.FindProperty("updateMethod");
buildOnAwake = serializedUsers.FindProperty("buildOnAwake");
buildOnEnable = serializedUsers.FindProperty("buildOnEnable");
multithreaded = serializedUsers.FindProperty("multithreaded");
autoUpdate = serializedUsers.FindProperty("_autoUpdate");
SerializedProperty sampleCollection = serializedUsers.FindProperty("sampleCollection");
loopSamples = sampleCollection.FindPropertyRelative("loopSamples");
clipFrom = sampleCollection.FindPropertyRelative("clipFrom");
clipTo = sampleCollection.FindPropertyRelative("clipTo"); ;
spline = serializedUsers.FindProperty("_spline");
EditorGUI.BeginChangeCheck();
HeaderGUI();
if (EditorGUI.EndChangeCheck())
{
serializedUsers.ApplyModifiedProperties();
for (int i = 0; i < users.Length; i++)
{
EditorUtility.SetDirty(users[i]);
users[i].Rebuild();
}
}
EditorGUI.BeginChangeCheck();
BodyGUI();
if (EditorGUI.EndChangeCheck())
{
serializedUsers.ApplyModifiedProperties();
for (int i = 0; i < users.Length; i++)
{
try
{
EditorUtility.SetDirty(users[i]);
users[i].Rebuild();
} catch (System.Exception ex)
{
Debug.Log(ex.Message);
}
}
}
EditorGUI.BeginChangeCheck();
FooterGUI();
if (EditorGUI.EndChangeCheck())
{
serializedUsers.ApplyModifiedProperties();
for (int i = 0; i < users.Length; i++)
{
EditorUtility.SetDirty(users[i]);
users[i].Rebuild();
}
}
}
void DoRebuild()
{
for (int i = 0; i < users.Length; i++) users[i].Rebuild();
doRebuild = false;
}
protected virtual void OnDestroy()
{
SplineUser user = (SplineUser)target;
if (Application.isEditor && !Application.isPlaying)
{
if (user == null) OnDelete(); //The object or the component is being deleted
else if (user.spline != null) user.Rebuild();
}
SplineComputerEditor.hold = false;
}
protected virtual void OnDelete()
{
}
protected virtual void Awake()
{
}
protected virtual void OnEnable()
{
SplineUser user = (SplineUser)target;
user.EditorAwake();
rotationModifierEditor = new RotationModifierEditor(user, this, user.rotationModifier);
offsetModifierEditor = new OffsetModifierEditor(user, this, user.offsetModifier);
colorModifierEditor = new ColorModifierEditor(user, this, user.colorModifier);
sizeModifierEditor = new SizeModifierEditor(user, this, user.sizeModifier);
users = new SplineUser[targets.Length];
for (int i = 0; i < users.Length; i++) users[i] = (SplineUser)targets[i];
Undo.undoRedoPerformed += OnUndoRedo;
}
protected virtual void OnDisable()
{
Undo.undoRedoPerformed += OnUndoRedo;
}
protected virtual void OnUndoRedo()
{
doRebuild = true;
}
public bool EditButton(bool selected)
{
float width = 40f;
editButtonContent.image = ImageDB.GetImage("edit_cursor.png", "Splines/Editor/Icons");
if (editButtonContent.image != null)
{
editButtonContent.text = "";
width = 25f;
}
if (SplineEditorGUI.EditorLayoutSelectableButton(editButtonContent, true, selected, GUILayout.Width(width)))
{
SceneView.RepaintAll();
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0895930635ab45148bfcd359f0f2ce19
timeCreated: 1451752176
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class SplineUserSubEditor
{
protected string title = "";
protected SplineUser user;
protected SplineUserEditor editor = null;
public bool isOpen
{
get { return foldout; }
}
bool foldout = false;
public SplineUserSubEditor(SplineUser user, SplineUserEditor editor)
{
this.editor = editor;
this.user = user;
}
public virtual void DrawInspector()
{
foldout = EditorGUILayout.Foldout(foldout, title);
}
public virtual void DrawScene()
{
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 072866cc5f8b8e94d9ed416f33661a42
timeCreated: 1484136844
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,69 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(SurfaceGenerator))]
[CanEditMultipleObjects]
public class SurfaceGeneratorEditor : MeshGenEditor
{
protected override void OnSceneGUI()
{
base.OnSceneGUI();
SurfaceGenerator user = (SurfaceGenerator)target;
if(user.extrudeSpline != null)
SplineDrawer.DrawSplineComputer(user.extrudeSpline, 0.0, 1.0, 0.5f);
}
protected override void BodyGUI()
{
showSize = false;
showRotation = false;
base.BodyGUI();
SurfaceGenerator user = (SurfaceGenerator)target;
serializedObject.Update();
SerializedProperty expand = serializedObject.FindProperty("_expand");
SerializedProperty extrude = serializedObject.FindProperty("_extrude");
SerializedProperty extrudeSpline = serializedObject.FindProperty("_extrudeSpline");
EditorGUI.BeginChangeCheck();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Shape", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(expand, new GUIContent("Expand"));
if (extrudeSpline.objectReferenceValue == null) EditorGUILayout.PropertyField(extrude, new GUIContent("Extrude"));
EditorGUILayout.PropertyField(extrudeSpline, new GUIContent("Extrude Path"));
if (extrudeSpline.objectReferenceValue != null)
{
SerializedProperty extrudeClipFrom = serializedObject.FindProperty("_extrudeFrom");
SerializedProperty extrudeClipTo = serializedObject.FindProperty("_extrudeTo");
float clipFrom = extrudeClipFrom.floatValue;
float clipTo = extrudeClipTo.floatValue;
EditorGUILayout.MinMaxSlider(new GUIContent("Extrude Clip Range:"), ref clipFrom, ref clipTo, 0f, 1f);
extrudeClipFrom.floatValue = clipFrom;
extrudeClipTo.floatValue = clipTo;
}
if (EditorGUI.EndChangeCheck())
{
for (int i = 0; i < users.Length; i++)
{
users[i].Rebuild();
}
serializedObject.ApplyModifiedProperties();
}
UVControls(user);
if (extrude.floatValue != 0f || extrudeSpline.objectReferenceValue != null)
{
SerializedProperty sideUvOffset = serializedObject.FindProperty("_sideUvOffset");
SerializedProperty sideUvScale = serializedObject.FindProperty("_sideUvScale");
SerializedProperty uniformUvs = serializedObject.FindProperty("_uniformUvs");
EditorGUILayout.PropertyField(sideUvOffset, new GUIContent("Side UV Offset"));
EditorGUILayout.PropertyField(sideUvScale, new GUIContent("Side UV Scale"));
EditorGUILayout.PropertyField(uniformUvs, new GUIContent("Unform UVs"));
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 09f3755defd393e4d862eb6298748196
timeCreated: 1456760142
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(TubeGenerator))]
[CanEditMultipleObjects]
public class TubeGeneratorEditor : MeshGenEditor
{
protected override void BodyGUI()
{
base.BodyGUI();
TubeGenerator tubeGenerator = (TubeGenerator)target;
serializedObject.Update();
SerializedProperty sides = serializedObject.FindProperty("_sides");
SerializedProperty capMode = serializedObject.FindProperty("_capMode");
SerializedProperty revolve = serializedObject.FindProperty("_revolve");
EditorGUI.BeginChangeCheck();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Shape", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(sides, new GUIContent("Sides"));
EditorGUILayout.PropertyField(capMode, new GUIContent("Cap"));
EditorGUILayout.PropertyField(revolve, new GUIContent("Revolve"));
if(capMode.intValue == (int)TubeGenerator.CapMethod.Round)
{
SerializedProperty latitude = serializedObject.FindProperty("_roundCapLatitude");
EditorGUILayout.PropertyField(latitude, new GUIContent("Cap Latitude"));
}
if (sides.intValue < 3) sides.intValue = 3;
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
UVControls(tubeGenerator);
if(capMode.intValue != 0)
{
SerializedProperty capUVScale = serializedObject.FindProperty("_capUVScale");
EditorGUILayout.PropertyField(capUVScale, new GUIContent("Cap UV Scale"));
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 79c4f01065705344ab89e0e3534c2e64
timeCreated: 1454003144
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(WaveformGenerator), true)]
[CanEditMultipleObjects]
public class WaveGeneratorEditor : MeshGenEditor
{
protected override void BodyGUI()
{
showSize = false;
showRotation = false;
base.BodyGUI();
WaveformGenerator user = (WaveformGenerator)target;
serializedObject.Update();
SerializedProperty axis = serializedObject.FindProperty("_axis");
SerializedProperty slices = serializedObject.FindProperty("_slices");
SerializedProperty symmetry = serializedObject.FindProperty("_symmetry");
SerializedProperty uvWrapMode = serializedObject.FindProperty("_uvWrapMode");
SerializedProperty uvOffset = serializedObject.FindProperty("_uvOffset");
SerializedProperty uvScale = serializedObject.FindProperty("_uvScale");
EditorGUI.BeginChangeCheck();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Axis", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(axis, new GUIContent("Axis"));
EditorGUILayout.Space();
EditorGUILayout.LabelField("Shape", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(slices, new GUIContent("Slices"));
if (slices.intValue < 1) slices.intValue = 1;
EditorGUILayout.PropertyField(symmetry, new GUIContent("Use Symmetry"));
EditorGUILayout.Space();
EditorGUILayout.LabelField("Uv Coordinates", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(uvWrapMode, new GUIContent("Wrap Mode"));
EditorGUILayout.PropertyField(uvOffset, new GUIContent("UV Offset"));
EditorGUILayout.PropertyField(uvScale, new GUIContent("UV Scale"));
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 988e0370e4dbf5a4e82a4b537aaf96e4
timeCreated: 1456910867
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 7417baf45051d9e4b974d45e69811efd
timeCreated: 1523272668
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: b4b069b14ffccf146b40c7aae7c4818f
timeCreated: 1497441467
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 09a5be8542799294ab31f6b97c88471b
timeCreated: 1459172591
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 71feaa5f5395f3640a94b1ba649bc941
timeCreated: 1472464036
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 809d29b9ca1b74947aca02225d2ec233
timeCreated: 1497441486
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: c78150f2237d29247b0f01c770f06979
timeCreated: 1457811264
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 71dadc4e471c37945ba62bf068cf1468
timeCreated: 1457811264
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 5fad78752ebca1541a3321d08d1cd041
timeCreated: 1497441504
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,117 @@
fileFormatVersion: 2
guid: 3c4c2926f013fcf498c19b14b90050c5
timeCreated: 1484825827
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 14d9ee407d8622249bb457e71b4400d1
timeCreated: 1457811264
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 832e3a79eca687941a031a046045c8cc
timeCreated: 1457811264
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: 5a7f65ad6116cff448644595264d0ae4
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 7445cc27708caa049a4b4ef14d9a5eef
timeCreated: 1467623533
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 9dbfb387ba852e34299827107f06d528
timeCreated: 1457811264
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 02f78a9ec76d40f49bfac78c64a754d1
timeCreated: 1457811264
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 9bbaac8eb7021d44b9864113856c00fa
timeCreated: 1457811264
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: cf90d545cbe8b2a4197b471709a5e579
timeCreated: 1457811264
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: b4e3f1d75c0b07f4890e7acab6fd1a15
timeCreated: 1457811264
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: 608905f522fa0644398876606b832e68
timeCreated: 1497441532
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
using UnityEngine;
using System.Collections;
using System.Reflection;
using UnityEngine.Events;
namespace Dreamteck.Splines
{
[AddComponentMenu("Dreamteck/Splines/Length Calculator")]
public class LengthCalculator : SplineUser
{
[System.Serializable]
public class LengthEvent
{
public bool enabled = true;
public float targetLength = 0f;
public UnityEvent onChange = new UnityEvent();
public enum Type { Growing, Shrinking, Both}
public Type type = Type.Both;
public LengthEvent()
{
}
public LengthEvent(Type t)
{
type = t;
}
public void Check(float fromLength, float toLength)
{
if (!enabled) return;
bool condition = false;
switch (type)
{
case Type.Growing: condition = toLength >= targetLength && fromLength < targetLength; break;
case Type.Shrinking: condition = toLength <= targetLength && fromLength > targetLength; break;
case Type.Both: condition = toLength >= targetLength && fromLength < targetLength || toLength <= targetLength && fromLength > targetLength; break;
}
if (condition) onChange.Invoke();
}
}
[HideInInspector]
public LengthEvent[] lengthEvents = new LengthEvent[0];
[HideInInspector]
public float idealLength = 1f;
private float _length = 0f;
private float lastLength = 0f;
public float length
{
get {
return _length;
}
}
protected override void Awake()
{
base.Awake();
_length = CalculateLength();
lastLength = _length;
for (int i = 0; i < lengthEvents.Length; i++)
{
if (lengthEvents[i].targetLength == _length) lengthEvents[i].onChange.Invoke();
}
}
protected override void Build()
{
base.Build();
_length = CalculateLength();
if (lastLength != _length)
{
for (int i = 0; i < lengthEvents.Length; i++)
{
lengthEvents[i].Check(lastLength, _length);
}
lastLength = _length;
}
}
private void AddEvent(LengthEvent lengthEvent)
{
LengthEvent[] newEvents = new LengthEvent[lengthEvents.Length + 1];
lengthEvents.CopyTo(newEvents, 0);
newEvents[newEvents.Length - 1] = lengthEvent;
lengthEvents = newEvents;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 995701723b428a94c9305a2abf319ad6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: b4b069b14ffccf146b40c7aae7c4818f, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,440 @@
using UnityEngine;
using System.Collections;
using System.Threading;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Dreamteck.Splines
{
public class MeshGenerator : SplineUser
{
public float size
{
get { return _size; }
set
{
if (value != _size)
{
_size = value;
Rebuild();
} else _size = value;
}
}
public Color color
{
get { return _color; }
set
{
if (value != _color)
{
_color = value;
Rebuild();
}
}
}
public Vector3 offset
{
get { return _offset; }
set
{
if (value != _offset)
{
_offset = value;
Rebuild();
}
}
}
public NormalMethod normalMethod
{
get { return _normalMethod; }
set
{
if (value != _normalMethod)
{
_normalMethod = value;
Rebuild();
}
}
}
public bool calculateTangents
{
get { return _calculateTangents; }
set
{
if (value != _calculateTangents)
{
_calculateTangents = value;
Rebuild();
}
}
}
public float rotation
{
get { return _rotation; }
set
{
if (value != _rotation)
{
_rotation = value;
Rebuild();
}
}
}
public bool flipFaces
{
get { return _flipFaces; }
set
{
if (value != _flipFaces)
{
_flipFaces = value;
Rebuild();
}
}
}
public bool doubleSided
{
get { return _doubleSided; }
set
{
if (value != _doubleSided)
{
_doubleSided = value;
Rebuild();
}
}
}
public UVMode uvMode
{
get { return _uvMode; }
set
{
if (value != _uvMode)
{
_uvMode = value;
Rebuild();
}
}
}
public Vector2 uvScale
{
get { return _uvScale; }
set
{
if (value != _uvScale)
{
_uvScale = value;
Rebuild();
}
}
}
public Vector2 uvOffset
{
get { return _uvOffset; }
set
{
if (value != _uvOffset)
{
_uvOffset = value;
Rebuild();
}
}
}
public float uvRotation
{
get { return _uvRotation; }
set
{
if (value != _uvRotation)
{
_uvRotation = value;
Rebuild();
}
}
}
public bool baked
{
get
{
return _baked;
}
}
public enum UVMode { Clip, UniformClip, Clamp, UniformClamp }
public enum NormalMethod { Recalculate, SplineNormals }
[SerializeField]
[HideInInspector]
private bool _baked = false;
[SerializeField]
[HideInInspector]
private float _size = 1f;
[SerializeField]
[HideInInspector]
private Color _color = Color.white;
[SerializeField]
[HideInInspector]
private Vector3 _offset = Vector3.zero;
[SerializeField]
[HideInInspector]
private NormalMethod _normalMethod = NormalMethod.SplineNormals;
[SerializeField]
[HideInInspector]
private bool _calculateTangents = true;
[SerializeField]
[HideInInspector]
[Range(-360f, 360f)]
private float _rotation = 0f;
[SerializeField]
[HideInInspector]
private bool _flipFaces = false;
[SerializeField]
[HideInInspector]
private bool _doubleSided = false;
[SerializeField]
[HideInInspector]
private UVMode _uvMode = UVMode.Clip;
[SerializeField]
[HideInInspector]
private Vector2 _uvScale = Vector2.one;
[SerializeField]
[HideInInspector]
private Vector2 _uvOffset = Vector2.zero;
[SerializeField]
[HideInInspector]
private float _uvRotation = 0f;
[SerializeField]
[HideInInspector]
protected MeshCollider meshCollider;
[SerializeField]
[HideInInspector]
protected MeshFilter filter;
[SerializeField]
[HideInInspector]
protected MeshRenderer meshRenderer;
[SerializeField]
[HideInInspector]
protected TS_Mesh tsMesh = new TS_Mesh();
[SerializeField]
[HideInInspector]
protected Mesh mesh;
[HideInInspector]
public float colliderUpdateRate = 0.2f;
protected bool updateCollider = false;
protected float lastUpdateTime = 0f;
private float vDist = 0f;
protected static Vector2 uvs = Vector2.zero;
#if UNITY_EDITOR
public override void EditorAwake()
{
base.EditorAwake();
CloneMesh();
Awake();
}
public void Bake(bool makeStatic, bool lightmapUV)
{
if (mesh == null) return;
gameObject.isStatic = false;
UnityEditor.MeshUtility.Optimize(mesh);
if(spline != null) spline.Unsubscribe(this);
filter = GetComponent<MeshFilter>();
meshRenderer = GetComponent<MeshRenderer>();
filter.hideFlags = meshRenderer.hideFlags = HideFlags.None;
filter.sharedMesh = mesh;
if (lightmapUV) Unwrapping.GenerateSecondaryUVSet(filter.sharedMesh);
if (makeStatic) gameObject.isStatic = true;
_baked = true;
}
public void Unbake()
{
gameObject.isStatic = false;
_baked = false;
spline.Subscribe(this);
Rebuild();
}
#endif
protected override void Awake()
{
if (mesh == null) mesh = new Mesh();
base.Awake();
filter = GetComponent<MeshFilter>();
meshRenderer = GetComponent<MeshRenderer>();
meshCollider = GetComponent<MeshCollider>();
}
protected override void Reset()
{
base.Reset();
#if UNITY_EDITOR
MeshRenderer rend = GetComponent<MeshRenderer>();
bool materialFound = false;
for (int i = 0; i < rend.sharedMaterials.Length; i++)
{
if (rend.sharedMaterials[i] != null)
{
materialFound = true;
break;
}
}
if (!materialFound) rend.sharedMaterial = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Diffuse.mat");
#endif
}
public void CloneMesh()
{
if (tsMesh != null) tsMesh = TS_Mesh.Copy(tsMesh);
else tsMesh = new TS_Mesh();
if (mesh != null) mesh = (Mesh)Instantiate(mesh);
else mesh = new Mesh();
}
public override void Rebuild()
{
if (_baked) return;
base.Rebuild();
}
public override void RebuildImmediate()
{
if (_baked) return;
base.RebuildImmediate();
}
protected override void OnEnable()
{
base.OnEnable();
}
protected override void OnDisable()
{
base.OnDisable();
}
protected override void OnDestroy()
{
base.OnDestroy();
MeshFilter filter = GetComponent<MeshFilter>();
MeshRenderer rend = GetComponent<MeshRenderer>();
if (filter != null) filter.hideFlags = HideFlags.None;
if (rend != null) rend.hideFlags = HideFlags.None;
}
public void UpdateCollider()
{
meshCollider = GetComponent<MeshCollider>();
if (meshCollider == null) meshCollider = gameObject.AddComponent<MeshCollider>();
meshCollider.sharedMesh = filter.sharedMesh;
}
protected override void LateRun()
{
if (_baked) return;
base.LateRun();
if (updateCollider)
{
if (meshCollider != null)
{
if (Time.time - lastUpdateTime >= colliderUpdateRate)
{
lastUpdateTime = Time.time;
updateCollider = false;
meshCollider.sharedMesh = filter.sharedMesh;
}
}
}
}
protected override void Build()
{
base.Build();
if (sampleCount > 0) BuildMesh();
}
protected override void PostBuild()
{
base.PostBuild();
WriteMesh();
}
protected virtual void BuildMesh()
{
//Logic for mesh generation, automatically called in the Build method
}
protected virtual void WriteMesh()
{
MeshUtility.InverseTransformMesh(tsMesh, trs);
if (_doubleSided) MeshUtility.MakeDoublesidedHalf(tsMesh);
else if(_flipFaces) MeshUtility.FlipFaces(tsMesh);
if (_calculateTangents) MeshUtility.CalculateTangents(tsMesh);
if(tsMesh.vertexCount > 64000) Debug.LogError("WARNING: The generated mesh for " + name + " has " + tsMesh.vertexCount + " vertices. The maximum vertex count for meshes in Unity is 64000. The mesh will not be updated.");
tsMesh.WriteMesh(ref mesh);
if (_normalMethod == 0) mesh.RecalculateNormals();
if (filter != null) filter.sharedMesh = mesh;
updateCollider = true;
}
protected virtual void AllocateMesh(int vertexCount, int trisCount)
{
if (_doubleSided)
{
vertexCount *= 2;
trisCount *= 2;
}
if (tsMesh.vertexCount != vertexCount)
{
tsMesh.vertices = new Vector3[vertexCount];
tsMesh.normals = new Vector3[vertexCount];
tsMesh.tangents = new Vector4[vertexCount];
tsMesh.colors = new Color[vertexCount];
tsMesh.uv = new Vector2[vertexCount];
}
if (tsMesh.triangles.Length != trisCount) tsMesh.triangles = new int[trisCount];
}
protected void ResetUVDistance()
{
vDist = 0f;
if (uvMode == UVMode.UniformClip) vDist = spline.CalculateLength(0.0, GetSampleRaw(0).percent);
}
protected void AddUVDistance(int sampleIndex)
{
if (sampleIndex == 0) return;
vDist += Vector3.Distance(GetSampleRaw(sampleIndex).position, GetSampleRaw(sampleIndex - 1).position);
}
protected void CalculateUVs(double percent, float u)
{
uvs.x = u * _uvScale.x - _uvOffset.x;
switch (uvMode)
{
case UVMode.Clip: uvs.y = (float)percent * _uvScale.y - _uvOffset.y; break;
case UVMode.Clamp: uvs.y = (float)DMath.InverseLerp(clipFrom, clipTo, percent) * _uvScale.y - _uvOffset.y; break;
case UVMode.UniformClamp: uvs.y = vDist * _uvScale.y / (float)span - _uvOffset.y; break;
default: uvs.y = vDist * _uvScale.y - _uvOffset.y; break;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 49c9228d9868e1747b4763bc4cb1d86f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 9bbaac8eb7021d44b9864113856c00fa, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,372 @@
using UnityEngine;
using System.Collections;
namespace Dreamteck.Splines
{
[ExecuteInEditMode]
public class Node : MonoBehaviour
{
[System.Serializable]
public class Connection
{
public SplineComputer spline
{
get { return _computer; }
}
public int pointIndex
{
get { return _pointIndex; }
}
public bool invertTangents = false;
[SerializeField]
private int _pointIndex = 0;
[SerializeField]
private SplineComputer _computer = null;
[SerializeField]
[HideInInspector]
internal SplinePoint point;
internal bool isValid
{
get
{
if (_computer == null) return false;
if (_pointIndex >= _computer.pointCount) return false;
return true;
}
}
internal Connection(SplineComputer comp, int index, SplinePoint inputPoint)
{
_pointIndex = index;
_computer = comp;
point = inputPoint;
}
}
public enum Type { Smooth, Free }
[HideInInspector]
public Type type = Type.Smooth;
public bool transformNormals
{
get { return _transformNormals; }
set
{
if (value != _transformNormals)
{
_transformNormals = value;
UpdatePoints();
}
}
}
public bool transformSize
{
get { return _transformSize; }
set
{
if (value != _transformSize)
{
_transformSize = value;
UpdatePoints();
}
}
}
public bool transformTangents
{
get { return _transformTangents; }
set
{
if (value != _transformTangents)
{
_transformTangents = value;
UpdatePoints();
}
}
}
[SerializeField]
[HideInInspector]
protected Connection[] connections = new Connection[0];
[SerializeField]
[HideInInspector]
private bool _transformSize = true;
[SerializeField]
[HideInInspector]
private bool _transformNormals = true;
[SerializeField]
[HideInInspector]
private bool _transformTangents = true;
private Vector3 lastPosition, lastScale;
private Quaternion lastRotation;
Transform trs;
private void Awake()
{
trs = transform;
SampleTransform();
}
void LateUpdate()
{
Run();
}
void Update()
{
Run();
}
bool TransformChanged()
{
#if UNITY_EDITOR
if(trs == null) return lastPosition != transform.position || lastRotation != transform.rotation || lastScale != transform.lossyScale;
#endif
return lastPosition != trs.position || lastRotation != trs.rotation || lastScale != trs.lossyScale;
}
void SampleTransform() {
#if UNITY_EDITOR
lastPosition = transform.position;
lastScale = transform.lossyScale;
lastRotation = transform.rotation;
return;
#else
lastPosition = trs.position;
lastScale = trs.lossyScale;
lastRotation = trs.rotation;
#endif
}
private void Run()
{
if (TransformChanged())
{
UpdateConnectedComputers();
SampleTransform();
}
}
public SplinePoint GetPoint(int connectionIndex, bool swapTangents)
{
SplinePoint point = PointToWorld(connections[connectionIndex].point);
if (connections[connectionIndex].invertTangents && swapTangents)
{
Vector3 tempTan = point.tangent;
point.tangent = point.tangent2;
point.tangent2 = tempTan;
}
return point;
}
public void SetPoint(int connectionIndex, SplinePoint worldPoint, bool swappedTangents)
{
Connection connection = connections[connectionIndex];
connection.point = PointToLocal(worldPoint);
if (connection.invertTangents && swappedTangents)
{
Vector3 tempTan = connection.point.tangent;
connection.point.tangent = connection.point.tangent2;
connection.point.tangent2 = tempTan;
}
if (type == Type.Smooth)
{
if (connection.point.type == SplinePoint.Type.SmoothFree)
{
for (int i = 0; i < connections.Length; i++)
{
if (i == connectionIndex) continue;
Vector3 tanDir = (connection.point.tangent - connection.point.position).normalized;
if (tanDir == Vector3.zero) tanDir = -(connection.point.tangent2 - connection.point.position).normalized;
float tan1Length = (connections[i].point.tangent - connections[i].point.position).magnitude;
float tan2Length = (connections[i].point.tangent2 - connections[i].point.position).magnitude;
connections[i].point = connection.point;
connections[i].point.tangent = connections[i].point.position + tanDir * tan1Length;
connections[i].point.tangent2 = connections[i].point.position - tanDir * tan2Length;
}
}
else
{
for (int i = 0; i < connections.Length; i++)
{
if (i == connectionIndex) continue;
connections[i].point = connection.point;
}
}
}
}
void OnDestroy()
{
ClearConnections();
}
public void ClearConnections()
{
for (int i = connections.Length-1; i >= 0; i--)
{
if (connections[i].spline != null) connections[i].spline.DisconnectNode(connections[i].pointIndex);
}
connections = new Connection[0];
}
public void UpdateConnectedComputers(SplineComputer excludeComputer = null)
{
for (int i = connections.Length - 1; i >= 0; i--)
{
if (!connections[i].isValid)
{
RemoveConnection(i);
continue;
}
if (connections[i].spline == excludeComputer) continue;
if (type == Type.Smooth && i != 0) SetPoint(i, GetPoint(0, false), false);
SplinePoint point = GetPoint(i, true);
if (!transformNormals) point.normal = connections[i].spline.GetPointNormal(connections[i].pointIndex);
if (!transformTangents)
{
point.tangent = connections[i].spline.GetPointTangent(connections[i].pointIndex);
point.tangent2 = connections[i].spline.GetPointTangent2(connections[i].pointIndex);
}
if(!transformSize) point.size = connections[i].spline.GetPointSize(connections[i].pointIndex);
connections[i].spline.SetPoint(connections[i].pointIndex, point);
}
}
public void UpdatePoint(SplineComputer computer, int pointIndex, SplinePoint point, bool updatePosition = true)
{
#if UNITY_EDITOR
if (!Application.isPlaying) transform.position = point.position;
else trs.position = point.position;
#else
trs.position = point.position;
#endif
for (int i = 0; i < connections.Length; i++)
{
if (connections[i].spline == computer && connections[i].pointIndex == pointIndex) SetPoint(i, point, true);
}
}
private void UpdatePoints()
{
for (int i = connections.Length - 1; i >= 0; i--)
{
if (!connections[i].isValid)
{
RemoveConnection(i);
continue;
}
SplinePoint point = connections[i].spline.GetPoint(connections[i].pointIndex);
point.SetPosition(transform.position);
SetPoint(i, point, true);
}
}
#if UNITY_EDITOR
//Use this to maintain the connections between computers in the editor
public void EditorMaintainConnections()
{
RemoveInvalidConnections();
}
#endif
//Remove invalid connections
protected void RemoveInvalidConnections()
{
for (int i = connections.Length - 1; i >= 0; i--)
{
if (connections[i] == null || !connections[i].isValid) RemoveConnection(i);
}
}
public virtual void AddConnection(SplineComputer computer, int pointIndex)
{
RemoveInvalidConnections();
Node connected = computer.GetNode(pointIndex);
if (connected != null)
{
Debug.LogError(computer.name + " is already connected to node " + connected.name + " at point " + pointIndex);
return;
}
SplinePoint point = computer.GetPoint(pointIndex);
point.SetPosition(transform.position);
ArrayUtility.Add(ref connections, new Connection(computer, pointIndex, PointToLocal(point)));
if(connections.Length == 1) SetPoint(connections.Length - 1, point, true);
UpdateConnectedComputers();
}
protected SplinePoint PointToLocal(SplinePoint worldPoint)
{
worldPoint.position = Vector3.zero;
worldPoint.tangent = transform.InverseTransformPoint(worldPoint.tangent);
worldPoint.tangent2 = transform.InverseTransformPoint(worldPoint.tangent2);
worldPoint.normal = transform.InverseTransformDirection(worldPoint.normal);
worldPoint.size /= (transform.localScale.x + transform.localScale.y + transform.localScale.z)/ 3f;
return worldPoint;
}
protected SplinePoint PointToWorld(SplinePoint localPoint)
{
localPoint.position = transform.position;
localPoint.tangent = transform.TransformPoint(localPoint.tangent);
localPoint.tangent2 = transform.TransformPoint(localPoint.tangent2);
localPoint.normal = transform.TransformDirection(localPoint.normal);
localPoint.size *= (transform.localScale.x + transform.localScale.y + transform.localScale.z) / 3f;
return localPoint;
}
public virtual void RemoveConnection(SplineComputer computer, int pointIndex)
{
int index = -1;
for (int i = 0; i < connections.Length; i++)
{
if (connections[i].pointIndex == pointIndex && connections[i].spline == computer)
{
index = i;
break;
}
}
if (index < 0) return;
RemoveConnection(index);
}
private void RemoveConnection(int index)
{
Connection[] newConnections = new Connection[connections.Length - 1];
SplineComputer computer = connections[index].spline;
int pointIndex = connections[index].pointIndex;
for (int i = 0; i < connections.Length; i++)
{
if (i < index) newConnections[i] = connections[i];
else if (i == index) continue;
else newConnections[i - 1] = connections[i];
}
connections = newConnections;
}
public virtual bool HasConnection(SplineComputer computer, int pointIndex)
{
for (int i = connections.Length - 1; i >= 0; i--)
{
if (!connections[i].isValid)
{
RemoveConnection(i);
continue;
}
if (connections[i].spline == computer && connections[i].pointIndex == pointIndex) return true;
}
return false;
}
public Connection[] GetConnections()
{
return connections;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a212c074803b6824cae48ffa7abb84cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: -50
icon: {fileID: 2800000, guid: 09a5be8542799294ab31f6b97c88471b, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,803 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace Dreamteck.Splines
{
[AddComponentMenu("Dreamteck/Splines/Object Bender")]
public class ObjectBender : SplineUser
{
public enum Axis { X, Y, Z }
public enum NormalMode { Spline, Auto, Custom }
public enum ForwardMode { Spline, Custom }
public bool bend
{
get { return _bend; }
set
{
if(_bend != value)
{
_bend = value;
if (value)
{
UpdateReferences();
Rebuild();
} else Revert();
}
}
}
[SerializeField]
[HideInInspector]
private bool _bend = false;
public Axis axis
{
get { return _axis; }
set
{
if (spline != null && value != _axis)
{
_axis = value;
UpdateReferences();
Rebuild();
}
else _axis = value;
}
}
public NormalMode upMode
{
get { return _normalMode; }
set
{
if (spline != null && value != _normalMode)
{
_normalMode = value;
Rebuild();
} else _normalMode = value;
}
}
public Vector3 customNormal
{
get { return _customNormal; }
set
{
if (spline != null && value != _customNormal)
{
_customNormal = value;
Rebuild();
}
else _customNormal = value;
}
}
public ForwardMode forwardMode
{
get { return _forwardMode; }
set
{
if (spline != null && value != _forwardMode)
{
_forwardMode = value;
Rebuild();
} else _forwardMode = value;
}
}
public Vector3 customForward
{
get { return _customForward; }
set
{
if (spline != null && value != _customForward)
{
_customForward = value;
Rebuild();
}
else _customForward = value;
}
}
[HideInInspector]
public BendProperty[] bendProperties = new BendProperty[0];
[SerializeField]
[HideInInspector]
private TS_Bounds bounds = null;
[SerializeField]
[HideInInspector]
private Axis _axis = Axis.Z;
[SerializeField]
[HideInInspector]
private NormalMode _normalMode = NormalMode.Auto;
[SerializeField]
[HideInInspector]
private ForwardMode _forwardMode = ForwardMode.Spline;
[SerializeField]
[HideInInspector]
[UnityEngine.Serialization.FormerlySerializedAs("_upVector")]
private Vector3 _customNormal = Vector3.up;
[SerializeField]
[HideInInspector]
private Vector3 _customForward = Vector3.forward;
Matrix4x4 normalMatrix = new Matrix4x4();
Quaternion bendRotation = Quaternion.identity;
private void GetTransformsRecursively(Transform current, ref List<Transform> transformList)
{
transformList.Add(current);
foreach (Transform child in current)
{
GetTransformsRecursively(child, ref transformList);
}
}
private void GetObjects()
{
List<Transform> found = new List<Transform>();
GetTransformsRecursively(transform, ref found);
BendProperty[] newProperties = new BendProperty[found.Count];
for (int i = 0; i < found.Count; i++)
{
CreateProperty(ref newProperties[i], found[i]);
}
bendProperties = newProperties;
}
public TS_Bounds GetBounds()
{
return new TS_Bounds(bounds.min, bounds.max, bounds.center);
}
#if UNITY_EDITOR
public void EditorGenerateLightmapUVs()
{
for (int i = 0; i < bendProperties.Length; i++)
{
if (bendProperties[i].bendMesh)
{
if (bendProperties[i].filter == null) continue;
if (bendProperties[i].filter.sharedMesh == null) continue;
EditorUtility.DisplayProgressBar("Generating Lightmap UVS", bendProperties[i].filter.sharedMesh.name, (float)i / (bendProperties.Length - 1));
Unwrapping.GenerateSecondaryUVSet(bendProperties[i].filter.sharedMesh);
}
}
EditorUtility.ClearProgressBar();
}
#endif
private void CreateProperty(ref BendProperty property, Transform t)
{
property = new BendProperty(t, t == trs); //Create a new bend property for each child
for (int i = 0; i < bendProperties.Length; i++)
{
//Search for properties that have the same trasform and copy their settings
if (bendProperties[i].transform.transform == t)
{
property.enabled = bendProperties[i].enabled;
property.applyRotation = bendProperties[i].applyRotation;
property.applyScale = bendProperties[i].applyScale;
property.bendMesh = bendProperties[i].bendMesh;
property.bendCollider = bendProperties[i].bendCollider;
property.generateLightmapUVs = bendProperties[i].generateLightmapUVs;
property.colliderUpdateRate = bendProperties[i].colliderUpdateRate;
break;
}
}
if (t.transform != trs)
{
property.originalPosition = trs.InverseTransformPoint(t.position);
property.originalRotation = Quaternion.Inverse(trs.rotation) * t.rotation;
}
}
private void CalculateBounds()
{
if (bounds == null) bounds = new TS_Bounds(Vector3.zero, Vector3.zero);
bounds.min = bounds.max = Vector3.zero;
for (int i = 0; i < bendProperties.Length; i++)
{
CalculatePropertyBounds(ref bendProperties[i]);
}
for (int i = 0; i < bendProperties.Length; i++)
{
CalculatePercents(bendProperties[i]);
}
}
private void CalculatePropertyBounds(ref BendProperty property)
{
if (property.transform.transform == trs)
{
if (0f < bounds.min.x) bounds.min.x = 0f;
if (0f < bounds.min.y) bounds.min.y = 0f;
if (0f < bounds.min.z) bounds.min.z = 0f;
if (0f > bounds.max.x) bounds.max.x = 0f;
if (0f > bounds.max.y) bounds.max.y = 0f;
if (0f > bounds.max.z) bounds.max.z = 0f;
}
else
{
if (property.originalPosition.x < bounds.min.x) bounds.min.x = property.originalPosition.x;
if (property.originalPosition.y < bounds.min.y) bounds.min.y = property.originalPosition.y;
if (property.originalPosition.z < bounds.min.z) bounds.min.z = property.originalPosition.z;
if (property.originalPosition.x > bounds.max.x) bounds.max.x = property.originalPosition.x;
if (property.originalPosition.y > bounds.max.y) bounds.max.y = property.originalPosition.y;
if (property.originalPosition.z > bounds.max.z) bounds.max.z = property.originalPosition.z;
}
if (property.editMesh != null)
{
for (int n = 0; n < property.editMesh.vertices.Length; n++)
{
Vector3 localPos = property.transform.TransformPoint(property.editMesh.vertices[n]);
localPos = trs.InverseTransformPoint(localPos);
if (localPos.x < bounds.min.x) bounds.min.x = localPos.x;
if (localPos.y < bounds.min.y) bounds.min.y = localPos.y;
if (localPos.z < bounds.min.z) bounds.min.z = localPos.z;
if (localPos.x > bounds.max.x) bounds.max.x = localPos.x;
if (localPos.y > bounds.max.y) bounds.max.y = localPos.y;
if (localPos.z > bounds.max.z) bounds.max.z = localPos.z;
}
}
if (property.editColliderMesh != null)
{
for (int n = 0; n < property.editColliderMesh.vertices.Length; n++)
{
Vector3 localPos = property.transform.TransformPoint(property.editColliderMesh.vertices[n]);
localPos = trs.InverseTransformPoint(localPos);
if (localPos.x < bounds.min.x) bounds.min.x = localPos.x;
if (localPos.y < bounds.min.y) bounds.min.y = localPos.y;
if (localPos.z < bounds.min.z) bounds.min.z = localPos.z;
if (localPos.x > bounds.max.x) bounds.max.x = localPos.x;
if (localPos.y > bounds.max.y) bounds.max.y = localPos.y;
if (localPos.z > bounds.max.z) bounds.max.z = localPos.z;
}
}
if (property.originalSpline != null)
{
for (int n = 0; n < property.originalSpline.points.Length; n++)
{
Vector3 localPos = trs.InverseTransformPoint(property.originalSpline.points[n].position);
if (localPos.x < bounds.min.x) bounds.min.x = localPos.x;
if (localPos.y < bounds.min.y) bounds.min.y = localPos.y;
if (localPos.z < bounds.min.z) bounds.min.z = localPos.z;
if (localPos.x > bounds.max.x) bounds.max.x = localPos.x;
if (localPos.y > bounds.max.y) bounds.max.y = localPos.y;
if (localPos.z > bounds.max.z) bounds.max.z = localPos.z;
}
}
bounds.CreateFromMinMax(bounds.min, bounds.max);
}
public void CalculatePercents(BendProperty property)
{
if (property.transform.transform != trs) property.positionPercent = GetPercentage(trs.InverseTransformPoint(property.transform.position));
else property.positionPercent = GetPercentage(Vector3.zero);
if (property.editMesh != null)
{
if (property.vertexPercents.Length != property.editMesh.vertexCount) property.vertexPercents = new Vector3[property.editMesh.vertexCount];
if (property.editColliderMesh != null)
{
if (property.colliderVertexPercents.Length != property.editMesh.vertexCount) property.colliderVertexPercents = new Vector3[property.editColliderMesh.vertexCount];
}
for (int i = 0; i < property.editMesh.vertexCount; i++)
{
Vector3 localVertex = property.transform.TransformPoint(property.editMesh.vertices[i]);
localVertex = trs.InverseTransformPoint(localVertex);
property.vertexPercents[i] = GetPercentage(localVertex);
}
if (property.editColliderMesh != null)
{
for (int i = 0; i < property.editColliderMesh.vertexCount; i++)
{
Vector3 localVertex = property.transform.TransformPoint(property.editColliderMesh.vertices[i]);
localVertex = trs.InverseTransformPoint(localVertex);
property.colliderVertexPercents[i] = GetPercentage(localVertex);
}
}
}
if (property.splineComputer != null)
{
SplinePoint[] points = property.splineComputer.GetPoints();
property.splinePointPercents = new Vector3[points.Length];
property.primaryTangentPercents = new Vector3[points.Length];
property.secondaryTangentPercents = new Vector3[points.Length];
for (int i = 0; i < points.Length; i++)
{
property.splinePointPercents[i] = GetPercentage(trs.InverseTransformPoint(points[i].position));
property.primaryTangentPercents[i] = GetPercentage(trs.InverseTransformPoint(points[i].tangent));
property.secondaryTangentPercents[i] = GetPercentage(trs.InverseTransformPoint(points[i].tangent2));
}
}
}
private void Revert()
{
for (int i = 0; i < bendProperties.Length; i++)
{
bendProperties[i].Revert();
}
}
public void UpdateReferences()
{
#if UNITY_EDITOR
#if !UNITY_2018_3_OR_NEWER
if (PrefabUtility.GetPrefabType(gameObject) == PrefabType.Prefab) return;
#endif
#endif
trs = transform;
if (_bend)
{
for (int i = 0; i < bendProperties.Length; i++) bendProperties[i].Revert();
}
GetObjects();
CalculateBounds();
if (_bend)
{
Bend();
for (int i = 0; i < bendProperties.Length; i++)
{
bendProperties[i].Apply(i > 0 || trs != spline.transform);
bendProperties[i].Update();
}
}
}
private void GetevalResult(Vector3 percentage)
{
switch (axis)
{
case Axis.X: Evaluate(percentage.x, evalResult); break;
case Axis.Y: Evaluate(percentage.y, evalResult); break;
case Axis.Z: Evaluate(percentage.z, evalResult); break;
}
switch (_normalMode)
{
case NormalMode.Auto: evalResult.up = Vector3.Cross(evalResult.forward, evalResult.right); break;
case NormalMode.Custom: evalResult.up = _customNormal; break;
}
if (_forwardMode == ForwardMode.Custom) evalResult.forward = customForward;
ModifySample(evalResult);
Vector3 right = evalResult.right;
Quaternion axisRotation = Quaternion.identity;
switch (axis)
{
case Axis.Z:
evalResult.position += right * Mathf.Lerp(bounds.min.x, bounds.max.x, percentage.x) * evalResult.size;
evalResult.position += evalResult.up * Mathf.Lerp(bounds.min.y, bounds.max.y, percentage.y) * evalResult.size;
break;
case Axis.X:
axisRotation = Quaternion.Euler(0f, -90f, 0f);
evalResult.position += right * Mathf.Lerp(bounds.max.z, bounds.min.z, percentage.z) * evalResult.size;
evalResult.position += evalResult.up * Mathf.Lerp(bounds.min.y, bounds.max.y, percentage.y) * evalResult.size;
break;
case Axis.Y:
axisRotation = Quaternion.Euler(90f, 0f, 0f);
evalResult.position += right * Mathf.Lerp(bounds.min.x, bounds.max.x, percentage.x) * evalResult.size;
evalResult.position += evalResult.up * Mathf.Lerp(bounds.min.z, bounds.max.z, percentage.z) * evalResult.size;
break;
}
bendRotation = evalResult.rotation * axisRotation;
normalMatrix = Matrix4x4.TRS(evalResult.position, bendRotation, Vector3.one * evalResult.size).inverse.transpose;
}
private Vector3 GetPercentage(Vector3 point)
{
point.x = Mathf.InverseLerp(bounds.min.x, bounds.max.x, point.x);
point.y = Mathf.InverseLerp(bounds.min.y, bounds.max.y, point.y);
point.z = Mathf.InverseLerp(bounds.min.z, bounds.max.z, point.z);
return point;
}
protected override void Build()
{
base.Build();
if (_bend) Bend();
}
private void Bend()
{
if (sampleCount <= 1) return;
if (bendProperties.Length == 0) return;
for (int i = 0; i < bendProperties.Length; i++) BendObject(bendProperties[i]);
}
public void BendObject(BendProperty p)
{
if (!p.enabled) return;
GetevalResult(p.positionPercent);
p.transform.position = evalResult.position;
if (p.applyRotation)
{
//p.transform.rotation = evalResult.rotation * axisRotation * p.originalRotation;
p.transform.rotation = bendRotation * (Quaternion.Inverse(p.parentRotation) * p.originalRotation);
} else p.transform.rotation = p.originalRotation;
if (p.applyScale) p.transform.scale = p.originalScale * evalResult.size;
Matrix4x4 toLocalMatrix = Matrix4x4.TRS(p.transform.position, p.transform.rotation, p.transform.scale).inverse;
if (p.editMesh != null)
{
BendMesh(p.vertexPercents, p.normals, p.editMesh, toLocalMatrix);
p.editMesh.hasUpdate = true;
}
if (p._editColliderMesh != null)
{
BendMesh(p.colliderVertexPercents, p.colliderNormals, p.editColliderMesh, toLocalMatrix);
p.editColliderMesh.hasUpdate = true;
}
if (p.originalSpline != null)
{
for (int n = 0; n < p.splinePointPercents.Length; n++)
{
SplinePoint point = p.originalSpline.points[n];
GetevalResult(p.splinePointPercents[n]);
point.position = evalResult.position;
GetevalResult(p.primaryTangentPercents[n]);
point.tangent = evalResult.position;
GetevalResult(p.secondaryTangentPercents[n]);
point.tangent2 = evalResult.position;
switch (axis)
{
case Axis.X: point.normal = Quaternion.LookRotation(evalResult.forward, evalResult.up) * Quaternion.FromToRotation(Vector3.up, evalResult.up) * point.normal; break;
case Axis.Y: point.normal = Quaternion.LookRotation(evalResult.forward, evalResult.up) * Quaternion.FromToRotation(Vector3.up, evalResult.up) * point.normal; break;
case Axis.Z: point.normal = Quaternion.LookRotation(evalResult.forward, evalResult.up) * point.normal; break;
}
p.destinationSpline.points[n] = point;
}
}
}
void BendMesh(Vector3[] vertexPercents, Vector3[] originalNormals, TS_Mesh mesh, Matrix4x4 worldToLocalMatrix)
{
if(mesh.vertexCount != vertexPercents.Length)
{
Debug.LogError("Vertex count mismatch");
return;
}
for (int i = 0; i < mesh.vertexCount; i++)
{
Vector3 percent = vertexPercents[i];
if (axis == Axis.Y) percent.z = 1f - percent.z;
GetevalResult(percent);
mesh.vertices[i] = worldToLocalMatrix.MultiplyPoint3x4(evalResult.position);
mesh.normals[i] = worldToLocalMatrix.MultiplyVector(normalMatrix.MultiplyVector(originalNormals[i]));
}
}
protected override void PostBuild()
{
base.PostBuild();
if (!_bend) return;
for (int i = 0; i < bendProperties.Length; i++)
{
bendProperties[i].Apply(i > 0 || trs != spline.transform);
bendProperties[i].Update();
}
}
protected override void LateRun()
{
base.LateRun();
for (int i = 0; i < bendProperties.Length; i++)
{
bendProperties[i].Update();
}
}
[System.Serializable]
public class BendProperty
{
public bool enabled = true;
public bool isValid
{
get
{
return transform != null && transform.transform != null;
}
}
public TS_Transform transform;
public bool applyRotation = true;
public bool applyScale = true;
public bool bendMesh
{
get { return _bendMesh; }
set
{
if (value != _bendMesh)
{
_bendMesh = value;
if (value)
{
if (filter != null && filter.sharedMesh != null)
{
normals = originalMesh.normals;
for (int i = 0; i < normals.Length; i++) normals[i] = transform.transform.TransformDirection(normals[i]);
}
} else RevertMesh();
}
}
}
public bool generateLightmapUVs = false;
public bool bendCollider
{
get { return _bendCollider; }
set
{
if (value != _bendCollider)
{
_bendCollider = value;
if (value)
{
if (collider != null && collider.sharedMesh != null && collider.sharedMesh != originalMesh) colliderNormals = originalColliderMesh.normals;
}
else RevertCollider();
}
}
}
public bool bendSpline
{
get { return _bendSpline; }
set
{
_bendSpline = value;
if (value)
{
}
}
}
[SerializeField]
[HideInInspector]
private bool _bendMesh = true;
[SerializeField]
[HideInInspector]
private bool _bendSpline = true;
[SerializeField]
[HideInInspector]
private bool _bendCollider = true;
private float colliderUpdateDue = 0f;
public float colliderUpdateRate = 0.2f;
private bool updateCollider = false;
public Vector3 originalPosition = Vector3.zero;
public Vector3 originalScale = Vector3.one;
public Quaternion originalRotation = Quaternion.identity;
public Quaternion parentRotation = Quaternion.identity;
public Vector3 positionPercent;
public Vector3[] vertexPercents = new Vector3[0];
public Vector3[] normals = new Vector3[0];
public Vector3[] colliderVertexPercents = new Vector3[0];
public Vector3[] colliderNormals = new Vector3[0];
[SerializeField]
[HideInInspector]
private Mesh originalMesh = null;
[SerializeField]
[HideInInspector]
private Mesh originalColliderMesh = null;
private Spline _originalSpline;
[SerializeField]
[HideInInspector]
private Mesh destinationMesh = null;
[SerializeField]
[HideInInspector]
private Mesh destinationColliderMesh = null;
public Spline destinationSpline;
public TS_Mesh editMesh
{
get
{
if (!bendMesh || originalMesh == null) _editMesh = null;
else if (_editMesh == null && originalMesh != null) _editMesh = new TS_Mesh(originalMesh);
return _editMesh;
}
}
public TS_Mesh editColliderMesh
{
get
{
if (!bendCollider || originalColliderMesh == null) _editColliderMesh = null;
else if (_editColliderMesh == null && originalColliderMesh != null && originalColliderMesh != originalMesh) _editColliderMesh = new TS_Mesh(originalColliderMesh);
return _editColliderMesh;
}
}
public Spline originalSpline
{
get
{
if (!bendSpline || splineComputer == null) _originalSpline = null;
else if (_originalSpline == null && splineComputer != null) {
_originalSpline = new Spline(splineComputer.type);
_originalSpline.points = splineComputer.GetPoints();
}
return _originalSpline;
}
}
public TS_Mesh _editMesh = null;
public TS_Mesh _editColliderMesh = null;
public MeshFilter filter = null;
public MeshCollider collider = null;
public SplineComputer splineComputer = null;
public Vector3[] splinePointPercents = new Vector3[0];
public Vector3[] primaryTangentPercents = new Vector3[0];
public Vector3[] secondaryTangentPercents = new Vector3[0];
[SerializeField]
[HideInInspector]
private bool parent;
public BendProperty(Transform t, bool isParent = false)
{
parent = isParent;
transform = new TS_Transform(t);
originalPosition = t.localPosition;
originalScale = t.localScale;
originalRotation = t.localRotation;
parentRotation = t.transform.rotation;
if (t.transform.parent != null) parentRotation = t.transform.parent.rotation;
filter = t.GetComponent<MeshFilter>();
collider = t.GetComponent<MeshCollider>();
if (filter != null && filter.sharedMesh != null)
{
originalMesh = filter.sharedMesh;
normals = originalMesh.normals;
for (int i = 0; i < normals.Length; i++) normals[i] = transform.transform.TransformDirection(normals[i]).normalized;
}
if (collider != null && collider.sharedMesh != null)
{
originalColliderMesh = collider.sharedMesh;
colliderNormals = originalColliderMesh.normals;
for (int i = 0; i < colliderNormals.Length; i++) colliderNormals[i] = transform.transform.TransformDirection(colliderNormals[i]);
}
if (!parent) splineComputer = t.GetComponent<SplineComputer>();
if (splineComputer != null)
{
if (splineComputer.isClosed) originalSpline.Close();
destinationSpline = new Spline(originalSpline.type);
destinationSpline.points = new SplinePoint[originalSpline.points.Length];
destinationSpline.points = splineComputer.GetPoints();
if (splineComputer.isClosed) destinationSpline.Close();
}
}
public void Revert()
{
if (!isValid) return;
RevertTransform();
RevertCollider();
RevertMesh();
if (splineComputer != null) splineComputer.SetPoints(_originalSpline.points);
}
private void RevertMesh()
{
if (filter != null) filter.sharedMesh = originalMesh;
destinationMesh = null;
}
private void RevertTransform()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
transform.transform.localPosition = originalPosition;
transform.transform.localRotation = originalRotation;
}
else
{
transform.localPosition = originalPosition;
transform.localRotation = originalRotation;
transform.Update();
}
#else
transform.localPosition = originalPosition;
transform.localRotation = originalRotation;
transform.Update();
#endif
transform.scale = originalScale;
transform.Update();
}
private void RevertCollider()
{
if (collider != null) collider.sharedMesh = originalColliderMesh;
destinationColliderMesh = null;
}
public void Apply(bool applyTransform)
{
if (!enabled) return;
if (!isValid) return;
if(applyTransform) transform.Update();
if (editMesh != null && editMesh.hasUpdate) ApplyMesh();
if (bendCollider && collider != null)
{
if (!updateCollider)
{
if((editColliderMesh == null && editMesh != null) || editColliderMesh != null)
{
updateCollider = true;
if(Application.isPlaying) colliderUpdateDue = Time.time + colliderUpdateRate;
}
}
}
if (splineComputer != null) ApplySpline();
}
public void Update()
{
if (Time.time >= colliderUpdateDue && updateCollider)
{
updateCollider = false;
ApplyCollider();
}
}
private void ApplyMesh()
{
if (filter == null) return;
MeshUtility.CalculateTangents(editMesh);
if (destinationMesh == null)
{
destinationMesh = new Mesh();
destinationMesh.name = originalMesh.name;
}
editMesh.WriteMesh(ref destinationMesh);
destinationMesh.RecalculateBounds();
filter.sharedMesh = destinationMesh;
}
private void ApplyCollider()
{
if (collider == null) return;
if (originalColliderMesh == originalMesh) collider.sharedMesh = filter.sharedMesh; //if the collider has the same mesh as the filter - just copy it
else
{
MeshUtility.CalculateTangents(editColliderMesh);
if (destinationColliderMesh == null)
{
destinationColliderMesh = new Mesh();
destinationColliderMesh.name = originalColliderMesh.name;
}
editColliderMesh.WriteMesh(ref destinationColliderMesh);
destinationColliderMesh.RecalculateBounds();
collider.sharedMesh = destinationColliderMesh;
}
}
private void ApplySpline()
{
if (destinationSpline == null) return;
splineComputer.SetPoints(destinationSpline.points);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f64d070be79692d449ab6f792ee7fb57
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 71feaa5f5395f3640a94b1ba649bc941, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,684 @@
using UnityEngine;
using System.Collections;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Dreamteck.Splines
{
[AddComponentMenu("Dreamteck/Splines/Object Controller")]
public class ObjectController : SplineUser
{
[System.Serializable]
internal class ObjectControl
{
public bool isNull
{
get
{
return gameObject == null;
}
}
public Transform transform
{
get {
if (gameObject == null) return null;
return gameObject.transform;
}
}
public GameObject gameObject;
public Vector3 position = Vector3.zero;
public Quaternion rotation = Quaternion.identity;
public Vector3 scale = Vector3.one;
public bool active = true;
public Vector3 baseScale = Vector3.one;
public ObjectControl(GameObject input)
{
gameObject = input;
baseScale = gameObject.transform.localScale;
}
public void Destroy()
{
if (gameObject == null) return;
GameObject.Destroy(gameObject);
}
public void DestroyImmediate()
{
if (gameObject == null) return;
GameObject.DestroyImmediate(gameObject);
}
public void Apply()
{
if (gameObject == null) return;
transform.position = position;
transform.rotation = rotation;
transform.localScale = scale;
gameObject.SetActive(active);
}
}
public enum ObjectMethod { Instantiate, GetChildren }
public enum Positioning { Stretch, Clip }
public enum Iteration { Ordered, Random }
[SerializeField]
[HideInInspector]
public GameObject[] objects = new GameObject[0];
public ObjectMethod objectMethod
{
get { return _objectMethod; }
set
{
if (value != _objectMethod)
{
if (value == ObjectMethod.GetChildren)
{
_objectMethod = value;
Spawn();
}
else _objectMethod = value;
}
}
}
public int spawnCount
{
get { return _spawnCount; }
set
{
if (value != _spawnCount)
{
if (value < 0) value = 0;
if (_objectMethod == ObjectMethod.Instantiate)
{
if (value < _spawnCount)
{
_spawnCount = value;
Remove();
}
else
{
_spawnCount = value;
Spawn();
}
}
else _spawnCount = value;
}
}
}
public Positioning objectPositioning
{
get { return _objectPositioning; }
set
{
if (value != _objectPositioning)
{
_objectPositioning = value;
Rebuild();
}
}
}
public Iteration iteration
{
get { return _iteration; }
set
{
if (value != _iteration)
{
_iteration = value;
Rebuild();
}
}
}
#if UNITY_EDITOR
public bool retainPrefabInstancesInEditor
{
get { return _retainPrefabInstancesInEditor; }
set
{
if (value != _retainPrefabInstancesInEditor)
{
_retainPrefabInstancesInEditor = value;
Clear();
Spawn();
Rebuild();
}
}
}
#endif
public int randomSeed
{
get { return _randomSeed; }
set
{
if (value != _randomSeed)
{
_randomSeed = value;
Rebuild();
}
}
}
public Vector3 minOffset
{
get { return _minOffset; }
set
{
if (value != _minOffset)
{
_minOffset = value;
Rebuild();
}
}
}
public Vector3 maxOffset
{
get { return _maxOffset; }
set
{
if (value != _maxOffset)
{
_maxOffset = value;
Rebuild();
}
}
}
public bool offsetUseWorldCoords
{
get { return _offsetUseWorldCoords; }
set
{
if (value != _offsetUseWorldCoords)
{
_offsetUseWorldCoords = value;
Rebuild();
}
}
}
public Vector3 minRotation
{
get { return _minRotation; }
set
{
if (value != _minRotation)
{
_minRotation = value;
Rebuild();
}
}
}
public Vector3 maxRotation
{
get { return _maxRotation; }
set
{
if (value != _maxRotation)
{
_maxRotation = value;
Rebuild();
}
}
}
public Vector3 rotationOffset
{
get { return (_maxRotation+_minRotation)/2f; }
set
{
if (value != _minRotation || value != _maxRotation)
{
_minRotation = _maxRotation = value;
Rebuild();
}
}
}
public Vector3 minScaleMultiplier
{
get { return _minScaleMultiplier; }
set
{
if (value != _minScaleMultiplier)
{
_minScaleMultiplier = value;
Rebuild();
}
}
}
public Vector3 maxScaleMultiplier
{
get { return _maxScaleMultiplier; }
set
{
if (value != _maxScaleMultiplier)
{
_maxScaleMultiplier = value;
Rebuild();
}
}
}
public Vector3 scaleMultiplier
{
get { return (_minScaleMultiplier + _maxScaleMultiplier) / 2f; }
set
{
if (value != _minScaleMultiplier || value != _maxScaleMultiplier)
{
_minScaleMultiplier = _maxScaleMultiplier = value;
Rebuild();
}
}
}
public bool shellOffset
{
get { return _shellOffset; }
set
{
if (value != _shellOffset)
{
_shellOffset = value;
Rebuild();
}
}
}
public bool applyRotation
{
get { return _applyRotation; }
set
{
if (value != _applyRotation)
{
_applyRotation = value;
Rebuild();
}
}
}
public bool rotateByOffset
{
get { return _rotateByOffset; }
set
{
if (value != _rotateByOffset)
{
_rotateByOffset = value;
Rebuild();
}
}
}
public bool applyScale
{
get { return _applyScale; }
set
{
if (value != _applyScale)
{
_applyScale = value;
Rebuild();
}
}
}
public float evaluateOffset
{
get { return _evaluateOffset; }
set
{
if (value != _evaluateOffset)
{
_evaluateOffset = value;
Rebuild();
}
}
}
[SerializeField]
[HideInInspector]
private float _evaluateOffset = 0f;
[SerializeField]
[HideInInspector]
private int _spawnCount = 0;
#if UNITY_EDITOR
[SerializeField]
[HideInInspector]
private bool _retainPrefabInstancesInEditor = true;
#endif
[SerializeField]
[HideInInspector]
private Positioning _objectPositioning = Positioning.Stretch;
[SerializeField]
[HideInInspector]
private Iteration _iteration = Iteration.Ordered;
[SerializeField]
[HideInInspector]
private int _randomSeed = 1;
[SerializeField]
[HideInInspector]
private Vector3 _minOffset = Vector3.zero;
[SerializeField]
[HideInInspector]
private Vector3 _maxOffset = Vector3.zero;
[SerializeField]
[HideInInspector]
private bool _offsetUseWorldCoords = false;
[SerializeField]
[HideInInspector]
private Vector3 _minRotation = Vector3.zero;
[SerializeField]
[HideInInspector]
private Vector3 _maxRotation = Vector3.zero;
[SerializeField]
[HideInInspector]
private Vector3 _minScaleMultiplier = Vector3.one;
[SerializeField]
[HideInInspector]
private Vector3 _maxScaleMultiplier = Vector3.one;
[SerializeField]
[HideInInspector]
private bool _shellOffset = false;
[SerializeField]
[HideInInspector]
private bool _applyRotation = true;
[SerializeField]
[HideInInspector]
private bool _rotateByOffset = false;
[SerializeField]
[HideInInspector]
private bool _applyScale = false;
[SerializeField]
[HideInInspector]
private ObjectMethod _objectMethod = ObjectMethod.Instantiate;
[HideInInspector]
public bool delayedSpawn = false;
[HideInInspector]
public float spawnDelay = 0.1f;
[SerializeField]
[HideInInspector]
private int lastChildCount = 0;
[SerializeField]
[HideInInspector]
private ObjectControl[] spawned = new ObjectControl[0];
System.Random offsetRandomizer, shellRandomizer, rotationRandomizer, scaleRandomizer;
public void Clear()
{
for (int i = 0; i < spawned.Length; i++)
{
if (spawned[i] == null || spawned[i].transform == null) continue;
spawned[i].transform.localScale = spawned[i].baseScale;
if (_objectMethod == ObjectMethod.GetChildren) spawned[i].gameObject.SetActive(false);
else
{
#if UNITY_EDITOR
if (!Application.isPlaying) spawned[i].DestroyImmediate();
else spawned[i].Destroy();
#else
spawned[i].Destroy();
#endif
}
}
spawned = new ObjectControl[0];
}
private void OnValidate()
{
if (_spawnCount < 0) _spawnCount = 0;
}
private void Remove()
{
#if UNITY_EDITOR
#if !UNITY_2018_3_OR_NEWER
if (PrefabUtility.GetPrefabType(gameObject) == PrefabType.Prefab) return;
#endif
#endif
if (_spawnCount >= spawned.Length) return;
for (int i = spawned.Length - 1; i >= _spawnCount; i--)
{
if (i >= spawned.Length) break;
if (spawned[i] == null) continue;
spawned[i].transform.localScale = spawned[i].baseScale;
if (_objectMethod == ObjectMethod.GetChildren) spawned[i].gameObject.SetActive(false);
else
{
if (Application.isEditor) spawned[i].DestroyImmediate();
else spawned[i].Destroy();
}
}
ObjectControl[] newSpawned = new ObjectControl[_spawnCount];
for (int i = 0; i < newSpawned.Length; i++)
{
newSpawned[i] = spawned[i];
}
spawned = newSpawned;
Rebuild();
}
public void GetAll()
{
ObjectControl[] newSpawned = new ObjectControl[transform.childCount];
int index = 0;
foreach (Transform child in transform)
{
if (newSpawned[index] == null)
{
newSpawned[index++] = new ObjectControl(child.gameObject);
continue;
}
bool found = false;
for (int i = 0; i < spawned.Length; i++)
{
if (spawned[i].gameObject == child.gameObject)
{
newSpawned[index++] = spawned[i];
found = true;
break;
}
}
if (!found) newSpawned[index++] = new ObjectControl(child.gameObject);
}
spawned = newSpawned;
}
public void Spawn()
{
#if UNITY_EDITOR
#if !UNITY_2018_3_OR_NEWER
if (PrefabUtility.GetPrefabType(gameObject) == PrefabType.Prefab) return;
#endif
#endif
if (_objectMethod == ObjectMethod.Instantiate)
{
if (delayedSpawn && Application.isPlaying)
{
StopCoroutine("InstantiateAllWithDelay");
StartCoroutine(InstantiateAllWithDelay());
}
else InstantiateAll();
}
else GetAll();
Rebuild();
}
protected override void LateRun()
{
base.LateRun();
if (_objectMethod == ObjectMethod.GetChildren && lastChildCount != transform.childCount)
{
Spawn();
lastChildCount = transform.childCount;
}
}
IEnumerator InstantiateAllWithDelay()
{
if (spline == null) yield break;
if (objects.Length == 0) yield break;
for (int i = spawned.Length; i <= spawnCount; i++)
{
InstantiateSingle();
yield return new WaitForSeconds(spawnDelay);
}
}
private void InstantiateAll()
{
if (spline == null) return;
if (objects.Length == 0) return;
for (int i = spawned.Length; i < spawnCount; i++) InstantiateSingle();
}
private void InstantiateSingle()
{
if (objects.Length == 0) return;
int index = 0;
if (_iteration == Iteration.Ordered)
{
index = spawned.Length - Mathf.FloorToInt(spawned.Length / objects.Length) * objects.Length;
}
else index = Random.Range(0, objects.Length);
if (objects[index] == null) return;
ObjectControl[] newSpawned = new ObjectControl[spawned.Length + 1];
spawned.CopyTo(newSpawned, 0);
#if UNITY_EDITOR
if (!Application.isPlaying && retainPrefabInstancesInEditor)
{
GameObject go = (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(objects[index]);
go.transform.position = transform.position;
go.transform.rotation = transform.rotation;
newSpawned[newSpawned.Length - 1] = new ObjectControl(go);
} else
{
newSpawned[newSpawned.Length - 1] = new ObjectControl((GameObject)Instantiate(objects[index], transform.position, transform.rotation));
}
#else
newSpawned[newSpawned.Length - 1] = new ObjectControl((GameObject)Instantiate(objects[index], transform.position, transform.rotation));
#endif
newSpawned[newSpawned.Length - 1].transform.parent = transform;
spawned = newSpawned;
}
protected override void Build()
{
base.Build();
offsetRandomizer = new System.Random(_randomSeed);
if(_shellOffset) shellRandomizer = new System.Random(_randomSeed + 1);
rotationRandomizer = new System.Random(_randomSeed + 2);
scaleRandomizer = new System.Random(_randomSeed + 3);
bool randomScaleMultiplier = _minScaleMultiplier != _maxScaleMultiplier;
for (int i = 0; i < spawned.Length; i++)
{
if (spawned[i] == null)
{
Clear();
Spawn();
break;
}
float percent = 0f;
if (spawned.Length > 1)
{
if(spline.isClosed) percent = (float)i / spawned.Length;
else percent = (float)i / (spawned.Length - 1);
}
percent += _evaluateOffset;
if (percent > 1f) percent -= 1f;
else if (percent < 0f) percent += 1f;
if (objectPositioning == Positioning.Clip) spline.Evaluate(percent, evalResult);
else Evaluate(percent, evalResult);
ModifySample(evalResult);
spawned[i].position = evalResult.position;
if (_applyScale)
{
Vector3 scale = spawned[i].baseScale * evalResult.size;
if(randomScaleMultiplier)
{
scale.x *= Mathf.Lerp(_minScaleMultiplier.x, _maxScaleMultiplier.x, (float)scaleRandomizer.NextDouble());
scale.y *= Mathf.Lerp(_minScaleMultiplier.y, _maxScaleMultiplier.y, (float)scaleRandomizer.NextDouble());
scale.z *= Mathf.Lerp(_minScaleMultiplier.z, _maxScaleMultiplier.z, (float)scaleRandomizer.NextDouble());
} else
{
scale.x *= scaleMultiplier.x;
scale.y *= scaleMultiplier.y;
scale.z *= scaleMultiplier.z;
}
spawned[i].scale = scale;
}
else spawned[i].scale = spawned[i].baseScale;
Vector3 right = Vector3.Cross(evalResult.forward, evalResult.up).normalized;
Vector3 posOffset = _minOffset;
if (_minOffset != _maxOffset)
{
if(_shellOffset)
{
float x = _maxOffset.x - _minOffset.x;
float y = _maxOffset.y - _minOffset.y;
float angleInRadians = (float)shellRandomizer.NextDouble() * 360f * Mathf.Deg2Rad;
posOffset = new Vector2(0.5f * Mathf.Cos(angleInRadians), 0.5f * Mathf.Sin(angleInRadians));
posOffset.x *= x;
posOffset.y *= y;
} else
{
float rnd = (float)offsetRandomizer.NextDouble();
posOffset.x = Mathf.Lerp(_minOffset.x, _maxOffset.x, rnd);
rnd = (float)offsetRandomizer.NextDouble();
posOffset.y = Mathf.Lerp(_minOffset.y, _maxOffset.y, rnd);
rnd = (float)offsetRandomizer.NextDouble();
posOffset.z = Mathf.Lerp(_minOffset.z, _maxOffset.z, rnd);
}
}
if (_offsetUseWorldCoords) spawned[i].position += posOffset;
else spawned[i].position += right * posOffset.x * evalResult.size + evalResult.up * posOffset.y * evalResult.size;
if (_applyRotation)
{
Quaternion offsetRot = Quaternion.Euler(Mathf.Lerp(_minRotation.x, _maxRotation.x, (float)rotationRandomizer.NextDouble()), Mathf.Lerp(_minRotation.y, _maxRotation.y, (float)rotationRandomizer.NextDouble()), Mathf.Lerp(_minRotation.z, _maxRotation.z, (float)rotationRandomizer.NextDouble()));
if(_rotateByOffset) spawned[i].rotation = Quaternion.LookRotation(evalResult.forward, spawned[i].position - evalResult.position) * offsetRot;
else spawned[i].rotation = evalResult.rotation* offsetRot;
}
if (_objectPositioning == Positioning.Clip)
{
if (percent < clipFrom || percent > clipTo) spawned[i].active = false;
else spawned[i].active = true;
}
}
}
protected override void PostBuild()
{
base.PostBuild();
for (int i = 0; i < spawned.Length; i++)
{
spawned[i].Apply();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: acb0592a986cebb4287d41702ab6ea22
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 809d29b9ca1b74947aca02225d2ec233, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,224 @@
namespace Dreamteck.Splines
{
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[ExecuteInEditMode]
[AddComponentMenu("Dreamteck/Splines/Particle Controller")]
public class ParticleController : SplineUser
{
[HideInInspector]
public ParticleSystem _particleSystem;
public enum EmitPoint { Beginning, Ending, Random, Ordered }
public enum MotionType { None, UseParticleSystem, FollowForward, FollowBackward, ByNormal, ByNormalRandomized }
public enum Wrap { Default, Loop }
[HideInInspector]
public bool volumetric = false;
[HideInInspector]
public bool emitFromShell = false;
[HideInInspector]
public Vector2 scale = Vector2.one;
[HideInInspector]
public EmitPoint emitPoint = EmitPoint.Beginning;
[HideInInspector]
public MotionType motionType = MotionType.UseParticleSystem;
[HideInInspector]
public Wrap wrapMode = Wrap.Default;
[HideInInspector]
public float minCycles = 1f;
[HideInInspector]
public float maxCycles = 1f;
private ParticleSystem.Particle[] particles = new ParticleSystem.Particle[0];
private Particle[] controllers = new Particle[0];
private int particleCount = 0;
private int birthIndex = 0;
protected override void LateRun()
{
if (_particleSystem == null) return;
if (sampleCount == 0) return;
int maxParticles = _particleSystem.main.maxParticles;
if (particles.Length != maxParticles)
{
particles = new ParticleSystem.Particle[maxParticles];
Particle[] newControllers = new Particle[maxParticles];
for (int i = 0; i < newControllers.Length; i++)
{
if (i >= controllers.Length) break;
newControllers[i] = controllers[i];
}
controllers = newControllers;
}
particleCount = _particleSystem.GetParticles(particles);
bool isLocal = _particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.Local;
Transform particleSystemTransform = _particleSystem.transform;
for (int i = particleCount-1; i >= 0; i--)
{
if (isLocal) TransformParticle(ref particles[i], particleSystemTransform);
if (controllers[i] == null)
{
controllers[i] = new Particle();
OnParticleBorn(i);
if (isLocal) InverseTransformParticle(ref particles[i], particleSystemTransform);
continue;
}
float life = particles[i].startLifetime - particles[i].remainingLifetime;
if (life <= Time.deltaTime && controllers[i].lifeTime > life) OnParticleBorn(i);
if (isLocal) InverseTransformParticle(ref particles[i], particleSystemTransform);
}
for (int i = 0; i < particleCount; i++)
{
if (controllers[i] == null) controllers[i] = new Particle();
if (isLocal) TransformParticle(ref particles[i], particleSystemTransform);
HandleParticle(i);
if (isLocal) InverseTransformParticle(ref particles[i], particleSystemTransform);
}
_particleSystem.SetParticles(particles, particleCount);
}
void TransformParticle(ref ParticleSystem.Particle particle, Transform trs)
{
particle.position = trs.TransformPoint(particle.position);
particle.velocity = trs.TransformDirection(particle.velocity);
}
void InverseTransformParticle(ref ParticleSystem.Particle particle, Transform trs)
{
particle.position = trs.InverseTransformPoint(particle.position);
particle.velocity = trs.InverseTransformDirection(particle.velocity);
}
protected override void Reset()
{
base.Reset();
updateMethod = UpdateMethod.LateUpdate;
if (_particleSystem == null) _particleSystem = GetComponent<ParticleSystem>();
}
void HandleParticle(int index)
{
float lifePercent = particles[index].remainingLifetime / particles[index].startLifetime;
if (motionType == MotionType.FollowBackward || motionType == MotionType.FollowForward || motionType == MotionType.None)
{
Evaluate(controllers[index].GetSplinePercent(wrapMode, particles[index]), evalResult);
ModifySample(evalResult);
particles[index].position = evalResult.position;
if (volumetric)
{
Vector3 right = -Vector3.Cross(evalResult.forward, evalResult.up);
Vector2 offset = controllers[index].startOffset;
if (motionType != MotionType.None) offset = Vector2.Lerp(controllers[index].startOffset, controllers[index].endOffset, 1f - lifePercent);
particles[index].position += right * offset.x * scale.x * evalResult.size + evalResult.up * offset.y * scale.y * evalResult.size;
}
particles[index].velocity = evalResult.forward;
particles[index].startColor = controllers[index].startColor * evalResult.color;
}
controllers[index].remainingLifetime = particles[index].remainingLifetime;
controllers[index].lifeTime = particles[index].startLifetime - particles[index].remainingLifetime;
}
void OnParticleDie(int index)
{
}
void OnParticleBorn(int index)
{
birthIndex++;
double percent = 0.0;
float emissionRate = Mathf.Lerp(_particleSystem.emission.rateOverTime.constantMin, _particleSystem.emission.rateOverTime.constantMax, 0.5f);
float expectedParticleCount = emissionRate * _particleSystem.main.startLifetime.constantMax;
if (birthIndex > expectedParticleCount) birthIndex = 0;
switch (emitPoint)
{
case EmitPoint.Beginning: percent = 0f; break;
case EmitPoint.Ending: percent = 1f; break;
case EmitPoint.Random: percent = Random.Range(0f, 1f); break;
case EmitPoint.Ordered: percent = expectedParticleCount > 0 ? (float)birthIndex / expectedParticleCount : 0f; break;
}
Evaluate(percent, evalResult);
ModifySample(evalResult);
controllers[index].startColor = particles[index].startColor;
controllers[index].startPercent = percent;
controllers[index].startLifetime = particles[index].startLifetime;
controllers[index].remainingLifetime = particles[index].remainingLifetime;
controllers[index].cycleSpeed = Random.Range(minCycles, maxCycles);
Vector2 circle = Vector2.zero;
if (volumetric)
{
if (emitFromShell) circle = Quaternion.AngleAxis(Random.Range(0f, 360f), Vector3.forward) * Vector2.right;
else circle = Random.insideUnitCircle;
}
controllers[index].startOffset = circle * 0.5f;
controllers[index].endOffset = Random.insideUnitCircle * 0.5f;
Vector3 right = Vector3.Cross(evalResult.forward, evalResult.up);
particles[index].position = evalResult.position + right * controllers[index].startOffset.x * evalResult.size * scale.x + evalResult.up * controllers[index].startOffset.y * evalResult.size * scale.y;
float forceX = _particleSystem.forceOverLifetime.x.constantMax;
float forceY = _particleSystem.forceOverLifetime.y.constantMax;
float forceZ = _particleSystem.forceOverLifetime.z.constantMax;
if (_particleSystem.forceOverLifetime.randomized)
{
forceX = Random.Range(_particleSystem.forceOverLifetime.x.constantMin, _particleSystem.forceOverLifetime.x.constantMax);
forceY = Random.Range(_particleSystem.forceOverLifetime.y.constantMin, _particleSystem.forceOverLifetime.y.constantMax);
forceZ = Random.Range(_particleSystem.forceOverLifetime.z.constantMin, _particleSystem.forceOverLifetime.z.constantMax);
}
float time = particles[index].startLifetime - particles[index].remainingLifetime;
Vector3 forceDistance = new Vector3(forceX, forceY, forceZ) * 0.5f * (time * time);
float startSpeed = _particleSystem.main.startSpeed.constantMax;
if (motionType == MotionType.ByNormal)
{
particles[index].position += evalResult.up * startSpeed * (particles[index].startLifetime - particles[index].remainingLifetime);
particles[index].position += forceDistance;
particles[index].velocity = evalResult.up * startSpeed + new Vector3(forceX, forceY, forceZ) * time;
}
else if (motionType == MotionType.ByNormalRandomized)
{
Vector3 normal = Quaternion.AngleAxis(Random.Range(0f, 360f), evalResult.forward) * evalResult.up;
particles[index].position += normal * startSpeed * (particles[index].startLifetime - particles[index].remainingLifetime);
particles[index].position += forceDistance;
particles[index].velocity = normal * startSpeed + new Vector3(forceX, forceY, forceZ) * time;
}
HandleParticle(index);
}
public class Particle
{
internal Vector2 startOffset = Vector2.zero;
internal Vector2 endOffset = Vector2.zero;
internal float cycleSpeed = 0f;
internal float startLifetime = 0f;
internal Color startColor = Color.white;
internal float remainingLifetime = 0f;
internal float lifeTime = 0f;
internal double startPercent = 0.0;
internal double GetSplinePercent(Wrap wrap, ParticleSystem.Particle particle)
{
switch (wrap)
{
case Wrap.Default: return DMath.Clamp01(startPercent + (1f - particle.remainingLifetime / particle.startLifetime) * cycleSpeed);
case Wrap.Loop:
double loopPoint = startPercent + (1.0 - particle.remainingLifetime / particle.startLifetime) * cycleSpeed;
if(loopPoint > 1.0) loopPoint -= Mathf.FloorToInt((float)loopPoint);
return loopPoint;
}
return 0.0;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More