initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
@ -0,0 +1,146 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Mathematics;
|
||||
using UnityEditor;
|
||||
using UnityEditor.EditorTools;
|
||||
using UnityEditor.Splines;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Splines;
|
||||
|
||||
using Interpolators = UnityEngine.Splines.Interpolators;
|
||||
|
||||
namespace Unity.Splines.Examples
|
||||
{
|
||||
[EditorTool("Border Tool", typeof(SpawnWithinSplineBounds))]
|
||||
public class BorderTool : SplineDataToolBase<float>, IDrawSelectedHandles
|
||||
{
|
||||
const float k_HandleOffset = 2f;
|
||||
const float k_LineLengthsSize = 4f;
|
||||
const int k_SamplesPerCurve = 15;
|
||||
|
||||
List<Vector3> m_LineSegments = new List<Vector3>();
|
||||
|
||||
GUIContent m_IconContent;
|
||||
public override GUIContent toolbarIcon => m_IconContent;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_IconContent = new GUIContent()
|
||||
{
|
||||
image = Resources.Load<Texture2D>("Icons/BorderTool"),
|
||||
text = "Border Tool",
|
||||
tooltip = "Define the border limit of the area defined by the spline."
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnToolGUI(EditorWindow window)
|
||||
{
|
||||
var splineDataTarget = target as SpawnWithinSplineBounds;
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.splineContainer.Spline, splineDataTarget.splineContainer.transform.localToWorldMatrix);
|
||||
|
||||
Undo.RecordObject(splineDataTarget,"Modifying Border SplineData");
|
||||
|
||||
Handles.color = Color.yellow;
|
||||
//User defined : Handles to manipulate Border data
|
||||
DrawDataPoints(nativeSpline, splineDataTarget.spawnBorderData);
|
||||
//Use defined : Draws a line along the whole Border SplineData
|
||||
DrawSplineData(nativeSpline, splineDataTarget.spawnBorderData);
|
||||
|
||||
//Using the out-of the box behaviour to manipulate SplineData indexes
|
||||
nativeSpline.DataPointHandles(splineDataTarget.spawnBorderData);
|
||||
}
|
||||
|
||||
public void OnDrawHandles()
|
||||
{
|
||||
var splineDataTarget = target as SpawnWithinSplineBounds;
|
||||
if(ToolManager.IsActiveTool(this) || splineDataTarget.splineContainer == null)
|
||||
return;
|
||||
|
||||
//Reduce number of time we have to convert spline To NativeSpline
|
||||
if(Event.current.type != EventType.Repaint)
|
||||
return;
|
||||
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.splineContainer.Spline, splineDataTarget.splineContainer.transform.localToWorldMatrix);
|
||||
Color color = Color.yellow;
|
||||
color.a = 0.5f;
|
||||
Handles.color = color;
|
||||
DrawSplineData(nativeSpline,splineDataTarget.spawnBorderData);
|
||||
}
|
||||
|
||||
protected override bool DrawDataPoint(
|
||||
Vector3 position,
|
||||
Vector3 tangent,
|
||||
Vector3 up,
|
||||
float inValue,
|
||||
out float outValue)
|
||||
{
|
||||
var controlID = GUIUtility.GetControlID(FocusType.Passive);
|
||||
outValue = inValue;
|
||||
var handleColor = Handles.color;
|
||||
if(GUIUtility.hotControl == 0 && HandleUtility.nearestControl == controlID)
|
||||
handleColor = Handles.preselectionColor;
|
||||
|
||||
var right = Vector3.Cross(tangent.normalized, up.normalized);
|
||||
var borderPos = position + right * inValue;
|
||||
|
||||
var size = k_HandleSize * HandleUtility.GetHandleSize(borderPos);
|
||||
var sliderOffset = GetBorderHandleOffset(borderPos);
|
||||
|
||||
var handleMatrix = Handles.matrix * Matrix4x4.TRS(sliderOffset, Quaternion.identity, Vector3.one);
|
||||
var inUse = false;
|
||||
using (new Handles.DrawingScope(handleColor, handleMatrix))
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newBorderPos = Handles.Slider(controlID, borderPos, right, size, Handles.RectangleHandleCap, 0f);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
var delta = newBorderPos - borderPos;
|
||||
|
||||
outValue = Mathf.Max(0f, inValue + (Vector3.Dot(right, delta) > 0 ? delta.magnitude : -delta.magnitude));
|
||||
inUse = true;
|
||||
}
|
||||
}
|
||||
return inUse;
|
||||
}
|
||||
|
||||
void DrawSplineData(
|
||||
ISpline spline,
|
||||
SplineData<float> splineData)
|
||||
{
|
||||
m_LineSegments.Clear();
|
||||
|
||||
var curveCount = spline.Closed ? spline.Count : spline.Count - 1;
|
||||
var stepSize = 1f / k_SamplesPerCurve;
|
||||
var prevBorderPos = Vector3.zero;
|
||||
|
||||
for (int curveIndex = 0; curveIndex < curveCount; ++curveIndex)
|
||||
{
|
||||
for (int step = 0; step < k_SamplesPerCurve; ++step)
|
||||
{
|
||||
var splineTime = spline.CurveToSplineT(curveIndex + step * stepSize);
|
||||
spline.Evaluate(splineTime, out var position, out var tangent, out var upVector);
|
||||
var right = math.cross(math.normalize(tangent), upVector);
|
||||
var border = splineData.Evaluate(spline, splineTime, PathIndexUnit.Normalized, new Interpolators.LerpFloat());
|
||||
var borderPos = position + right * border;
|
||||
borderPos += (float3) GetBorderHandleOffset(borderPos);
|
||||
if (curveIndex > 0 || step > 0)
|
||||
{
|
||||
m_LineSegments.Add(prevBorderPos);
|
||||
m_LineSegments.Add(borderPos);
|
||||
}
|
||||
|
||||
prevBorderPos = borderPos;
|
||||
}
|
||||
}
|
||||
|
||||
Handles.DrawDottedLines(m_LineSegments.ToArray(), k_LineLengthsSize);
|
||||
|
||||
}
|
||||
|
||||
Vector3 GetBorderHandleOffset(Vector3 borderPos)
|
||||
{
|
||||
var size = k_HandleSize * HandleUtility.GetHandleSize(borderPos);
|
||||
return Vector3.up * size * k_HandleOffset;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 587e928622d803146a2c2b07253c78e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,163 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Mathematics;
|
||||
using UnityEditor;
|
||||
using UnityEditor.EditorTools;
|
||||
using UnityEditor.Splines;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Splines;
|
||||
|
||||
using Interpolators = UnityEngine.Splines.Interpolators;
|
||||
|
||||
namespace Unity.Splines.Examples
|
||||
{
|
||||
[EditorTool("Drift Tool", typeof(DriftSplineData))]
|
||||
public class DriftTool : SplineDataToolBase<float>, IDrawSelectedHandles
|
||||
{
|
||||
float m_DisplaySpace = 0.2f;
|
||||
List<Vector3> m_LineSegments = new List<Vector3>();
|
||||
|
||||
GUIContent m_IconContent;
|
||||
public override GUIContent toolbarIcon => m_IconContent;
|
||||
|
||||
bool m_DriftInUse;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_IconContent = new GUIContent()
|
||||
{
|
||||
image = Resources.Load<Texture2D>("Icons/DriftTool"),
|
||||
text = "Drift Tool",
|
||||
tooltip = "Adjust how much the vehicle is drifting away from the spline."
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnToolGUI(EditorWindow window)
|
||||
{
|
||||
var splineDataTarget = target as DriftSplineData;
|
||||
|
||||
if(splineDataTarget == null || splineDataTarget.container == null)
|
||||
return;
|
||||
|
||||
Undo.RecordObject(splineDataTarget,"Modifying Drift SplineData");
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.container.Spline, splineDataTarget.container.transform.localToWorldMatrix);
|
||||
|
||||
Handles.color = Color.green;
|
||||
|
||||
//User defined : Handles to manipulate Drift data
|
||||
m_DriftInUse = DrawDataPoints(nativeSpline, splineDataTarget.drift);
|
||||
//Use defined : Draws a line along the whole Drift SplineData
|
||||
DrawSplineData(nativeSpline, splineDataTarget.drift);
|
||||
|
||||
//Using the out-of the box behaviour to manipulate SplineData indexes
|
||||
nativeSpline.DataPointHandles(splineDataTarget.drift);
|
||||
}
|
||||
|
||||
public void OnDrawHandles()
|
||||
{
|
||||
var splineDataTarget = target as DriftSplineData;
|
||||
if(ToolManager.IsActiveTool(this) || splineDataTarget.container == null)
|
||||
return;
|
||||
|
||||
if(Event.current.type != EventType.Repaint)
|
||||
return;
|
||||
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.container.Spline, splineDataTarget.container.transform.localToWorldMatrix);
|
||||
|
||||
Color color = Color.green;
|
||||
color.a = 0.5f;
|
||||
Handles.color = color;
|
||||
DrawSplineData(nativeSpline,splineDataTarget.drift);
|
||||
}
|
||||
|
||||
protected override bool DrawDataPoint(
|
||||
Vector3 position,
|
||||
Vector3 tangent,
|
||||
Vector3 up,
|
||||
float inValue,
|
||||
out float outValue)
|
||||
{
|
||||
outValue = 0f;
|
||||
if(tangent == Vector3.zero)
|
||||
return false;
|
||||
|
||||
var controlID = GUIUtility.GetControlID(FocusType.Passive);
|
||||
|
||||
var handleColor = Handles.color;
|
||||
if(GUIUtility.hotControl == controlID)
|
||||
handleColor = Handles.selectedColor;
|
||||
else if(GUIUtility.hotControl == 0 && HandleUtility.nearestControl==controlID)
|
||||
handleColor = Handles.preselectionColor;
|
||||
|
||||
var right = math.normalize(math.cross(up, tangent));
|
||||
var extremity = position + inValue * (Vector3)right;
|
||||
|
||||
using(new Handles.DrawingScope(handleColor))
|
||||
{
|
||||
var size = 1.5f * k_HandleSize * HandleUtility.GetHandleSize(position);
|
||||
Handles.DrawLine(position, extremity);
|
||||
var val = Handles.Slider(
|
||||
controlID,
|
||||
extremity,
|
||||
inValue == 0 ? right : right*math.sign(inValue),
|
||||
size,
|
||||
Handles.ConeHandleCap,
|
||||
0);
|
||||
Handles.Label(extremity + 2f * size * Vector3.up, inValue.ToString());
|
||||
|
||||
if(GUIUtility.hotControl == controlID)
|
||||
{
|
||||
outValue = (val - position).magnitude * math.sign(math.dot(val - position, right));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DrawSplineData(NativeSpline spline, SplineData<float> splineData)
|
||||
{
|
||||
m_LineSegments.Clear();
|
||||
if(GUIUtility.hotControl == 0
|
||||
|| m_DriftInUse
|
||||
|| !ToolManager.IsActiveTool(this)
|
||||
|| Tools.viewToolActive)
|
||||
{
|
||||
var data = splineData.Evaluate(spline, 0, PathIndexUnit.Distance, new Interpolators.LerpFloat());
|
||||
spline.Evaluate(0, out var position, out var direction, out var upDirection);
|
||||
|
||||
var right = math.normalize(math.cross(upDirection, direction));
|
||||
var previousExtremity = (Vector3)position + data * (Vector3)right;
|
||||
|
||||
var currentOffset = m_DisplaySpace;
|
||||
while(currentOffset < spline.GetLength())
|
||||
{
|
||||
var t = currentOffset / spline.GetLength();
|
||||
spline.Evaluate(t, out position, out direction, out upDirection);
|
||||
|
||||
right = math.normalize(math.cross(upDirection, direction));
|
||||
|
||||
data = splineData.Evaluate(spline, currentOffset, PathIndexUnit.Distance, new Interpolators.LerpFloat());
|
||||
|
||||
var extremity = (Vector3)position + data * (Vector3)right;
|
||||
|
||||
m_LineSegments.Add(previousExtremity);
|
||||
m_LineSegments.Add(extremity);
|
||||
|
||||
currentOffset += m_DisplaySpace;
|
||||
previousExtremity = extremity;
|
||||
}
|
||||
|
||||
spline.Evaluate(1, out position, out direction, out upDirection);
|
||||
|
||||
right = math.normalize(math.cross(upDirection, direction));
|
||||
data = splineData.Evaluate(spline, 1f, PathIndexUnit.Normalized, new Interpolators.LerpFloat());
|
||||
|
||||
var lastExtremity = (Vector3)position + data * (Vector3)right;
|
||||
|
||||
m_LineSegments.Add(previousExtremity);
|
||||
m_LineSegments.Add(lastExtremity);
|
||||
}
|
||||
Handles.DrawLines(m_LineSegments.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a02b7ee8b850af34e906a2a59186f9ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9da031aacf1c1d649934f9377349661d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Toolbars;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Splines.Examples
|
||||
{
|
||||
[EditorToolbarElement("SpeedTiltTool/SplineDataType")]
|
||||
public class SpeedTiltDropdown : EditorToolbarDropdown
|
||||
{
|
||||
string[] m_SplineDataTypes = new []
|
||||
{
|
||||
SpeedTiltTool.SplineDataType.SpeedData.ToString(),
|
||||
SpeedTiltTool.SplineDataType.TiltData.ToString()
|
||||
};
|
||||
|
||||
public string k_Tooltip = "Select the SplineData to target for interactions.";
|
||||
|
||||
public SpeedTiltDropdown()
|
||||
{
|
||||
name = "SplineData Target Type";
|
||||
|
||||
clicked += OpenContextMenu;
|
||||
text = m_SplineDataTypes[(int)SpeedTiltTool.selectedSplineData];
|
||||
}
|
||||
|
||||
void OpenContextMenu()
|
||||
{
|
||||
var menu = new GenericMenu();
|
||||
for(int i = 0; i< m_SplineDataTypes.Length; i++)
|
||||
{
|
||||
var index = i;
|
||||
var component = m_SplineDataTypes[i];
|
||||
menu.AddItem(new GUIContent(component, k_Tooltip), text == component,
|
||||
() => SetSelectedComponent(index));
|
||||
}
|
||||
menu.DropDown(worldBound);
|
||||
}
|
||||
|
||||
void SetSelectedComponent(int selectedIndex)
|
||||
{
|
||||
text = m_SplineDataTypes[selectedIndex];
|
||||
SpeedTiltTool.selectedSplineData = (SpeedTiltTool.SplineDataType)selectedIndex;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d4c650b6f99c0d149be6ca04cbb10e7e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,102 @@
|
|||
using UnityEditor;
|
||||
using UnityEditor.Splines;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Splines;
|
||||
using Unity.Mathematics;
|
||||
using UnityEditor.EditorTools;
|
||||
|
||||
namespace Unity.Splines.Examples
|
||||
{
|
||||
[EditorTool("LookAtPoint Tool", typeof(PointSplineData))]
|
||||
public class LookAtTool : SplineDataToolBase<float2>, IDrawSelectedHandles
|
||||
{
|
||||
GUIContent m_IconContent;
|
||||
public override GUIContent toolbarIcon => m_IconContent;
|
||||
|
||||
bool m_DisableHandles;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_IconContent = new GUIContent()
|
||||
{
|
||||
image = Resources.Load<Texture2D>("Icons/LookAtTool"),
|
||||
text = "LookAt Tool",
|
||||
tooltip = "Adjust the LookAt DataPoint along the spline."
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnToolGUI(EditorWindow window)
|
||||
{
|
||||
var splineDataTarget = target as PointSplineData;
|
||||
if(splineDataTarget == null || splineDataTarget.container == null)
|
||||
return;
|
||||
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.container.Spline, splineDataTarget.container.transform.localToWorldMatrix);
|
||||
|
||||
Handles.color = Color.yellow;
|
||||
m_DisableHandles = false;
|
||||
|
||||
Undo.RecordObject(splineDataTarget,"Modifying LookAt SplineData");
|
||||
|
||||
//User defined : Handles to manipulate LookAtPoint data
|
||||
DrawDataPoints(nativeSpline, splineDataTarget.points);
|
||||
|
||||
//Using the out-of the box behaviour to manipulate SplineData indexes
|
||||
nativeSpline.DataPointHandles(splineDataTarget.points);
|
||||
}
|
||||
|
||||
public void OnDrawHandles()
|
||||
{
|
||||
var splineDataTarget = target as PointSplineData;
|
||||
if(ToolManager.IsActiveTool(this) || splineDataTarget.container == null)
|
||||
return;
|
||||
|
||||
if(Event.current.type != EventType.Repaint)
|
||||
return;
|
||||
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.container.Spline, splineDataTarget.container.transform.localToWorldMatrix);
|
||||
|
||||
Color color = Color.yellow;
|
||||
color.a = 0.5f;
|
||||
Handles.color = color;
|
||||
|
||||
m_DisableHandles = true;
|
||||
DrawDataPoints(nativeSpline,splineDataTarget.points);
|
||||
}
|
||||
|
||||
protected override bool DrawDataPoint(
|
||||
Vector3 position,
|
||||
Vector3 tangent,
|
||||
Vector3 up,
|
||||
float2 inValue,
|
||||
out float2 outValue)
|
||||
{
|
||||
var controlID = m_DisableHandles ? -1 : GUIUtility.GetControlID(FocusType.Passive);
|
||||
outValue = float2.zero;
|
||||
var handleColor = Handles.color;
|
||||
if(GUIUtility.hotControl == 0
|
||||
&& HandleUtility.nearestControl!= -1
|
||||
&& HandleUtility.nearestControl == controlID)
|
||||
handleColor = Handles.preselectionColor;
|
||||
|
||||
var pointValue = new float3(inValue.x, 0f, inValue.y);
|
||||
|
||||
var size = k_HandleSize * HandleUtility.GetHandleSize(pointValue);
|
||||
|
||||
using (new Handles.DrawingScope(handleColor))
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Handles.DrawLine(position, pointValue);
|
||||
|
||||
var newPointValue = (float3)Handles.Slider2D(controlID, pointValue, -Vector3.up, Vector3.right, Vector3.forward, size, Handles.ConeHandleCap, Vector2.zero, true);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
var delta = newPointValue - pointValue;
|
||||
outValue = inValue + new float2(delta.x, delta.z);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e81ed8fed864d88408649c082a9924bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,406 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Mathematics;
|
||||
using UnityEditor;
|
||||
using UnityEditor.EditorTools;
|
||||
using UnityEditor.Splines;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Splines;
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
using UnityEditor.Overlays;
|
||||
#else
|
||||
using System.Reflection;
|
||||
using UnityEditor.Toolbars;
|
||||
using UnityEngine.UIElements;
|
||||
#endif
|
||||
|
||||
using Interpolators = UnityEngine.Splines.Interpolators;
|
||||
|
||||
namespace Unity.Splines.Examples
|
||||
{
|
||||
[CustomEditor(typeof(SpeedTiltTool))]
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
class SplineDataPointToolSettings : UnityEditor.Editor, ICreateToolbar
|
||||
#else
|
||||
class SplineDataPointToolSettings : UnityEditor.Editor
|
||||
#endif
|
||||
{
|
||||
public virtual IEnumerable<string> toolbarElements
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return "Tool Settings/Pivot Mode";
|
||||
yield return "Tool Settings/Pivot Rotation";
|
||||
yield return "SpeedTiltTool/SplineDataType";
|
||||
}
|
||||
}
|
||||
|
||||
#if !UNITY_2022_1_OR_NEWER
|
||||
const string k_ElementClassName = "unity-editor-toolbar-element";
|
||||
const string k_StyleSheetsPath = "StyleSheets/Toolbars/";
|
||||
|
||||
static VisualElement CreateToolbar()
|
||||
{
|
||||
var target = new VisualElement();
|
||||
var path = k_StyleSheetsPath + "EditorToolbar";
|
||||
|
||||
var common = EditorGUIUtility.Load($"{path}Common.uss") as StyleSheet;
|
||||
if (common != null)
|
||||
target.styleSheets.Add(common);
|
||||
|
||||
var themeSpecificName = EditorGUIUtility.isProSkin ? "Dark" : "Light";
|
||||
var themeSpecific = EditorGUIUtility.Load($"{path}{themeSpecificName}.uss") as StyleSheet;
|
||||
if (themeSpecific != null)
|
||||
target.styleSheets.Add(themeSpecific);
|
||||
|
||||
target.AddToClassList("unity-toolbar-overlay");
|
||||
target.style.flexDirection = FlexDirection.Row;
|
||||
return target;
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
var root = CreateToolbar();
|
||||
|
||||
var elements = TypeCache.GetTypesWithAttribute(typeof(EditorToolbarElementAttribute));
|
||||
|
||||
foreach (var element in toolbarElements)
|
||||
{
|
||||
var type = elements.FirstOrDefault(x =>
|
||||
{
|
||||
var attrib = x.GetCustomAttribute<EditorToolbarElementAttribute>();
|
||||
return attrib != null && attrib.id == element;
|
||||
});
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
const BindingFlags flags = BindingFlags.Instance |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.NonPublic |
|
||||
BindingFlags.CreateInstance;
|
||||
|
||||
var ve = (VisualElement)Activator.CreateInstance(type, flags, null, null, null, null);
|
||||
ve.AddToClassList(k_ElementClassName);
|
||||
root.Add(ve);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Failed creating toolbar element from ID \"{element}\".\n{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorToolbarUtility.SetupChildrenAsButtonStrip(root);
|
||||
|
||||
return root;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[EditorTool("Speed & Tilt Tool", typeof(AnimateCarAlongSpline))]
|
||||
public class SpeedTiltTool : EditorTool, IDrawSelectedHandles
|
||||
{
|
||||
internal enum SplineDataType
|
||||
{
|
||||
SpeedData,
|
||||
TiltData
|
||||
};
|
||||
|
||||
//Speed handles parameters
|
||||
const float k_SpeedScaleFactor = 10f;
|
||||
const float k_DisplaySpace = 0.5f;
|
||||
|
||||
//Tilt handles parameters
|
||||
Quaternion m_StartingRotation;
|
||||
|
||||
const float k_HandleSize = 0.15f;
|
||||
|
||||
Color[] m_HandlesColors = {Color.red, new (1f,0.6f,0f)};
|
||||
List<Vector3> m_LineSegments = new List<Vector3>();
|
||||
static SplineDataType s_SelectedSplineData = SplineDataType.SpeedData;
|
||||
internal static SplineDataType selectedSplineData
|
||||
{
|
||||
get => s_SelectedSplineData;
|
||||
set => s_SelectedSplineData = value;
|
||||
}
|
||||
|
||||
GUIContent m_IconContent;
|
||||
public override GUIContent toolbarIcon => m_IconContent;
|
||||
|
||||
bool m_DisableHandles;
|
||||
bool m_SpeedInUse;
|
||||
bool m_TiltInUse;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_IconContent = new GUIContent()
|
||||
{
|
||||
image = Resources.Load<Texture2D>("Icons/SpeedTiltTool"),
|
||||
text = "Speed & Tilt Tool",
|
||||
tooltip = "Adjust the vehicle speed and tilt DataPoints along the spline."
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnToolGUI(EditorWindow window)
|
||||
{
|
||||
var splineDataTarget = target as AnimateCarAlongSpline;
|
||||
if(splineDataTarget == null || splineDataTarget.splineContainer == null)
|
||||
return;
|
||||
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.splineContainer.Spline, splineDataTarget.splineContainer.transform.localToWorldMatrix);
|
||||
|
||||
Undo.RecordObject(splineDataTarget, "Modifying Speed and Tilt SplineData");
|
||||
|
||||
m_DisableHandles = false;
|
||||
|
||||
//Speed handles section
|
||||
Handles.color = m_HandlesColors[(int)SplineDataType.SpeedData];
|
||||
//User defined : Handles to manipulate Speed data
|
||||
m_SpeedInUse = DrawSpeedDataPoints(nativeSpline, splineDataTarget.speed, splineDataTarget.m_MaxSpeed, true);
|
||||
//Use defined : Draws a line along the whole Speed SplineData
|
||||
DrawSpeedSplineData(nativeSpline, splineDataTarget.speed);
|
||||
|
||||
//Tilt handles section
|
||||
Handles.color = m_HandlesColors[(int)SplineDataType.TiltData];
|
||||
//User defined : Handles to manipulate Tilt data
|
||||
m_TiltInUse = DrawTiltDataPoints(nativeSpline, splineDataTarget.tilt);
|
||||
//Use defined : Draws a line along the whole Tilt SplineData
|
||||
DrawTiltSplineData(nativeSpline, splineDataTarget.tilt);
|
||||
|
||||
//Draw DataPoint default Manipulation handles
|
||||
Handles.color = m_HandlesColors[(int)s_SelectedSplineData];
|
||||
if(s_SelectedSplineData == SplineDataType.SpeedData)
|
||||
nativeSpline.DataPointHandles(splineDataTarget.speed);
|
||||
else
|
||||
nativeSpline.DataPointHandles(splineDataTarget.tilt);
|
||||
}
|
||||
|
||||
public void OnDrawHandles()
|
||||
{
|
||||
var splineDataTarget = target as AnimateCarAlongSpline;
|
||||
if(ToolManager.IsActiveTool(this) || splineDataTarget.splineContainer == null)
|
||||
return;
|
||||
|
||||
if(Event.current.type != EventType.Repaint)
|
||||
return;
|
||||
|
||||
m_DisableHandles = true;
|
||||
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.splineContainer.Spline, splineDataTarget.splineContainer.transform.localToWorldMatrix);
|
||||
Color color = m_HandlesColors[(int)SplineDataType.SpeedData];
|
||||
color.a = 0.5f;
|
||||
Handles.color = color;
|
||||
DrawSpeedDataPoints(nativeSpline, splineDataTarget.speed, splineDataTarget.m_MaxSpeed, false);
|
||||
DrawSpeedSplineData(nativeSpline, splineDataTarget.speed);
|
||||
|
||||
color = m_HandlesColors[(int)SplineDataType.TiltData];
|
||||
color.a = 0.5f;
|
||||
Handles.color = color;
|
||||
DrawTiltSplineData(nativeSpline,splineDataTarget.tilt);
|
||||
}
|
||||
|
||||
bool DrawSpeedDataPoints(NativeSpline spline, SplineData<float> speedSplineData, float maxSpeed, bool drawLabel)
|
||||
{
|
||||
var inUse = false;
|
||||
for(int dataFrameIndex = 0; dataFrameIndex < speedSplineData.Count; dataFrameIndex++)
|
||||
{
|
||||
var dataPoint = speedSplineData[dataFrameIndex];
|
||||
|
||||
var normalizedT = SplineUtility.GetNormalizedInterpolation(spline, dataPoint.Index, speedSplineData.PathIndexUnit);
|
||||
var position = spline.EvaluatePosition(normalizedT);
|
||||
|
||||
var speedValue = dataPoint.Value;
|
||||
if(speedValue > maxSpeed)
|
||||
{
|
||||
speedValue = maxSpeed;
|
||||
dataPoint.Value = maxSpeed;
|
||||
speedSplineData[dataFrameIndex] = dataPoint;
|
||||
}
|
||||
|
||||
var id = m_DisableHandles ? -1 : GUIUtility.GetControlID(FocusType.Passive);
|
||||
if(DrawSpeedDataPoint(id, position, speedValue, drawLabel, out var result))
|
||||
{
|
||||
dataPoint.Value = Mathf.Clamp(result, 0.01f, maxSpeed);
|
||||
speedSplineData[dataFrameIndex] = dataPoint;
|
||||
inUse = true;
|
||||
}
|
||||
}
|
||||
|
||||
return inUse;
|
||||
}
|
||||
|
||||
bool DrawSpeedDataPoint(
|
||||
int controlID,
|
||||
Vector3 position,
|
||||
float inValue,
|
||||
bool drawLabel,
|
||||
out float outValue)
|
||||
{
|
||||
outValue = 0f;
|
||||
var handleColor = Handles.color;
|
||||
if(GUIUtility.hotControl == controlID)
|
||||
handleColor = Handles.selectedColor;
|
||||
else if(GUIUtility.hotControl == 0 && HandleUtility.nearestControl==controlID)
|
||||
handleColor = Handles.preselectionColor;
|
||||
|
||||
var extremity = position + (inValue / k_SpeedScaleFactor) * Vector3.up;
|
||||
using(new Handles.DrawingScope(handleColor))
|
||||
{
|
||||
var size = k_HandleSize * HandleUtility.GetHandleSize(position);
|
||||
Handles.DrawLine(position, extremity);
|
||||
var val = Handles.Slider(controlID, extremity, Vector3.up, size, Handles.SphereHandleCap, 0);
|
||||
if(drawLabel)
|
||||
Handles.Label(extremity + 2f * size * Vector3.up, inValue.ToString());
|
||||
|
||||
if(GUIUtility.hotControl == controlID)
|
||||
{
|
||||
outValue = k_SpeedScaleFactor * (val - position).magnitude * math.sign(math.dot(val - position, Vector3.up));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DrawTiltDataPoints(NativeSpline spline, SplineData<float3> tiltSplineData)
|
||||
{
|
||||
var inUse = false;
|
||||
for(int dataFrameIndex = 0; dataFrameIndex < tiltSplineData.Count; dataFrameIndex++)
|
||||
{
|
||||
var dataPoint = tiltSplineData[dataFrameIndex];
|
||||
|
||||
var normalizedT = SplineUtility.GetNormalizedInterpolation(spline, dataPoint.Index, tiltSplineData.PathIndexUnit);
|
||||
spline.Evaluate(normalizedT, out var position, out var tangent, out var up);
|
||||
|
||||
var id = m_DisableHandles ? -1 : GUIUtility.GetControlID(FocusType.Passive);
|
||||
if(DrawTiltDataPoint(id, position, tangent, up, dataPoint.Value, out var result))
|
||||
{
|
||||
dataPoint.Value = result;
|
||||
tiltSplineData[dataFrameIndex] = dataPoint;
|
||||
inUse = true;
|
||||
}
|
||||
}
|
||||
return inUse;
|
||||
}
|
||||
|
||||
bool DrawTiltDataPoint(
|
||||
int controlID,
|
||||
Vector3 position,
|
||||
Vector3 tangent,
|
||||
Vector3 up,
|
||||
float3 inValue,
|
||||
out float3 outValue)
|
||||
{
|
||||
outValue = float3.zero;
|
||||
if(tangent == Vector3.zero)
|
||||
return false;
|
||||
|
||||
Matrix4x4 localMatrix = Matrix4x4.identity;
|
||||
localMatrix.SetTRS(position, Quaternion.LookRotation(tangent, up), Vector3.one);
|
||||
|
||||
var matrix = Handles.matrix * localMatrix;
|
||||
using(new Handles.DrawingScope(matrix))
|
||||
{
|
||||
var dataPointRotation = Quaternion.FromToRotation(Vector3.up, inValue);
|
||||
|
||||
if(GUIUtility.hotControl == 0)
|
||||
m_StartingRotation = dataPointRotation;
|
||||
|
||||
var color = Handles.color;
|
||||
if(!m_TiltInUse)
|
||||
color.a = 0.33f;
|
||||
|
||||
using(new Handles.DrawingScope(color))
|
||||
Handles.ArrowHandleCap(-1, Vector3.zero, Quaternion.FromToRotation(Vector3.forward, inValue), 1f, EventType.Repaint);
|
||||
|
||||
var rotation = Handles.Disc(controlID, dataPointRotation, Vector3.zero, Vector3.forward, 1, false, 0);
|
||||
|
||||
if(GUIUtility.hotControl == controlID)
|
||||
{
|
||||
var deltaRot = Quaternion.Inverse(m_StartingRotation) * rotation;
|
||||
outValue = deltaRot * m_StartingRotation * Vector3.up;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DrawSpeedSplineData(NativeSpline spline, SplineData<float> splineData)
|
||||
{
|
||||
m_LineSegments.Clear();
|
||||
if(GUIUtility.hotControl == 0
|
||||
|| m_SpeedInUse
|
||||
|| !ToolManager.IsActiveTool(this)
|
||||
|| Tools.viewToolActive)
|
||||
{
|
||||
var data = splineData.Evaluate(spline, 0, PathIndexUnit.Distance, new Interpolators.LerpFloat());
|
||||
var position = spline.EvaluatePosition(0);
|
||||
var previousExtremity = (Vector3)position + ( data / k_SpeedScaleFactor ) * Vector3.up;
|
||||
|
||||
var currentOffset = k_DisplaySpace;
|
||||
while(currentOffset < spline.GetLength())
|
||||
{
|
||||
var t = currentOffset / spline.GetLength();
|
||||
position = spline.EvaluatePosition(t);
|
||||
data = splineData.Evaluate(spline, currentOffset, PathIndexUnit.Distance, new Interpolators.LerpFloat());
|
||||
|
||||
var extremity = (Vector3)position + ( data / k_SpeedScaleFactor ) * Vector3.up;
|
||||
|
||||
m_LineSegments.Add(previousExtremity);
|
||||
m_LineSegments.Add(extremity);
|
||||
|
||||
currentOffset += k_DisplaySpace;
|
||||
previousExtremity = extremity;
|
||||
}
|
||||
|
||||
position = spline.EvaluatePosition(1);
|
||||
data = splineData.Evaluate(spline, spline.GetLength(), PathIndexUnit.Distance, new Interpolators.LerpFloat());
|
||||
|
||||
var lastExtremity = (Vector3)position + ( data / k_SpeedScaleFactor ) * Vector3.up;
|
||||
|
||||
m_LineSegments.Add(previousExtremity);
|
||||
m_LineSegments.Add(lastExtremity);
|
||||
}
|
||||
Handles.DrawLines(m_LineSegments.ToArray());
|
||||
}
|
||||
|
||||
void DrawTiltSplineData(NativeSpline spline, SplineData<float3> splineData)
|
||||
{
|
||||
m_LineSegments.Clear();
|
||||
if(GUIUtility.hotControl == 0
|
||||
|| m_TiltInUse
|
||||
|| !ToolManager.IsActiveTool(this)
|
||||
|| Tools.viewToolActive)
|
||||
{
|
||||
var currentOffset = k_DisplaySpace;
|
||||
while(currentOffset < spline.GetLength())
|
||||
{
|
||||
var t = currentOffset / spline.GetLength();
|
||||
spline.Evaluate(t, out float3 position, out float3 direction, out float3 up);
|
||||
var data = splineData.Evaluate(spline, t, PathIndexUnit.Normalized,
|
||||
new Interpolators.LerpFloat3());
|
||||
|
||||
Matrix4x4 localMatrix = Matrix4x4.identity;
|
||||
localMatrix.SetTRS(position, Quaternion.LookRotation(direction, up), Vector3.one);
|
||||
m_LineSegments.Add(localMatrix.GetPosition());
|
||||
m_LineSegments.Add(localMatrix.MultiplyPoint(math.normalize(data)));
|
||||
|
||||
currentOffset += k_DisplaySpace;
|
||||
}
|
||||
}
|
||||
|
||||
var color = Handles.color;
|
||||
if(!m_TiltInUse)
|
||||
color.a = 0.33f;
|
||||
|
||||
using(new Handles.DrawingScope(color))
|
||||
Handles.DrawLines(m_LineSegments.ToArray());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 13191b70b1bbf4348a215f42c3e852cf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,47 @@
|
|||
using UnityEditor.EditorTools;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Splines;
|
||||
|
||||
namespace Unity.Splines.Examples
|
||||
{
|
||||
public abstract class SplineDataToolBase<DataType> : EditorTool
|
||||
{
|
||||
protected const float k_HandleSize = 0.15f;
|
||||
|
||||
protected bool DrawDataPoints(ISpline spline, SplineData<DataType> splineData)
|
||||
{
|
||||
var inUse = false;
|
||||
for(int dataFrameIndex = 0; dataFrameIndex < splineData.Count; dataFrameIndex++)
|
||||
{
|
||||
var dataPoint = splineData[dataFrameIndex];
|
||||
|
||||
var normalizedT = SplineUtility.GetNormalizedInterpolation(spline, dataPoint.Index, splineData.PathIndexUnit);
|
||||
spline.Evaluate(normalizedT, out var position, out var tangent, out var up);
|
||||
|
||||
if(DrawDataPoint(position, tangent, up, dataPoint.Value, out var result))
|
||||
{
|
||||
dataPoint.Value = result;
|
||||
splineData[dataFrameIndex] = dataPoint;
|
||||
inUse = true;
|
||||
}
|
||||
}
|
||||
return inUse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User defined method, for simplicity here, all the SplineData Tools have to override the same DrawDataPoint method for consistency between tools
|
||||
/// </summary>
|
||||
/// <param name="position"></param>
|
||||
/// <param name="tangent"></param>
|
||||
/// <param name="up"></param>
|
||||
/// <param name="inValue"></param>
|
||||
/// <param name="outValue"></param>
|
||||
/// <returns>True if the dataPoint is manipulated, else false.</returns>
|
||||
protected abstract bool DrawDataPoint(
|
||||
Vector3 position,
|
||||
Vector3 tangent,
|
||||
Vector3 up,
|
||||
DataType inValue,
|
||||
out DataType outValue);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: af7617c1ec3b5f94fb17427d7465e15b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,125 @@
|
|||
using Unity.Mathematics;
|
||||
using UnityEditor;
|
||||
using UnityEditor.EditorTools;
|
||||
using UnityEditor.Splines;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Splines;
|
||||
|
||||
namespace Unity.Splines.Examples
|
||||
{
|
||||
[EditorTool("Width Tool", typeof(WidthSplineData))]
|
||||
public class WidthTool : SplineDataToolBase<float>, IDrawSelectedHandles
|
||||
{
|
||||
GUIContent m_IconContent;
|
||||
public override GUIContent toolbarIcon => m_IconContent;
|
||||
|
||||
bool m_DisableHandles = false;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_IconContent = new GUIContent()
|
||||
{
|
||||
image = Resources.Load<Texture2D>("Icons/WidthTool"),
|
||||
text = "Width Tool",
|
||||
tooltip = "Adjust the width of the created road mesh."
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnToolGUI(EditorWindow window)
|
||||
{
|
||||
var splineDataTarget = target as WidthSplineData;
|
||||
if(splineDataTarget == null || splineDataTarget.container == null)
|
||||
return;
|
||||
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.container.Spline, splineDataTarget.container.transform.localToWorldMatrix);
|
||||
|
||||
Undo.RecordObject(splineDataTarget,"Modifying Width SplineData");
|
||||
|
||||
Handles.color = Color.blue;
|
||||
m_DisableHandles = false;
|
||||
|
||||
//User defined handles to manipulate width
|
||||
DrawDataPoints(nativeSpline, splineDataTarget.width);
|
||||
|
||||
//Using the out-of the box behaviour to manipulate indexes
|
||||
nativeSpline.DataPointHandles(splineDataTarget.width);
|
||||
}
|
||||
|
||||
public void OnDrawHandles()
|
||||
{
|
||||
var splineDataTarget = target as WidthSplineData;
|
||||
if(ToolManager.IsActiveTool(this) || splineDataTarget.container == null)
|
||||
return;
|
||||
|
||||
var nativeSpline = new NativeSpline(splineDataTarget.container.Spline, splineDataTarget.container.transform.localToWorldMatrix);
|
||||
|
||||
Color color = Color.blue;
|
||||
color.a = 0.5f;
|
||||
Handles.color = color;
|
||||
m_DisableHandles = true;
|
||||
DrawDataPoints(nativeSpline,splineDataTarget.width);
|
||||
}
|
||||
|
||||
protected override bool DrawDataPoint(
|
||||
Vector3 position,
|
||||
Vector3 tangent,
|
||||
Vector3 up,
|
||||
float inValue,
|
||||
out float outValue)
|
||||
{
|
||||
int id1 = m_DisableHandles ? -1 : GUIUtility.GetControlID(FocusType.Passive);
|
||||
int id2 = m_DisableHandles ? -1 : GUIUtility.GetControlID(FocusType.Passive);
|
||||
|
||||
outValue = 0f;
|
||||
if(tangent == Vector3.zero)
|
||||
return false;
|
||||
|
||||
if(Event.current.type == EventType.MouseUp
|
||||
&& Event.current.button != 0
|
||||
&& ( GUIUtility.hotControl == id1 || GUIUtility.hotControl == id2 ))
|
||||
{
|
||||
Event.current.Use();
|
||||
return false;
|
||||
}
|
||||
|
||||
var handleColor = Handles.color;
|
||||
if(GUIUtility.hotControl == id1 || GUIUtility.hotControl == id2)
|
||||
handleColor = Handles.selectedColor;
|
||||
else if(GUIUtility.hotControl == 0 && (HandleUtility.nearestControl==id1 || HandleUtility.nearestControl==id2))
|
||||
handleColor = Handles.preselectionColor;
|
||||
|
||||
var normalDirection = math.normalize(math.cross(tangent, up));
|
||||
|
||||
var extremity1 = position - inValue * (Vector3)normalDirection;
|
||||
var extremity2 = position + inValue * (Vector3)normalDirection;
|
||||
Vector3 val1, val2;
|
||||
using(new Handles.DrawingScope(handleColor))
|
||||
{
|
||||
Handles.DrawLine(extremity1, extremity2);
|
||||
val1 = Handles.Slider(id1, extremity1, normalDirection,
|
||||
k_HandleSize * .5f * HandleUtility.GetHandleSize(position), CustomHandleCap, 0);
|
||||
val2 = Handles.Slider(id2, extremity2, normalDirection,
|
||||
k_HandleSize * .5f * HandleUtility.GetHandleSize(position), CustomHandleCap, 0);
|
||||
}
|
||||
|
||||
if(GUIUtility.hotControl == id1 && math.abs(( val1 - extremity1 ).magnitude) > 0)
|
||||
{
|
||||
outValue = math.abs(( val1 - position ).magnitude);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(GUIUtility.hotControl == id2 && math.abs(( val2 - extremity2 ).magnitude) > 0)
|
||||
{
|
||||
outValue = math.abs(( val2 - position ).magnitude);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void CustomHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)
|
||||
{
|
||||
Handles.CubeHandleCap(controlID, position, rotation, size, m_DisableHandles ? EventType.Repaint : eventType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 161dbe244d397fa478a292687ea673e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue