推进度!

This commit is contained in:
SoulliesOfficial
2025-11-25 21:49:03 -05:00
parent f0c06f0337
commit ad4948207e
1068 changed files with 418853 additions and 1047 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ba77a8819c7838d44b8df7356111fea2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
// using UnityEditor;
// using UnityEditor.PackageManager;
// using UnityEditor.PackageManager.Requests;
// using UnityEngine;
//
// namespace UISplineRendererEditor
// {
// internal static class DependencyResolver
// {
// static AddRequest splineRequest;
// static AddRequest collectionsRequest;
// static AddRequest mathematicsRequest;
// static AddRequest burstRequest;
// [InitializeOnLoadMethod]
// static void Install()
// {
// bool requested = false;
// #if !ENABLE_SPLINES
// splineRequest = Client.Add("com.unity.splines");
// requested = true;
// #endif
// #if !ENABLE_COLLECTIONS
// collectionsRequest = Client.Add("com.unity.collections");
// requested = true;
// #endif
// #if !ENABLE_MATHEMATICS
// mathematicsRequest = Client.Add("com.unity.mathematics");
// requested = true;
// #endif
// #if !ENABLE_BURST
// burstRequest = Client.Add("com.unity.burst");
// requested = true;
// #endif
// if(requested) EditorApplication.update += Progress;
// }
//
// static void Progress()
// {
// if(splineRequest != null) PrintResult(splineRequest);
// if(collectionsRequest != null) PrintResult(collectionsRequest);
// if(mathematicsRequest != null) PrintResult(mathematicsRequest);
// if(burstRequest != null) PrintResult(burstRequest);
//
// EditorApplication.update -= Progress;
// }
//
// static void PrintResult(AddRequest request)
// {
// if (request.IsCompleted)
// {
// if (request.Status == StatusCode.Success)
// Debug.Log("Installed: " + request.Result.packageId);
// else if (request.Status >= StatusCode.Failure)
// Debug.Log(request.Error.message);
// }
// }
// }
// }

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4b66ad526b1cb0c49b3364a6b4884ccd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: c3499b63a6dc8424f8ca9c03466edd59
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
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
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,76 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
<uie:ObjectField label="Spline Container" binding-path="splineContainer" name="splineContainer" type="UnityEngine.Splines.SplineContainer, Unity.Splines" />
<uie:ObjectField label="Material" binding-path="m_Material" name="material" type="UnityEngine.Material, UnityEngine.CoreModule" />
<ui:Toggle label="Recursive Material" binding-path="_recursiveMaterial" name="recursivceMaterial" tooltip="If true, this renderer&apos;s material value will also be applied to startImages and endImages." style="padding-left: 20px;" />
<uie:ColorField label="Color" value="#FFFFFFFF" name="color" binding-path="m_Color" />
<uie:GradientField label="Color Gradient" name="colorGradient" binding-path="_colorGradient" />
<ui:Toggle label="Recursive Color" binding-path="_recursiveColor" name="recursivceColor" tooltip="If true, this renderer&apos;s color will also be applied to startImages and endImages." style="padding-left: 20px;" />
<ui:Toggle label="Raycast Target" binding-path="m_RaycastTarget" name="raycastTarget" />
<ui:Foldout text="Raycast Padding" name="raycastPaddingFoldout" value="false">
<ui:Vector4Field binding-path="m_RaycastPadding" name="raycastPadding" />
</ui:Foldout>
<ui:Toggle label="Maskable" binding-path="m_Maskable" name="maskable" />
<ui:VisualElement style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); height: 20px; max-height: 20px; min-height: 20px;" />
<ui:FloatField label="Width" value="6" binding-path="_width" name="width" tooltip="Width of this spline renderer" is-delayed="false" />
<uie:CurveField label="Width Curve" binding-path="_widthCurve" tooltip="Multiplier for the width of this spline. [0..1]" name="widthCurve" />
<ui:VisualElement name="lineTextureArea" style="background-color: rgba(0, 0, 0, 0);">
<ui:Toggle label="Keep Zero Z" binding-path="_keepZeroZ" name="keepZeroZ" tooltip="Keep all z position and transform.localPosition.z as 0. This keep the spline flatten on canvas." />
<ui:Toggle label="Keep Billboard" binding-path="_keepBillboard" name="keepBillboard" tooltip="Keep all normals of the vertices pointing towards the screen direction. This ensures that the spline is rendered as a billboard, even if you set odd rotations to knots." />
<ui:VisualElement style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); height: 20px; max-height: 20px; min-height: 20px;" />
<ui:VisualElement name="presetButtons" style="flex-grow: 1; flex-direction: row; flex-shrink: 0;">
<ui:Label text="Line Texture Preset" style="-unity-text-align: middle-left; align-self: stretch;" />
<ui:Button text="Default (Anti-Alised)" display-tooltip-when-elided="true" name="default" tooltip="Default anti-aliased texture. This is simple trick using a slightly blurred image." style="height: 30px; max-height: 30px; min-height: 30px; flex-grow: 1;" />
<ui:Button text="UV Test" display-tooltip-when-elided="true" name="uvTest" tooltip="Cheker texture with numbers. This is useful if you want to see how UVs are applied." style="height: 30px; max-height: 30px; min-height: 30px; flex-grow: 1;" />
<ui:Button text="Custom" display-tooltip-when-elided="true" name="custom" tooltip="Custom texture. If you set the texture property via script, it&apos;s automatically changed." style="height: 30px; max-height: 30px; min-height: 30px; flex-grow: 1;" />
</ui:VisualElement>
<uie:ObjectField label="Texture" binding-path="m_Texture" name="texture" type="UnityEngine.Texture, UnityEngine.CoreModule" style="padding-left: 20px;" />
<ui:SliderInt picking-mode="Ignore" label="Resolution" value="2" high-value="10" low-value="1" name="resolution" binding-path="_resolution" show-input-field="true" />
<ui:Label tabindex="-1" text="Vertex Count" display-tooltip-when-elided="true" name="vertexCount" tooltip="Unity vertex limit is 65,000. keep vertex count lower than this." style="padding-left: 20px; -unity-text-align: middle-left;" />
<ui:MinMaxSlider picking-mode="Ignore" label="Clip Range" min-value="0" max-value="1" low-limit="0" high-limit="1" name="clipRange" binding-path="_clipRange" />
<ui:EnumField label="UV Mode" type="UI_Spline_Renderer.UVMode, UISplineRenderer" binding-path="_uvMode" name="uvMode" />
</ui:VisualElement>
<ui:VisualElement name="startImageArea" style="flex-grow: 1; background-color: rgba(0, 0, 0, 0);">
<ui:VisualElement style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); height: 20px; max-height: 20px; min-height: 20px;" />
<ui:Vector2Field label="UV Multiplier" binding-path="_uvMultiplier" name="uvMultiplier" x="1" y="1" />
<ui:Vector2Field label="UV Offset" binding-path="_uvOffset" name="uvOffset" tooltip="Line textures UV offset. You can make simple texture animations using this property. " />
<ui:VisualElement name="presetButtons" style="flex-grow: 1; flex-shrink: 0; flex-direction: row;">
<ui:Label text="Start Image Preset" style="-unity-text-align: middle-left; align-self: stretch;" />
<ui:VisualElement name="vert" style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); justify-content: space-around;">
<ui:VisualElement name="hor1" style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); flex-direction: row; height: 30px; max-height: 30px; min-height: 30px;">
<ui:Button text="None" display-tooltip-when-elided="true" name="none" style="flex-grow: 1;" />
<ui:Button text="Triangle" display-tooltip-when-elided="true" name="triangle" style="flex-grow: 1;" />
<ui:Button text="Arrow" display-tooltip-when-elided="true" name="arrow" style="flex-grow: 1;" />
</ui:VisualElement>
<ui:VisualElement name="hor2" style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); flex-direction: row; height: 30px; max-height: 30px; min-height: 30px;">
<ui:Button text="Empty Circle" display-tooltip-when-elided="true" name="emptyCircle" style="flex-grow: 1;" />
<ui:Button text="Filled Circle" display-tooltip-when-elided="true" name="filledCircle" style="flex-grow: 1;" />
<ui:Button text="Custom" display-tooltip-when-elided="true" name="custom" style="flex-grow: 1;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
<uie:ObjectField label="Start Image Sprite" binding-path="_startImageSprite" name="sprite" type="UnityEngine.Sprite, UnityEngine.CoreModule" style="padding-left: 20px;" />
<ui:FloatField label="Start Image Size" value="32" binding-path="_startImageSize" name="size" style="padding-left: 20px;" />
<ui:FloatField label="Start Image Offset" value="0" binding-path="_startImageOffset" name="offset" tooltip="Offset from first point of spline. If the value is greater than 0, it moves along the spline. Otherwise, it moves backward relative to current rotation." style="padding-left: 20px;" />
</ui:VisualElement>
<ui:VisualElement name="endImageArea" style="flex-grow: 1; background-color: rgba(0, 0, 0, 0);">
<ui:VisualElement style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); height: 20px; max-height: 20px; min-height: 20px;" />
<ui:VisualElement name="presetButtons" style="flex-grow: 1; flex-shrink: 0; flex-direction: row;">
<ui:Label text="End Image Preset" style="-unity-text-align: middle-left; align-self: stretch;" />
<ui:VisualElement name="vert" style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); justify-content: space-around;">
<ui:VisualElement name="hor1" style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); flex-direction: row; height: 30px; max-height: 30px; min-height: 30px;">
<ui:Button text="None" display-tooltip-when-elided="true" name="none" style="flex-grow: 1;" />
<ui:Button text="Triangle" display-tooltip-when-elided="true" name="triangle" style="flex-grow: 1;" />
<ui:Button text="Arrow" display-tooltip-when-elided="true" name="arrow" style="flex-grow: 1;" />
</ui:VisualElement>
<ui:VisualElement name="hor2" style="flex-grow: 1; background-color: rgba(0, 0, 0, 0); flex-direction: row; height: 30px; max-height: 30px; min-height: 30px;">
<ui:Button text="Empty Circle" display-tooltip-when-elided="true" name="emptyCircle" style="flex-grow: 1;" />
<ui:Button text="Filled Circle" display-tooltip-when-elided="true" name="filledCircle" style="flex-grow: 1;" />
<ui:Button text="Custom" display-tooltip-when-elided="true" name="custom" style="flex-grow: 1;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
<uie:ObjectField label="End Image Sprite" binding-path="_endImageSprite" name="sprite" type="UnityEngine.Sprite, UnityEngine.CoreModule" style="padding-left: 20px;" />
<ui:FloatField label="End Image Size" value="32" binding-path="_endImageSize" name="size" style="padding-left: 20px;" />
<ui:FloatField label="End Image Offset" value="0" binding-path="_endImageOffset" name="offset" tooltip="Offset from last point of spline. If the value is smaller than 0, it moves along the spline. Otherwise, it moves forward relative to current rotation." style="padding-left: 20px;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3d080aacdb57b754ea02423382b3c18e
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,40 @@
{
"name": "UISplineRenderer.Editor",
"rootNamespace": "UISplineRendererEditor",
"references": [
"GUID:21d1eb854b91ade49bc69a263d12bee2",
"GUID:8f24f501fa8e1fb48a03f1d7e6d03db4"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.splines",
"expression": "",
"define": "ENABLE_SPLINES"
},
{
"name": "com.unity.collections",
"expression": "",
"define": "ENABLE_COLLECTIONS"
},
{
"name": "com.unity.mathematics",
"expression": "",
"define": "ENABLE_MATHEMATICS"
},
{
"name": "com.unity.burst",
"expression": "",
"define": "ENABLE_BURST"
}
],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ba3c2b61e54e2994595f1bd021287b42
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,583 @@
using System;
using UI_Spline_Renderer;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.Splines;
using UnityEngine.UIElements;
namespace UISplineRendererEditor
{
[CustomEditor(typeof(UISplineRenderer))]
[CanEditMultipleObjects]
public class UISplineRendererEditor : UnityEditor.Editor
{
UISplineRenderer _target;
ObjectField _splineContainerField;
ObjectField _materialField;
ObjectField _textureField;
Button _defaultLineTextureButton;
Button _uvTestLineTextureButton;
Button _customLineTextureButton;
Toggle _keepZeroZField;
Toggle _keepBillboardField;
EnumField _uvModeField;
SliderInt _resolutionSlider;
Label _vertexCountField;
ObjectField _startImageSpriteField;
FloatField _startImageSizeField;
FloatField _startImageOffsetField;
Button _noneStartImageButton;
Button _triangleStartImageButton;
Button _arrowStartImageButton;
Button _emptyCircleStartImageButton;
Button _filledCircleStartImageButton;
Button _customStartImageButton;
ObjectField _endImageSpriteField;
FloatField _endImageSizeField;
FloatField _endImageOffsetField;
Button _noneEndImageButton;
Button _triangleEndImageButton;
Button _arrowEndImageButton;
Button _emptyCircleEndImageButton;
Button _filledCircleEndImageButton;
Button _customEndImageButton;
bool _shouldUpdateStartEndImages;
UISplineRendererSettings settings => UISplineRendererSettings.Instance;
void OnEnable()
{
if (_target == null) _target = target as UISplineRenderer;
Spline.Changed += SplineChangeCallback;
SplineContainer.SplineAdded += SplineContainerChangeCallback;
SplineContainer.SplineRemoved += SplineContainerChangeCallback;
EditorApplication.update += _delayed_update_vertex_count;
void _delayed_update_vertex_count()
{
UpdateVertexCount();
EditorApplication.update -= UpdateVertexCount;
}
}
void OnDisable()
{
Spline.Changed -= SplineChangeCallback;
SplineContainer.SplineAdded -= SplineContainerChangeCallback;
SplineContainer.SplineRemoved -= SplineContainerChangeCallback;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(serializedObject.FindProperty("_splineContainer"));
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("_fitPosition"));
EditorGUI.indentLevel--;
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Material"));
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("_recursiveMaterial"));
EditorGUI.indentLevel--;
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Color"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_colorGradient"));
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("_recursiveColor"));
EditorGUI.indentLevel--;
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_RaycastTarget"));
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_RaycastPadding"));
EditorGUI.indentLevel--;
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Maskable"));
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty("_width"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_widthCurve"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_keepZeroZ"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_keepBillboard"));
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
var lineTexturePreset = EnumButtonField("Line Texture Preset", Enum.GetNames(typeof(LineTexturePreset)),
(int)_target.lineTexturePreset);
if(EditorGUI.EndChangeCheck())
{
_target.lineTexturePreset = (LineTexturePreset)lineTexturePreset;
}
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Texture"));
EditorGUI.indentLevel--;
EditorGUILayout.PropertyField(serializedObject.FindProperty("_smooth"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_roundEnds"));
EditorGUI.BeginChangeCheck();
var resolution = serializedObject.FindProperty("_resolution");
EditorGUILayout.IntSlider(resolution, 1, 20);
if (EditorGUI.EndChangeCheck())
{
_target.resolution = resolution.intValue;
}
EditorGUI.indentLevel++;
EditorGUILayout.LabelField("Vertex Count", _target.vertexCount.ToString());
EditorGUI.indentLevel--;
var clipRangeSP = serializedObject.FindProperty("_clipRange");
var clipRange = clipRangeSP.vector2Value;
EditorGUILayout.MinMaxSlider("Clip Range", ref clipRange.x, ref clipRange.y, 0, 1);
clipRangeSP.vector2Value = clipRange;
EditorGUILayout.LabelField($"min: {clipRange.x} | max: {clipRange.y}");
EditorGUILayout.PropertyField(serializedObject.FindProperty("_uvMode"));
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty("_uvMultiplier"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_uvOffset"));
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
var startImagePreset = EnumButtonField("Start Image Preset", Enum.GetNames(typeof(StartEndImagePreset)),
(int)_target.startImagePreset, 3);
if (EditorGUI.EndChangeCheck())
{
_target.startImagePreset = (StartEndImagePreset)startImagePreset;
}
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("_startImageSprite"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_startImageSize"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_startImageOffsetMode"));
if(_target.startImageOffsetMode == OffsetMode.Distance)
EditorGUILayout.PropertyField(serializedObject.FindProperty("_startImageOffset"));
else if(_target.startImageOffsetMode == OffsetMode.Normalized)
EditorGUILayout.PropertyField(serializedObject.FindProperty("_normalizedStartImageOffset"));
EditorGUI.indentLevel--;
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
var endImagePreset = EnumButtonField("End Image Preset", Enum.GetNames(typeof(StartEndImagePreset)),
(int)_target.endImagePreset, 3);
if(EditorGUI.EndChangeCheck())
{
_target.endImagePreset = (StartEndImagePreset)endImagePreset;
}
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("_endImageSprite"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_endImageSize"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("_endImageOffsetMode"));
if(_target.endImageOffsetMode == OffsetMode.Distance)
EditorGUILayout.PropertyField(serializedObject.FindProperty("_endImageOffset"));
else if(_target.endImageOffsetMode == OffsetMode.Normalized)
EditorGUILayout.PropertyField(serializedObject.FindProperty("_normalizedEndImageOffset"));
EditorGUI.indentLevel--;
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(target);
serializedObject.ApplyModifiedProperties();
_target.UpdateRaycastTargetRect();
foreach (var o in targets)
{
var renderer = o as UISplineRenderer;
renderer.UpdateStartEndImages(true);
renderer.UpdateStartEndImages(false);
}
}
}
int EnumButtonField(string label, string[] names, int selected, int lineChange = 0)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Label(label);
EditorGUILayout.BeginVertical();
EditorGUILayout.BeginHorizontal();
for(var i = 0; i < names.Length; i ++)
{
if (i > 0 && lineChange > 0 && i % lineChange == 0)
{
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
}
if (i == selected) GUI.color = new Color(2,2,2);
if (GUILayout.Button(names[i], GUILayout.Height(30)))
{
selected = i;
}
GUI.color = Color.white;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
return selected;
}
// public override VisualElement CreateInspectorGUI()
// {
// var asset = Resources.Load<VisualTreeAsset>("UISplineRenderer Inspector");
// var tree = asset.CloneTree();
//
// _splineContainerField = tree.Q<ObjectField>("splineContainer");
// _splineContainerField.SetEnabled(false);
//
// _materialField = tree.Q<ObjectField>("material");
// _materialField.RegisterValueChangedCallback(e =>
// {
// _target.material = e.newValue as Material;
// });
//
// _keepZeroZField = tree.Q<Toggle>("keepZeroZ");
// _keepZeroZField.RegisterValueChangedCallback(e =>
// {
// _target.UpdateStartEndImages(true);
// _target.UpdateStartEndImages(false);
// });
// _keepBillboardField = tree.Q<Toggle>("keepBillboard");
// _keepBillboardField.RegisterValueChangedCallback(e =>
// {
// _target.UpdateStartEndImages(true);
// _target.UpdateStartEndImages(false);
// });
//
// var lineTextureArea = tree.Q<VisualElement>("lineTextureArea");
// _textureField = lineTextureArea.Q<ObjectField>("texture");
//
// var textureButtons = tree.Q<VisualElement>("presetButtons");
// _defaultLineTextureButton = textureButtons.Q<Button>("default");
// _uvTestLineTextureButton = textureButtons.Q<Button>("uvTest");
// _customLineTextureButton = textureButtons.Q<Button>("custom");
//
// _defaultLineTextureButton.clicked += () => OnLineTexturePresetChanged(LineTexturePreset.Default);
// _uvTestLineTextureButton.clicked += () => OnLineTexturePresetChanged(LineTexturePreset.UVTest);
// _customLineTextureButton.clicked += () => OnLineTexturePresetChanged(LineTexturePreset.Custom);
//
// OnLineTexturePresetChanged(_target.lineTexturePreset);
//
// _uvModeField = lineTextureArea.Q<EnumField>("uvMode");
// _uvModeField.tooltip = "Tile - Texture is tiled along spline length. The wrap mode of the texture should be Repeat\n\n" +
// "Repeat per Segment - Texture is placed per segment(based on spline knots). The wrap mode of the texture should be Repeat\n\n" +
// "Stretch - Texture is stretched along spline.";
//
//
// _vertexCountField = lineTextureArea.Q<Label>("vertexCount");
// _resolutionSlider = lineTextureArea.Q<SliderInt>("resolution");
// _resolutionSlider.RegisterValueChangedCallback(e =>
// {
// _target.resolution = e.newValue;
// UpdateVertexCount();
// });
// UpdateVertexCount();
//
// var clipRangeSlider = lineTextureArea.Q<MinMaxSlider>("clipRange");
// clipRangeSlider.RegisterValueChangedCallback(e =>
// {
// UpdateVertexCount();
// });
//
// // init start images
// var startImageArea = tree.Q<VisualElement>("startImageArea");
// _startImageSpriteField = startImageArea.Q<ObjectField>("sprite");
// _startImageSpriteField.RegisterValueChangedCallback(e =>
// {
// _target.UpdateStartEndImages(true);
// });
//
// _noneStartImageButton = startImageArea.Q<Button>("none");
// _triangleStartImageButton = startImageArea.Q<Button>("triangle");
// _arrowStartImageButton = startImageArea.Q<Button>("arrow");
// _emptyCircleStartImageButton = startImageArea.Q<Button>("emptyCircle");
// _filledCircleStartImageButton = startImageArea.Q<Button>("filledCircle");
// _customStartImageButton = startImageArea.Q<Button>("custom");
//
// _noneStartImageButton.clicked += () => OnStartImagePresetChanged(StartEndImagePreset.None);
// _triangleStartImageButton.clicked += () => OnStartImagePresetChanged(StartEndImagePreset.Triangle);
// _arrowStartImageButton.clicked += () => OnStartImagePresetChanged(StartEndImagePreset.Arrow);
// _emptyCircleStartImageButton.clicked += () => OnStartImagePresetChanged(StartEndImagePreset.EmptyCircle);
// _filledCircleStartImageButton.clicked += () => OnStartImagePresetChanged(StartEndImagePreset.FilledCircle);
// _customStartImageButton.clicked += () => OnStartImagePresetChanged(StartEndImagePreset.Custom);
//
// _startImageSizeField = startImageArea.Q<FloatField>("size");
// _startImageSizeField.RegisterValueChangedCallback(e =>
// {
// _target.UpdateStartEndImages(true);
// });
//
// _startImageOffsetField = startImageArea.Q<FloatField>("offset");
// _startImageOffsetField.RegisterValueChangedCallback(e =>
// {
// _target.UpdateStartEndImages(true);
// });
//
// OnStartImagePresetChanged(_target.startImagePreset);
//
//
// // init end images
// var endImageArea = tree.Q<VisualElement>("endImageArea");
// _endImageSpriteField = endImageArea.Q<ObjectField>("sprite");
// _endImageSpriteField.RegisterValueChangedCallback(e =>
// {
// _target.UpdateStartEndImages(false);
// });
//
// _noneEndImageButton = endImageArea.Q<Button>("none");
// _triangleEndImageButton = endImageArea.Q<Button>("triangle");
// _arrowEndImageButton = endImageArea.Q<Button>("arrow");
// _emptyCircleEndImageButton = endImageArea.Q<Button>("emptyCircle");
// _filledCircleEndImageButton = endImageArea.Q<Button>("filledCircle");
// _customEndImageButton = endImageArea.Q<Button>("custom");
//
// _noneEndImageButton.clicked += () => OnEndImagePresetChanged(StartEndImagePreset.None);
// _triangleEndImageButton.clicked += () => OnEndImagePresetChanged(StartEndImagePreset.Triangle);
// _arrowEndImageButton.clicked += () => OnEndImagePresetChanged(StartEndImagePreset.Arrow);
// _emptyCircleEndImageButton.clicked += () => OnEndImagePresetChanged(StartEndImagePreset.EmptyCircle);
// _filledCircleEndImageButton.clicked += () => OnEndImagePresetChanged(StartEndImagePreset.FilledCircle);
// _customEndImageButton.clicked += () => OnEndImagePresetChanged(StartEndImagePreset.Custom);
//
//
// OnEndImagePresetChanged(_target.endImagePreset);
// _endImageSizeField = endImageArea.Q<FloatField>("size");
// _endImageSizeField.RegisterValueChangedCallback(e =>
// {
// _target.UpdateStartEndImages(false);
// });
//
// _endImageOffsetField = endImageArea.Q<FloatField>("offset");
// _endImageOffsetField.RegisterValueChangedCallback(e =>
// {
// _target.UpdateStartEndImages(false);
// });
//
//
// return tree;
// }
void OnLineTexturePresetChanged(LineTexturePreset preset)
{
switch (preset)
{
case LineTexturePreset.Default:
_defaultLineTextureButton.style.backgroundColor = Color.gray;
_uvTestLineTextureButton.style.backgroundColor = StyleKeyword.Null;
_customLineTextureButton.style.backgroundColor = StyleKeyword.Null;
_textureField.value = settings.defaultLineTexture;
// _textureField.SetEnabled(false);
// if not initialized yet
if (_target.texture == null)
{
_target.texture = settings.defaultLineTexture;
}
break;
case LineTexturePreset.UVTest:
_defaultLineTextureButton.style.backgroundColor = StyleKeyword.Null;
_uvTestLineTextureButton.style.backgroundColor = Color.gray;
_customLineTextureButton.style.backgroundColor = StyleKeyword.Null;
_textureField.value = settings.uvTestLineTexture;
// _textureField.SetEnabled(false);
break;
case LineTexturePreset.Custom:
_defaultLineTextureButton.style.backgroundColor = StyleKeyword.Null;
_uvTestLineTextureButton.style.backgroundColor = StyleKeyword.Null;
_customLineTextureButton.style.backgroundColor = Color.gray;
_textureField.SetEnabled(true);
break;
default:
throw new ArgumentOutOfRangeException(nameof(preset), preset, null);
}
}
void OnStartImagePresetChanged(StartEndImagePreset preset)
{
switch (preset)
{
case StartEndImagePreset.None:
_noneStartImageButton.style.backgroundColor = Color.gray;
_triangleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowStartImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_customStartImageButton.style.backgroundColor = StyleKeyword.Null;
_startImageSpriteField.value = null;
// _startImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.Triangle:
_noneStartImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleStartImageButton.style.backgroundColor = Color.gray;
_arrowStartImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_customStartImageButton.style.backgroundColor = StyleKeyword.Null;
_startImageSpriteField.value = settings.triangleHead;
// _startImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.Arrow:
_noneStartImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowStartImageButton.style.backgroundColor = Color.gray;
_emptyCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_customStartImageButton.style.backgroundColor = StyleKeyword.Null;
_startImageSpriteField.value = settings.arrowHead;
// _startImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.EmptyCircle:
_noneStartImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowStartImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleStartImageButton.style.backgroundColor = Color.gray;
_filledCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_customStartImageButton.style.backgroundColor = StyleKeyword.Null;
_startImageSpriteField.value = settings.emptyCircleHead;
// _startImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.FilledCircle:
_noneStartImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowStartImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleStartImageButton.style.backgroundColor = Color.gray;
_customStartImageButton.style.backgroundColor = StyleKeyword.Null;
_startImageSpriteField.value = settings.filledCircleHead;
// _startImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.Custom:
_noneStartImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowStartImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleStartImageButton.style.backgroundColor = StyleKeyword.Null;
_customStartImageButton.style.backgroundColor = Color.gray;
_startImageSpriteField.SetEnabled(true);
break;
default:
throw new ArgumentOutOfRangeException(nameof(preset), preset, null);
}
}
void OnEndImagePresetChanged(StartEndImagePreset preset)
{
switch (preset)
{
case StartEndImagePreset.None:
_noneEndImageButton.style.backgroundColor = Color.gray;
_triangleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowEndImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_customEndImageButton.style.backgroundColor = StyleKeyword.Null;
_endImageSpriteField.value = null;
// _endImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.Triangle:
_noneEndImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleEndImageButton.style.backgroundColor = Color.gray;
_arrowEndImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_customEndImageButton.style.backgroundColor = StyleKeyword.Null;
_endImageSpriteField.value = settings.triangleHead;
// _endImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.Arrow:
_noneEndImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowEndImageButton.style.backgroundColor = Color.gray;
_emptyCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_customEndImageButton.style.backgroundColor = StyleKeyword.Null;
_endImageSpriteField.value = settings.arrowHead;
// _endImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.EmptyCircle:
_noneEndImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowEndImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleEndImageButton.style.backgroundColor = Color.gray;
_filledCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_customEndImageButton.style.backgroundColor = StyleKeyword.Null;
_endImageSpriteField.value = settings.emptyCircleHead;
// _endImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.FilledCircle:
_noneEndImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowEndImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleEndImageButton.style.backgroundColor = Color.gray;
_customEndImageButton.style.backgroundColor = StyleKeyword.Null;
_endImageSpriteField.value = settings.filledCircleHead;
// _endImageSpriteField.SetEnabled(false);
break;
case StartEndImagePreset.Custom:
_noneEndImageButton.style.backgroundColor = StyleKeyword.Null;
_triangleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_arrowEndImageButton.style.backgroundColor = StyleKeyword.Null;
_emptyCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_filledCircleEndImageButton.style.backgroundColor = StyleKeyword.Null;
_customEndImageButton.style.backgroundColor = Color.gray;
_endImageSpriteField.SetEnabled(true);
break;
default:
throw new ArgumentOutOfRangeException(nameof(preset), preset, null);
}
}
void UpdateVertexCount()
{
if(_vertexCountField == null) return;
#if UNITY_2022_3_OR_NEWER
_vertexCountField.text = $"Vertex Count : {_target.vertexCount}";
#endif
}
void SplineChangeCallback(Spline spline, int idx, SplineModification modification)
{
for (int i = 0; i < _target.splineContainer.Splines.Count; i++)
{
if (_target.splineContainer.Splines[i] == spline)
{
UpdateVertexCount();
return;
}
}
}
void SplineContainerChangeCallback(SplineContainer container, int i)
{
if(container == _target.splineContainer) UpdateVertexCount();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 30338a4923984065905dd45640ab4853
timeCreated: 1690032615

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 676508ae22747f440975b4fa677cde47
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f4cb97132743ed84e8926b32c0e21b6a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7fa77eec39f8ab541993402f8b658f8f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
using UnityEngine;
namespace UI_Spline_Renderer.Example
{
public class DragPortExample : MonoBehaviour
{
// This is a just marker script
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: da33482d98404d569789131816357757
timeCreated: 1690506079

View File

@@ -0,0 +1,72 @@
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Splines;
using UnityEngine.UI;
namespace UI_Spline_Renderer.Example
{
public class DraggableSplinePointExample : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
public UISplineRenderer uiSplineRenderer;
public Image myImage;
public int splineIndex;
public int knotIndex;
public Color connectedColor;
public bool isConnected;
BezierKnot _originalKnot;
/*
* You must set false of the raycastTarget value of the UISplineRenderer and Image of this gameObject OnBeginDrag().
* Because it can block the raycast going to a port that pointer hovered.
*/
public void OnDrag(PointerEventData eventData)
{
var pos = transform.parent.InverseTransformPoint(eventData.position);
var knot = new BezierKnot(pos);
uiSplineRenderer.splineContainer[splineIndex].SetKnot(knotIndex, knot);
}
public void OnBeginDrag(PointerEventData eventData)
{
uiSplineRenderer.raycastTarget = false;
myImage.raycastTarget = false;
uiSplineRenderer.color = Color.white;
if(!isConnected)_originalKnot = uiSplineRenderer.splineContainer[splineIndex][knotIndex];
}
public void OnEndDrag(PointerEventData eventData)
{
foreach (var go in eventData.hovered)
{
if (go.GetComponent<DragPortExample>())
{
Connect(go.transform);
uiSplineRenderer.raycastTarget = true;
myImage.raycastTarget = true;
return;
}
}
Disconnect();
}
void Connect(Transform t)
{
var pos = transform.parent.InverseTransformPoint(t.position);
var knot = new BezierKnot(pos);
uiSplineRenderer.splineContainer[splineIndex].SetKnot(knotIndex, knot);
uiSplineRenderer.color = connectedColor;
isConnected = true;
}
void Disconnect()
{
uiSplineRenderer.color = Color.white;
uiSplineRenderer.splineContainer[splineIndex].SetKnot(knotIndex, _originalKnot);
isConnected = false;
uiSplineRenderer.raycastTarget = true;
myImage.raycastTarget = true;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 01ab4fe8e6ee4cfd890ed9514bb2f188
timeCreated: 1690505945

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UI_Spline_Renderer;
using UnityEngine;
using UnityEngine.UI;
namespace UI_Spline_Renderer.Example
{
public class UISplineRendererExample : MonoBehaviour
{
public UISplineRenderer target_uvAnimation;
public UISplineRenderer target_interaction;
void Start()
{
target_interaction.GetComponent<Button>().onClick.AddListener(() => Debug.Log($"Spline Clicked !"));
}
void Update()
{
UpdateUV();
}
void UpdateUV()
{
target_uvAnimation.uvOffset += new Vector2(0, Time.deltaTime * 2);
target_uvAnimation.clipRange = new Vector2(0, (Mathf.Sin(Time.time) + 1) * 0.5f);
}
}
}

View File

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

View File

@@ -0,0 +1 @@
https://docs.google.com/document/d/18kDoAWthPx_YqJgSHuGmEBlGGs8QKEEuB-hfK8fLOUo/edit?usp=sharing

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1b50ef9e519abc743884fbe3170c033d
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 92c8741e0e119c5408a3189b674d2d6c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a21f54b05b414b95874ba3e272a365f0, type: 3}
m_Name: UISplineRenderer Settings
m_EditorClassIdentifier:
defaultLineTexture: {fileID: 2800000, guid: de2cd6c5e176d6846b6ac52585e8307b, type: 3}
uvTestLineTexture: {fileID: 2800000, guid: 9a546562df1161a40b21293b5dadb11c, type: 3}
triangleHead: {fileID: 21300000, guid: 23c2331a5cac12343895afa95b9d5504, type: 3}
arrowHead: {fileID: 21300000, guid: d5d3eb9c021c8d440a2da201a039967c, type: 3}
emptyCircleHead: {fileID: 21300000, guid: 60e780f6137acf848bd41ff84c4bc3df, type: 3}
filledCircleHead: {fileID: 21300000, guid: 6fea2bbbbb345544a81bcfff2f1b1fe1, type: 3}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5413bd73fc9a0ec4095c77cd8d85162a
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c657af100b2a044419c14321d4cacfca
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b4fa186cddd3105438f20a753e523552
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,418 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Unity.Burst;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Splines;
namespace UI_Spline_Renderer
{
[BurstCompile]
internal static class InternalUtility
{
struct FrenetFrame
{
public float3 origin;
public float3 tangent;
public float3 normal;
public float3 binormal;
}
const int k_NormalsPerCurve = 16;
const float k_Epsilon = 0.0001f;
// source of this methods
// https://forum.unity.com/threads/moving-just-recttransform-pivot-in-world-space.1380249/
// by halley
internal static Vector3 GetPivotInWorldSpace(this RectTransform source)
{
var pivot = new Vector2(
source.rect.xMin + source.pivot.x * source.rect.width,
source.rect.yMin + source.pivot.y * source.rect.height);
return source.TransformPoint(new Vector3(pivot.x, pivot.y, 0f));
}
// source of this methods
// https://forum.unity.com/threads/moving-just-recttransform-pivot-in-world-space.1380249/
// by halley
internal static void SetPivotWithoutRect(this RectTransform source, Vector3 pivot)
{
var rect = source.rect;
if(float.IsNaN(rect.x) || float.IsNaN(rect.y) || float.IsNaN(rect.size.x) || float.IsNaN(rect.size.y)) return;
pivot = source.InverseTransformPoint(pivot);
var pivot2 = new Vector2(
(pivot.x - rect.xMin) / rect.width,
(pivot.y - rect.yMin) / rect.height);
var offset = pivot2 - source.pivot;
offset.Scale(source.rect.size);
var worldPos = source.position + source.TransformVector(offset);
source.pivot = pivot2;
source.position = worldPos;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static float Remap(this float value, float beforeRangeMin, float beforeRangeMax, float targetRangeMin, float targetRangeMax)
{
var denominator = beforeRangeMax - beforeRangeMin;
if (denominator == 0) return targetRangeMin;
var ratio = (value - beforeRangeMin) / denominator;
var result = (targetRangeMax - targetRangeMin) * ratio + targetRangeMin;
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static float Remap(this int value, float beforeRangeMin, float beforeRangeMax, float targetRangeMin, float targetRangeMax)
{
return Remap((float)value, beforeRangeMin, beforeRangeMax, targetRangeMin, targetRangeMax);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static float sq(this float value) => value * value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static float LerpPoint(float value, float min, float max)
{
return (value - min) / (max - min);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Angle(this float3 a, float3 b)
{
float dot = math.dot(math.normalizesafe(a), math.normalizesafe(b));
dot = math.clamp(dot, -1f, 1f); // 클램핑을 하지 않고 acos를 실행하면 NaN을 반환함.
return math.degrees(math.acos(dot));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float SignedAngle(this float3 a, float3 b)
{
var angle = math.acos(math.dot(math.normalizesafe(a), math.normalizesafe(b)));
var cross = math.cross(a, b);
angle *= math.sign(math.dot(math.up(), cross));
return math.degrees(angle);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float RadAngle(this float3 a, float3 b)
{
var angle = math.acos(math.dot(math.normalizesafe(a), math.normalizesafe(b)));
var cross = math.cross(a, b);
angle *= math.sign(math.dot(math.up(), cross));
return angle;
}
internal static StartEndImagePreset GetCurrentStartImagePreset(Sprite target)
{
if (target == null) return StartEndImagePreset.None;
if (target == UISplineRendererSettings.Instance.triangleHead) return StartEndImagePreset.Triangle;
if (target == UISplineRendererSettings.Instance.arrowHead) return StartEndImagePreset.Arrow;
if (target == UISplineRendererSettings.Instance.emptyCircleHead) return StartEndImagePreset.EmptyCircle;
if (target == UISplineRendererSettings.Instance.filledCircleHead) return StartEndImagePreset.FilledCircle;
return StartEndImagePreset.Custom;
}
public static float Repeat(float t, float length)
{
return math.clamp(t - math.floor(t / length) * length, 0.0f, length);
}
public static void CalculateCurveLengths(BezierCurve curve, NativeArray<DistanceToInterpolation> lookupTable)
{
var resolution = lookupTable.Length;
float magnitude = 0f;
float3 prev = CurveUtility.EvaluatePosition(curve, 0f);
lookupTable[0] = new DistanceToInterpolation() { Distance = 0f , T = 0f };
for (int i = 1; i < resolution; i++)
{
var t = i / ( resolution - 1f );
var point = CurveUtility.EvaluatePosition(curve, t);
var dir = point - prev;
magnitude += math.length(dir);
lookupTable[i] = new DistanceToInterpolation() { Distance = magnitude , T = t};
prev = point;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int CalcVertexCount(this Spline spline, float segmentLength, float2 renderRange)
{
var length = spline.GetLength() * (renderRange.y - renderRange.x);
return math.max((int)math.ceil(length * segmentLength), 1) * 2 + 4;
}
internal static int GetNearestKnotIndex(this CopiedNativeSpline spline, float t, out float distanceSq)
{
var p = spline.EvaluatePosition(t);
distanceSq = float.MaxValue;
var minIdx = -1;
for (int i = 0; i < spline.Knots.Length; i++)
{
var knot = spline.Knots[i];
var distSq = math.distancesq(knot.Position, p);
if (distSq < distanceSq)
{
minIdx = i;
distanceSq = distSq;
}
}
return minIdx;
}
internal static float CircularDistance(this float a, float b, float max = 1)
{
var half = max * 0.5f;
var aIsSmallSide = a < half;
var bIsSmallSide = b < half;
if (aIsSmallSide == bIsSmallSide)
{
return a > b ? a - b : b - a;
}
else
{
if (a > b)
{
b += max;
return b - a;
}
else
{
a += max;
return a - b;
}
}
}
internal static NativeColorGradient ToNative (this Gradient gradient, Allocator allocator = Allocator.TempJob)
{
var aKeys = new NativeArray<float2>(gradient.alphaKeys.Length, allocator);
for (int i = 0; i < gradient.alphaKeys.Length; i++)
{
var key = gradient.alphaKeys[i];
aKeys[i] = new float2(key.alpha, key.time);
}
var cKeys = new NativeArray<float4>(gradient.colorKeys.Length, allocator);
for (int i = 0; i < gradient.colorKeys.Length; i++)
{
var key = gradient.colorKeys[i];
cKeys[i] = new float4(key.color.r, key.color.g, key.color.b, key.time);
}
var native = new NativeColorGradient()
{
alphaKeyFrames = aKeys,
colorKeyFrames = cKeys
};
return native;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[BurstCompile]
internal static void ExtrudeEdge(
float w, float V, in Color clr, ref float3 pos, in float3 tan, in float3 up,
bool keepBillboard, bool keepZeroZ, in float2 uvMultiplier, in float2 uvOffset,
out UIVertex v0, out UIVertex v1)
{
var perpendicular =
keepBillboard ? math.normalizesafe(math.cross(tan, new float3(0, 0, -1))) : math.normalizesafe(math.cross(tan, up));
if (keepZeroZ)
{
pos.z = 0;
}
var uv = new float2(0, V) * uvMultiplier - uvOffset;
var vert = new UIVertex
{
position = pos + perpendicular * w * 0.5f,
uv0 = new Vector4(uv.x, uv.y),
color = clr
};
v0 = vert;
uv = new float2(1, V) * uvMultiplier - uvOffset;
vert = new UIVertex
{
position = pos - perpendicular * w * 0.5f,
uv0 = new Vector4(uv.x, uv.y),
color = clr
};
v1 = vert;
}
internal static float3 GetExplicitLinearTangent(float3 point, float3 to)
{
return (to - point) / 3.0f;
}
internal static float3 CalculateUpVector<T>(this T spline, int curveIndex, float curveT) where T : ISpline
{
if (spline.Count < 1)
return float3.zero;
var curve = spline.GetCurve(curveIndex);
var curveStartRotation = spline[curveIndex].Rotation;
var curveStartUp = math.rotate(curveStartRotation, math.up());
if (curveT == 0f)
return curveStartUp;
var endKnotIndex = spline.NextIndex(curveIndex);
var curveEndRotation = spline[endKnotIndex].Rotation;
var curveEndUp = math.rotate(curveEndRotation, math.up());
if (curveT == 1f)
return curveEndUp;
var up = EvaluateUpVector(curve, curveT, curveStartUp, curveEndUp);
return up;
}
internal static void EvaluateUpVectors(BezierCurve curve, float3 startUp, float3 endUp, Vector3[] upVectors)
{
upVectors[0] = startUp;
upVectors[upVectors.Length - 1] = endUp;
for(int i = 1; i < upVectors.Length - 1; i++)
{
var curveT = i / (float)(upVectors.Length - 1);
upVectors[i] = EvaluateUpVector(curve, curveT, upVectors[0], endUp);
}
}
internal static float3 EvaluateUpVector(BezierCurve curve, float t, float3 startUp, float3 endUp)
{
// Ensure we have workable tangents by linearizing ones that are of zero length
var linearTangentLen = math.length(GetExplicitLinearTangent(curve.P0, curve.P3));
var linearTangentOut = math.normalize(curve.P3 - curve.P0) * linearTangentLen;
if (Approximately(math.length(curve.P1 - curve.P0), 0f))
curve.P1 = curve.P0 + linearTangentOut;
if (Approximately(math.length(curve.P2 - curve.P3), 0f))
curve.P2 = curve.P3 - linearTangentOut;
var normalBuffer = new NativeArray<float3>(k_NormalsPerCurve, Allocator.Temp);
// Construct initial frenet frame
FrenetFrame frame;
frame.origin = curve.P0;
frame.tangent = curve.P1 - curve.P0;
frame.normal = startUp;
frame.binormal = math.normalize(math.cross(frame.tangent, frame.normal));
// SPLB-185 : If the tangent and normal are parallel, we can't construct a valid frame
// rather than returning a value based on startUp and endUp, we return a zero vector
// to indicate that this is not a valid up vector.
if(float.IsNaN(frame.binormal.x))
return float3.zero;
normalBuffer[0] = frame.normal;
// Continue building remaining rotation minimizing frames
var stepSize = 1f / (k_NormalsPerCurve - 1);
var currentT = stepSize;
var prevT = 0f;
var upVector = float3.zero;
FrenetFrame prevFrame;
for (int i = 1; i < k_NormalsPerCurve; ++i)
{
prevFrame = frame;
frame = GetNextRotationMinimizingFrame(curve, prevFrame, currentT);
normalBuffer[i] = frame.normal;
if (prevT <= t && currentT >= t)
{
var lerpT = (t - prevT) / stepSize;
upVector = Vector3.Slerp(prevFrame.normal, frame.normal, lerpT);
}
prevT = currentT;
currentT += stepSize;
}
if (prevT <= t && currentT >= t)
upVector = endUp;
var lastFrameNormal = normalBuffer[k_NormalsPerCurve - 1];
var angleBetweenNormals = math.acos(math.clamp(math.dot(lastFrameNormal, endUp), -1f, 1f));
if (angleBetweenNormals == 0f)
return upVector;
// Since there's an angle difference between the end knot's normal and the last evaluated frenet frame's normal,
// the remaining code gradually applies the angle delta across the evaluated frames' normals.
var lastNormalTangent = math.normalize(frame.tangent);
var positiveRotation = quaternion.AxisAngle(lastNormalTangent, angleBetweenNormals);
var negativeRotation = quaternion.AxisAngle(lastNormalTangent, -angleBetweenNormals);
var positiveRotationResult = math.acos(math.clamp(math.dot(math.rotate(positiveRotation, endUp), lastFrameNormal), -1f, 1f));
var negativeRotationResult = math.acos(math.clamp(math.dot(math.rotate(negativeRotation, endUp), lastFrameNormal), -1f, 1f));
if (positiveRotationResult > negativeRotationResult)
angleBetweenNormals *= -1f;
currentT = stepSize;
prevT = 0f;
for (int i = 1; i < normalBuffer.Length; i++)
{
var normal = normalBuffer[i];
var adjustmentAngle = math.lerp(0f, angleBetweenNormals, currentT);
var tangent = math.normalize(CurveUtility.EvaluateTangent(curve, currentT));
var adjustedNormal = math.rotate(quaternion.AxisAngle(tangent, -adjustmentAngle), normal);
normalBuffer[i] = adjustedNormal;
// Early exit if we've already adjusted the normals at offsets that curveT is in between
if (prevT <= t && currentT >= t)
{
var lerpT = (t - prevT) / stepSize;
upVector = Vector3.Slerp(normalBuffer[i - 1], normalBuffer[i], lerpT);
return upVector;
}
prevT = currentT;
currentT += stepSize;
}
return endUp;
}
static bool Approximately(float a, float b)
{
// Reusing Mathf.Approximately code
return math.abs(b - a) < math.max(0.000001f * math.max(math.abs(a), math.abs(b)), k_Epsilon * 8);
}
static FrenetFrame GetNextRotationMinimizingFrame(BezierCurve curve, FrenetFrame previousRMFrame, float nextRMFrameT)
{
FrenetFrame nextRMFrame;
// Evaluate position and tangent for next RM frame
nextRMFrame.origin = CurveUtility.EvaluatePosition(curve, nextRMFrameT);
nextRMFrame.tangent = CurveUtility.EvaluateTangent(curve, nextRMFrameT);
// Mirror the rotational axis and tangent
float3 toCurrentFrame = nextRMFrame.origin - previousRMFrame.origin;
float c1 = math.dot(toCurrentFrame, toCurrentFrame);
float3 riL = previousRMFrame.binormal - toCurrentFrame * 2f / c1 * math.dot(toCurrentFrame, previousRMFrame.binormal);
float3 tiL = previousRMFrame.tangent - toCurrentFrame * 2f / c1 * math.dot(toCurrentFrame, previousRMFrame.tangent);
// Compute a more stable binormal
float3 v2 = nextRMFrame.tangent - tiL;
float c2 = math.dot(v2, v2);
// Fix binormal's axis
nextRMFrame.binormal = math.normalize(riL - v2 * 2f / c2 * math.dot(v2, riL));
nextRMFrame.normal = math.normalize(math.cross(nextRMFrame.binormal, nextRMFrame.tangent));
return nextRMFrame;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 70ad0f216fa5499793e06998613a4133
timeCreated: 1688923970

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ea8f0f82da6648faac53810f1e6f932c
timeCreated: 1690424194

View File

@@ -0,0 +1,139 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Splines;
namespace UI_Spline_Renderer
{
public struct CopiedNativeSpline : ISpline, IDisposable
{
[ReadOnly]
NativeArray<BezierKnot> m_Knots;
[ReadOnly]
NativeArray<BezierCurve> m_Curves;
[ReadOnly]
NativeArray<DistanceToInterpolation> m_SegmentLengthsLookupTable;
bool m_Closed;
float m_Length;
const int k_SegmentResolution = 30;
public NativeArray<BezierKnot> Knots => m_Knots;
public NativeArray<BezierCurve> Curves => m_Curves;
public bool Closed => m_Closed;
public int Count => m_Knots.Length;
public readonly float GetLength() => m_Length;
public BezierKnot this[int index] => m_Knots[index];
public IEnumerator<BezierKnot> GetEnumerator() => m_Knots.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public CopiedNativeSpline(NativeArray<BezierKnot> knots, bool closed, float4x4 transform, Allocator allocator = Allocator.Temp)
{
int kc = knots.Length;
m_Knots = knots;
m_Curves = new NativeArray<BezierCurve>(kc, allocator);
m_SegmentLengthsLookupTable = new NativeArray<DistanceToInterpolation>(kc * k_SegmentResolution, allocator);
m_Closed = closed;
m_Length = 0f;
NativeArray<DistanceToInterpolation> distanceToTimes = new NativeArray<DistanceToInterpolation>(k_SegmentResolution, Allocator.Temp);
if (knots.Length > 0)
{
BezierKnot cur = knots[0].Transform(transform);
for (int i = 0; i < kc; ++i)
{
BezierKnot next = knots[(i + 1) % kc].Transform(transform);
m_Knots[i] = cur;
m_Curves[i] = new BezierCurve(cur, next);
InternalUtility.CalculateCurveLengths(m_Curves[i], distanceToTimes);
if (m_Closed || i < kc - 1)
m_Length += distanceToTimes[k_SegmentResolution - 1].Distance;
for (int index = 0; index < k_SegmentResolution; index++)
{
m_SegmentLengthsLookupTable[i * k_SegmentResolution + index] = distanceToTimes[index];
}
cur = next;
}
}
}
/// <summary>
/// Get a <see cref="BezierCurve"/> from a knot index.
/// </summary>
/// <param name="index">The knot index that serves as the first control point for this curve.</param>
/// <returns>
/// A <see cref="BezierCurve"/> formed by the knot at index and the next knot.
/// </returns>
public BezierCurve GetCurve(int index) => m_Curves[index];
/// <summary>
/// Get the length of a <see cref="BezierCurve"/>.
/// </summary>
/// <param name="curveIndex">The 0 based index of the curve to find length for.</param>
/// <returns>The length of the bezier curve at index.</returns>
public float GetCurveLength(int curveIndex)
{
return m_SegmentLengthsLookupTable[curveIndex * k_SegmentResolution + k_SegmentResolution - 1].Distance;
}
public float3 GetCurveUpVector(int index, float t)
{
return this.CalculateUpVector(index, t);
}
/// <summary>
/// Release allocated resources.
/// </summary>
public void Dispose()
{
m_Knots.Dispose();
m_Curves.Dispose();
m_SegmentLengthsLookupTable.Dispose();
}
// Wrapper around NativeSlice<T> because the native type does not implement IReadOnlyList<T>.
struct Slice<T> : IReadOnlyList<T> where T : struct
{
NativeSlice<T> m_Slice;
public Slice(NativeArray<T> array, int start, int count) { m_Slice = new NativeSlice<T>(array, start, count); }
public IEnumerator<T> GetEnumerator() => m_Slice.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public int Count => m_Slice.Length;
public T this[int index] => m_Slice[index];
}
/// <summary>
/// Return the normalized interpolation (t) corresponding to a distance on a <see cref="BezierCurve"/>.
/// </summary>
/// <param name="curveIndex"> The zero-based index of the curve.</param>
/// <param name="curveDistance">The curve-relative distance to convert to an interpolation ratio (also referred to as 't').</param>
/// <returns> The normalized interpolation ratio associated to distance on the designated curve.</returns>
public float GetCurveInterpolation(int curveIndex, float curveDistance)
{
if(curveIndex <0 || curveIndex >= m_SegmentLengthsLookupTable.Length || curveDistance <= 0)
return 0f;
var curveLength = GetCurveLength(curveIndex);
if(curveDistance >= curveLength)
return 1f;
var startIndex = curveIndex * k_SegmentResolution;
var slice = new Slice<DistanceToInterpolation>(m_SegmentLengthsLookupTable, startIndex, k_SegmentResolution);
return CurveUtility.GetDistanceToInterpolation(slice, curveDistance);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ea2e3adba3aa4b25a044aa103d6fc756
timeCreated: 1713945997

View File

@@ -0,0 +1,92 @@
using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
namespace UI_Spline_Renderer
{
internal struct NativeColorGradient : IDisposable
{
// y is time.
[ReadOnly]
public NativeArray<float2> alphaKeyFrames;
// w is time.
[ReadOnly]
public NativeArray<float4> colorKeyFrames;
public Color Evaluate(float t)
{
var nextAlphaIdx = -1;
for (int i = 0; i < alphaKeyFrames.Length; i++)
{
if(t > alphaKeyFrames[i].y) continue;
nextAlphaIdx = i;
break;
}
var nextColorKeyIdx = -1;
for (int i = 0; i < colorKeyFrames.Length; i++)
{
if (t > colorKeyFrames[i].w) continue;
nextColorKeyIdx = i;
break;
}
float alpha;
if (nextAlphaIdx == -1)
{
alpha = alphaKeyFrames[^1].x;
}
else if (nextAlphaIdx == 0)
{
alpha = alphaKeyFrames[0].x;
}
else
{
var preAlpha = alphaKeyFrames[nextAlphaIdx - 1];
var nextAlpha = alphaKeyFrames[nextAlphaIdx];
var remappedT = t.Remap(0, 1, preAlpha.y, nextAlpha.y);
alpha = math.lerp(preAlpha, nextAlpha, remappedT).x;
}
Color color;
if(nextColorKeyIdx == -1)
{
color = toColor(colorKeyFrames[^1]);
}
else if(nextColorKeyIdx == 0)
{
color = toColor(colorKeyFrames[0]);
}
else
{
var preColor = toColor(colorKeyFrames[nextColorKeyIdx - 1]);
var nextKey = toColor(colorKeyFrames[nextColorKeyIdx]);
var remappedT = (t - preColor.a) / (nextKey.a - preColor.a);
color = Color.Lerp(preColor, nextKey, remappedT);
}
color.a = alpha;
return color;
}
Color toColor(float4 f)
{
return new Color(f.x, f.y, f.z, f.w);
}
public void Dispose()
{
alphaKeyFrames.Dispose();
colorKeyFrames.Dispose();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: baf1300b266e4ca887cad7e70d1a70cb
timeCreated: 1690408892

View File

@@ -0,0 +1,351 @@
using System;
using System.Security.Cryptography;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Mathematics;
using UnityEngine;
namespace UI_Spline_Renderer
{
internal readonly struct NativeCurve : IDisposable
{
private const int TRUE = 1;
private const int FALSE = 1;
public readonly NativeArray<Keyframe> Keys;
private readonly int owner;
public NativeCurve(AnimationCurve c, Allocator alloc)
{
Keys = new NativeArray<Keyframe>(c.keys, alloc);
owner = TRUE;
}
public NativeCurve(int size, Allocator alloc)
{
Keys = new NativeArray<Keyframe>(size, alloc);
owner = TRUE;
}
public NativeCurve(Keyframe[] keyframes, Allocator alloc)
{
Keys = new NativeArray<Keyframe>(keyframes, alloc);
owner = TRUE;
}
public NativeCurve(NativeArray<Keyframe> keyframes, Allocator alloc)
{
Keys = new NativeArray<Keyframe>(keyframes, alloc);
owner = TRUE;
}
public NativeCurve(NativeArray<Keyframe> keyframes)
{
Keys = keyframes;
owner = FALSE;
}
public NativeCurve(NativeCurve other)
{
Keys = other.Keys;
owner = FALSE;
}
public NativeCurve(NativeCurve other, Allocator alloc)
{
Keys = new NativeArray<Keyframe>(other.Keys, alloc);
owner = TRUE;
}
public void Dispose()
{
if (owner != 0)
{
Keys.Dispose();
}
}
public float Evaluate(float time)
{
return CurveSampling.ThreadSafe.Evaluate(Keys, time);
}
public int Length => Keys.Length;
public float Duration => Keys[Length - 1].time - Keys[0].time;
}
public static class CurveSampling
{
const float DefaultWeight = 0;
public static class ThreadSafe
{
public static float Evaluate(NativeArray<Keyframe> keys, float curveT)
{
return EvaluateWithinRange(keys, curveT, 0, keys.Length - 1);
}
public static float EvaluateWithHint(NativeArray<Keyframe> keys, float curveT, ref int hintIndex)
{
int startIndex = 0;
int endIndex = keys.Length - 1;
if (endIndex <= hintIndex)
return keys[hintIndex].value;
// wrap time
curveT = math.clamp(curveT, keys[hintIndex].time, keys[endIndex].time);
FindIndexForSampling(keys, curveT, startIndex, endIndex, hintIndex, out int lhsIndex, out int rhsIndex);
Keyframe lhs = keys[hintIndex];
Keyframe rhs = keys[rhsIndex];
return InterpolateKeyframe(lhs, rhs, curveT);
}
public static float EvaluateWithinRange(NativeArray<Keyframe> keys, float curveT, int startIndex,
int endIndex)
{
if (endIndex <= startIndex)
return keys[startIndex].value;
// wrap time
curveT = math.clamp(curveT, keys[startIndex].time, keys[endIndex].time);
FindIndexForSampling(keys, curveT, startIndex, endIndex, -1, out int lhsIndex, out int rhsIndex);
Keyframe lhs = keys[lhsIndex];
Keyframe rhs = keys[rhsIndex];
return InterpolateKeyframe(lhs, rhs, curveT);
}
static void FindIndexForSampling(NativeArray<Keyframe> keys, float curveT, int start, int end,
int hint,
out int lhs, out int rhs)
{
if (hint != -1)
{
hint = math.clamp(hint, start, end);
// We can not use the cache time or time end since that is in unwrapped time space!
float time = keys[hint].time;
if (curveT > time)
{
const int kMaxLookahead = 3;
for (int i = 0; i < kMaxLookahead; i++)
{
int index = hint + i;
if (index + 1 < end && keys[index + 1].time > curveT)
{
lhs = index;
rhs = math.min(lhs + 1, end);
return;
}
}
}
}
// Fall back to using binary search
// upper bound (first value larger than curveT)
int __len = end - start;
int __half;
int __middle;
int __first = start;
while (__len > 0)
{
__half = __len >> 1;
__middle = __first + __half;
var mid = keys[__middle];
if (curveT < mid.time)
__len = __half;
else
{
__first = __middle;
++__first;
__len = __len - __half - 1;
}
}
// If not within range, we pick the last element twice
lhs = __first - 1;
rhs = math.min(end, __first);
}
public static float InterpolateKeyframe(Keyframe lhs, Keyframe rhs, float curveT)
{
float output;
if ((lhs.weightedMode & WeightedMode.Out) != 0 || (rhs.weightedMode & WeightedMode.In) != 0)
output = BezierInterpolate(curveT, lhs, rhs);
else
output = HermiteInterpolate(curveT, lhs, rhs);
HandleSteppedCurve(lhs, rhs, ref output);
return output;
}
static float HermiteInterpolate(float curveT, Keyframe lhs, Keyframe rhs)
{
float dx = rhs.time - lhs.time;
float m1;
float m2;
float t;
if (dx != 0.0F)
{
t = (curveT - lhs.time) / dx;
m1 = lhs.outTangent * dx;
m2 = rhs.inTangent * dx;
}
else
{
t = 0.0F;
m1 = 0;
m2 = 0;
}
return HermiteInterpolate(t, lhs.value, m1, m2, rhs.value);
}
static float HermiteInterpolate(float t, float p0, float m0, float m1, float p1)
{
float t2 = t * t;
float t3 = t2 * t;
float a = 2.0F * t3 - 3.0F * t2 + 1.0F;
float b = t3 - 2.0F * t2 + t;
float c = t3 - t2;
float d = -2.0F * t3 + 3.0F * t2;
return a * p0 + b * m0 + c * m1 + d * p1;
}
static float BezierInterpolate(float curveT, Keyframe lhs, Keyframe rhs)
{
float lhsOutWeight = (lhs.weightedMode & WeightedMode.Out) != 0 ? lhs.outWeight : DefaultWeight;
float rhsInWeight = (rhs.weightedMode & WeightedMode.In) != 0 ? rhs.inWeight : DefaultWeight;
float dx = rhs.time - lhs.time;
if (dx == 0.0F)
return lhs.value;
return BezierInterpolate((curveT - lhs.time) / dx, lhs.value, lhs.outTangent * dx, lhsOutWeight,
rhs.value, rhs.inTangent * dx, rhsInWeight);
}
static float FAST_CBRT_POSITIVE(float x)
{
return math.exp(math.log(x) / 3.0f);
}
static float FAST_CBRT(float x)
{
return (((x) < 0) ? -math.exp(math.log(-(x)) / 3.0f) : math.exp(math.log(x) / 3.0f));
}
static float BezierExtractU(float t, float w1, float w2)
{
float a = 3.0F * w1 - 3.0F * w2 + 1.0F;
float b = -6.0F * w1 + 3.0F * w2;
float c = 3.0F * w1;
float d = -t;
if (math.abs(a) > 1e-3f)
{
float p = -b / (3.0F * a);
float p2 = p * p;
float p3 = p2 * p;
float q = p3 + (b * c - 3.0F * a * d) / (6.0F * a * a);
float q2 = q * q;
float r = c / (3.0F * a);
float rmp2 = r - p2;
float s = q2 + rmp2 * rmp2 * rmp2;
if (s < 0.0F)
{
float ssi = math.sqrt(-s);
float r_1 = math.sqrt(-s + q2);
float phi = math.atan2(ssi, q);
float r_3 = FAST_CBRT_POSITIVE(r_1);
float phi_3 = phi / 3.0F;
// Extract cubic roots.
float u1 = 2.0F * r_3 * math.cos(phi_3) + p;
float u2 = 2.0F * r_3 * math.cos(phi_3 + 2.0F * (float)math.PI / 3.0f) + p;
float u3 = 2.0F * r_3 * math.cos(phi_3 - 2.0F * (float)math.PI / 3.0f) + p;
if (u1 >= 0.0F && u1 <= 1.0F)
return u1;
else if (u2 >= 0.0F && u2 <= 1.0F)
return u2;
else if (u3 >= 0.0F && u3 <= 1.0F)
return u3;
// Aiming at solving numerical imprecision when u is outside [0,1].
return (t < 0.5F) ? 0.0F : 1.0F;
}
else
{
float ss = math.sqrt(s);
float u = FAST_CBRT(q + ss) + FAST_CBRT(q - ss) + p;
if (u >= 0.0F && u <= 1.0F)
return u;
// Aiming at solving numerical imprecision when u is outside [0,1].
return (t < 0.5F) ? 0.0F : 1.0F;
}
}
if (math.abs(b) > 1e-3f)
{
float s = c * c - 4.0F * b * d;
float ss = math.sqrt(s);
float u1 = (-c - ss) / (2.0F * b);
float u2 = (-c + ss) / (2.0F * b);
if (u1 >= 0.0F && u1 <= 1.0F)
return u1;
else if (u2 >= 0.0F && u2 <= 1.0F)
return u2;
// Aiming at solving numerical imprecision when u is outside [0,1].
return (t < 0.5F) ? 0.0F : 1.0F;
}
if (math.abs(c) > 1e-3f)
{
return (-d / c);
}
return 0.0F;
}
static float BezierInterpolate(float t, float v1, float m1, float w1, float v2, float m2, float w2)
{
float u = BezierExtractU(t, w1, 1.0F - w2);
return BezierInterpolate(u, v1, w1 * m1 + v1, v2 - w2 * m2, v2);
}
static float BezierInterpolate(float t, float p0, float p1, float p2, float p3)
{
float t2 = t * t;
float t3 = t2 * t;
float omt = 1.0F - t;
float omt2 = omt * omt;
float omt3 = omt2 * omt;
return omt3 * p0 + 3.0F * t * omt2 * p1 + 3.0F * t2 * omt * p2 + t3 * p3;
}
static void HandleSteppedCurve(Keyframe lhs, Keyframe rhs, ref float value)
{
if (float.IsInfinity(lhs.outTangent) || float.IsInfinity(rhs.inTangent))
value = lhs.value;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7a04bbc35d484a798423531879e71d9c
timeCreated: 1696727209

View File

@@ -0,0 +1,571 @@
#if ENABLE_SPLINES
#if ENABLE_COLLECTIONS
#if ENABLE_MATHEMATICS
#if ENABLE_BURST
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
using UnityEngine.Splines;
namespace UI_Spline_Renderer
{
[BurstCompile]
internal struct SplineExtrudeJob : IJob
{
[ReadOnly] public NativeSpline spline;
[ReadOnly] public NativeCurve widthCurve;
[ReadOnly] public float width;
[ReadOnly] public bool keepZeroZ;
[ReadOnly] public bool keepBillboard;
[ReadOnly] public float2 clipRange;
[ReadOnly] public float2 uvMultiplier;
[ReadOnly] public float2 uvOffset;
[ReadOnly] public UVMode uvMode;
[ReadOnly] public Color color;
[ReadOnly] internal NativeColorGradient colorGradient;
[ReadOnly] public int resolution;
[ReadOnly] public bool smooth;
[ReadOnly] public bool roundEnds;
public NativeList<UIVertex> vertices;
public NativeList<int3> triangles;
public int addedEdgeCount;
int sampleCount => (int)(resolution * length * 0.03f);
float v;
float length;
public void Execute()
{
if (spline.Count < 2) return;
var edgePoints = new NativeList<EdgePoint>(Allocator.Temp);
if(smooth)
{
SmoothSample(ref edgePoints);
Extrude(in edgePoints);
}
else
{
UniformEvaluate(ref edgePoints);
Extrude(in edgePoints);
}
if (roundEnds && ((spline.Closed && (clipRange.x > math.EPSILON || clipRange.y < 1)) || !spline.Closed))
{
MakeRoundEdges(in edgePoints);
}
}
void SmoothSample(ref NativeList<EdgePoint> edgePoints)
{
var samples = new NativeList<EdgePoint>(Allocator.Temp);
// 전체 스플라인 샘플링
length = spline.GetLength();
for (int i = 0; i < spline.Count; i++)
{
var t = spline.CurveToSplineT(i);
var unitT = (GetWidthAt(t) / length) * 0.5f;
var knot = spline[i];
add_smooth_sample_point(in spline, samples, t, unitT, math.length(knot.TangentIn), math.length(knot.TangentOut));
}
var sampleUnitT = 1f / sampleCount;
for (int i = 0; i < spline.Count; i++)
{
var t = spline.CurveToSplineT(i);
var t_1 = spline.CurveToSplineT(i - 1);
var t1 = spline.CurveToSplineT(i + 1);
var leftT = math.lerp(t, t_1, 0.5f);
var rightT = math.lerp(t, t1, 0.5f);
var leftCount = (int)(math.abs(t - leftT) / sampleUnitT);
var rightCount = (int)(math.abs(rightT - t) / sampleUnitT);
if (spline.Closed)
{
if(i == 0)
{
t_1 = spline.CurveToSplineT(spline.Count - 1);
leftT = math.lerp(1, t_1, 0.5f);
leftCount = (int)(math.abs(1 - leftT) / sampleUnitT);
}
}
else
{
if (i == 0) leftCount = 0;
if (i == spline.Count - 1) rightCount = 0;
}
for (int j = 1; j < leftCount+1; j++)
{
var tt = t - sampleUnitT*j;
if (i == 0 && spline.Closed) tt += 1;
add_smooth_sample_point(in spline, samples, tt, sampleUnitT, 1, 1);
}
for (int j = 1; j < rightCount+1; j++)
{
var tt = t + sampleUnitT*j;
add_smooth_sample_point(in spline, samples, tt, sampleUnitT, 1, 1);
}
}
// SortByT(ref samples);
samples.Sort();
// 꼭짓점 스무딩
for (int i = 0; i < samples.Length; i++)
{
var sample = samples[i];
if(sample.angle < 10) continue;
// 열린 스플라인의 시작점과 끝점에선 스무딩을 안함.
if(!spline.Closed && (i == 0 || i == samples.Length - 1)) continue;
var preSampleIdx = previous_index(i, samples.Length);
var preSample = samples[preSampleIdx];
var nextSampleIdx = next_index(i, samples.Length);
var nextSample = samples[nextSampleIdx];
var mp0 = sample.pos;
var mp1 = math.lerp(preSample.pos, nextSample.pos, 0.5f);
var tanLength = (sample.tanInLength + sample.tanOutLength);
var curvature = tanLength < math.EPSILON ? 0 : tanLength / GetWidthAt(sample.t);
curvature = 1 - math.clamp(curvature, 0, 1);
var lerp = InternalUtility.Remap(sample.angle, 0, 180, 0, curvature);
var middlePos = math.lerp(mp0, mp1, lerp);
sample.pos = middlePos;
samples[i] = sample;
}
var knots = new NativeArray<BezierKnot>(samples.Length, Allocator.Temp);
for (int i = 0; i < samples.Length; i++)
{
var sample = samples[i];
var preSamplePos = samples[previous_index(i, samples.Length)].pos;
var nextSamplePos = samples[next_index(i, samples.Length)].pos;
var knot = SplineUtility.GetAutoSmoothKnot(sample.pos, preSamplePos, nextSamplePos, sample.up);
knots[i] = knot;
}
var nSpline = new CopiedNativeSpline(knots, spline.Closed, float4x4.identity);
for (int i = 0; i < nSpline.Count; i++)
{
var knot = nSpline[i];
var t = nSpline.CurveToSplineT(i);
// nSpline.Evaluate(t, out var pos, out var tan, out var up);
var tan = nSpline.EvaluateTangent(t);
var up = keepBillboard ? new float3(0,0,-1) : nSpline.EvaluateUpVector(t);
var sample = samples[i];
sample.t = t;
sample.pos = knot.Position;
sample.tan = tan;
sample.up = up;
samples[i] = sample;
}
var tempEdgePoints = new NativeList<EdgePoint>(Allocator.Temp);
// 각 세그먼트의 EdgePoint 계산
for (int i = 0; i < samples.Length; i++)
{
var isClosingSegment = i == samples.Length - 1 && spline.Closed;
var sample0 = samples[i];
var sample1 = isClosingSegment ? samples[0] : samples[i + 1];
// 열린 스플라인의 마지막 세그먼트에선 포인트를 추가하기만 함.
// (length - 1)은 마지막 ep라서 열린 스플라인에서 마지막 세그먼트가 아님
if (i == samples.Length - 2 && !spline.Closed)
{
tempEdgePoints.Add(sample0);
tempEdgePoints.Add(sample1);
break;
}
var inTan = sample0.tan;
var outTan = sample1.tan;
var angle = InternalUtility.Angle(inTan, outTan);
var edgePointCount = (int)math.round((angle / 30f) * 5);
// 실제 Extrude에 사용할 EdgePoints 추가
tempEdgePoints.Add(sample0);
for (int j = 0; j < edgePointCount; j++)
{
var t = (float)(j + 1) / (edgePointCount + 1);
t = t.Remap(0, 1, sample0.t, isClosingSegment ? 1 : sample1.t);
var ep = GetEdgePoint(nSpline, t);
tempEdgePoints.Add(ep);
}
if(i == samples.Length - 1 && spline.Closed) tempEdgePoints.Add(sample1);
}
var clipStartAdded = false;
var clipEndAdded = false;
var shouldClipping = clipRange.x > math.EPSILON || clipRange.y < 1;
for (int i = 0; i < tempEdgePoints.Length; i++)
{
var point = tempEdgePoints[i];
if (spline.Closed && shouldClipping && point.t == 0 && clipRange.y < 1)
{
continue;
}
if(shouldClipping && (point.t < clipRange.x || point.t > clipRange.y)) continue;
if (point.t == clipRange.x)
{
edgePoints.Add(point);
clipStartAdded = true;
continue;
}
if (point.t == clipRange.y)
{
edgePoints.Add(point);
clipEndAdded = true;
continue;
}
if (clipRange.x < point.t && point.t < clipRange.y)
{
if(!clipStartAdded)
{
var ep = GetEdgePoint(nSpline, clipRange.x);
edgePoints.Add(ep);
clipStartAdded = true;
}
else
{
edgePoints.Add(point);
}
}
}
if (!clipEndAdded)
{
var ep = GetEdgePoint(nSpline, clipRange.y);
edgePoints.Add(ep);
}
}
static void SortByT(ref NativeList<EdgePoint> samples)
{
for (int i = 0; i < samples.Length - 1; i++)
{
for (int j = i + 1; j < samples.Length; j++)
{
if (samples[i].t > samples[j].t)
{
// 두 객체의 위치를 교환
(samples[i], samples[j]) = (samples[j], samples[i]);
}
}
}
}
void add_smooth_sample_point(in NativeSpline s, NativeList<EdgePoint> samples, float t, float unitT, float tanInLength, float tanOutLength)
{
var preT = InternalUtility.Repeat(t - unitT, 1);
var preTTan = s.EvaluateTangent(preT);
var nextT = InternalUtility.Repeat(t + unitT, 1);
var nextTTan = s.EvaluateTangent(nextT);
var angle = InternalUtility.Angle(preTTan, nextTTan);
var ep = GetEdgePoint(s, t, angle, tanInLength, tanOutLength);
samples.Add(ep);
}
int previous_index(int i, int maxLength)
{
if (i == 0)
{
if (spline.Closed) return maxLength - 1;
return 0;
}
return i - 1;
}
int next_index(int i, int maxLength)
{
if (i == maxLength - 1)
{
if (spline.Closed) return 0;
return i;
}
return i + 1;
}
bool is_used(float t, float unitT, in NativeList<EdgePoint> list)
{
for (int i = 0; i < list.Length; i++)
{
var diff = t.CircularDistance(list[i].t, list.Length - 1);
if (diff < unitT) return true;
}
return false;
}
void UniformEvaluate(ref NativeList<EdgePoint> edgePoints)
{
length = spline.GetLength();
var clippedLength = length * (clipRange.y - clipRange.x);
var edgeCount = math.max((int)math.ceil(clippedLength * resolution * 0.05f), 1) + 2;
for (int i = 0; i < edgeCount; i++)
{
var t = (float)i / (edgeCount - 1);
t = t.Remap(0, 1, clipRange.x, clipRange.y);
var ep = GetEdgePoint(spline, t);
edgePoints.Add(ep);
}
}
EdgePoint GetEdgePoint(in NativeSpline s, float t, float angle = 0, float tanInLength = 0, float tanOutLength = 0)
{
if (keepBillboard)
{
var pos = s.EvaluatePosition(t);
var tan = s.EvaluateTangent(t);
return new EdgePoint(t, angle, pos, tan, new float3(0,0,-1), tanInLength, tanOutLength);
}
else
{
s.Evaluate(t, out var pos, out var tan, out var up);
return new EdgePoint(t, angle, pos, tan, up, tanInLength, tanOutLength);
}
}
EdgePoint GetEdgePoint(in CopiedNativeSpline s, float t)
{
if (keepBillboard)
{
var pos = s.EvaluatePosition(t);
var tan = s.EvaluateTangent(t);
return new EdgePoint(t, 0, pos, tan, new float3(0,0,-1));
}
else
{
s.Evaluate(t, out var pos, out var tan, out var up);
return new EdgePoint(t, 0, pos, tan, up);
}
}
void Extrude(in NativeList<EdgePoint> edgePoints)
{
for (int i = 0; i < edgePoints.Length; i++)
{
var ep = edgePoints[i];
var t = ep.t;
var pos = ep.pos;
var tan = ep.tan;
var up = ep.up;
// resolve (0,0,0) tangent
if (tan is { x: 0, y: 0 })
{
var prev = i == 0 ? pos : edgePoints[^2].pos;
var next = i == edgePoints.Length - 1 ? pos : edgePoints[i + 1].pos;
tan = next - prev;
}
InternalUtility.ExtrudeEdge(
GetWidthAt(t), GetVAt(t, i), GetColorAt(t), ref pos, tan, up,
keepBillboard, keepZeroZ, uvMultiplier, uvOffset, out var v0, out var v1);
AddVert(in v0, in v1);
if (i > 0)
{
AddQuadUsingLastVertices();
}
}
}
void AddVert(in UIVertex left, in UIVertex right)
{
vertices.Add(left);
vertices.Add(right);
}
void AddQuadUsingLastVertices()
{
var vi = vertices.Length;
triangles.Add(new int3
(
vi - 2,
vi - 3,
vi - 4
));
triangles.Add(new int3
(
vi - 2,
vi - 1,
vi - 3
));
}
float GetWidthAt(float t)
{
return width * widthCurve.Evaluate(t);
}
Color GetColorAt(float t)
{
return color * colorGradient.Evaluate(t);
}
float GetVAt(float t, int i)
{
switch (uvMode)
{
case UVMode.Tile:
return length / width * t;
case UVMode.RepeatPerSegment:
return i;
case UVMode.Stretch:
return t;
default:
throw new ArgumentOutOfRangeException();
}
}
void MakeRoundEdges(in NativeList<EdgePoint> edgePoints)
{
var sl = vertices[0];
var sr = vertices[1];
var el = vertices[^2];
var er = vertices[^1];
{
// at start
var start = edgePoints[0];
var t = start.t;
var pos = start.pos;
var tan = start.tan;
var up = start.up;
var V = GetVAt(t, 0);
var uv = new float2(0, V) * uvMultiplier - uvOffset;
var clr = GetColorAt(t);
MakeRoundEdge(in pos, sl.position, sr.position, false, up, uv, clr);
}
{
// at end
var end = edgePoints[^1];
var t = end.t;
var pos = end.pos;
var tan = end.tan;
var up = end.up;
var V = GetVAt(t, edgePoints.Length - 1);
var uv = new float2(0, V) * uvMultiplier - uvOffset;
var clr = GetColorAt(t);
MakeRoundEdge(in pos, el.position, er.position, true, up, uv, clr);
}
}
void MakeRoundEdge(in float3 center, in float3 left, in float3 right, bool invert,
in float3 up, in float2 uv, in Color clr)
{
var vertexCount = resolution + 7;
var marginAngle = 180f / vertexCount;
var radius = math.length(center - left);
var axis = keepBillboard ? math.back() : up;
var arm = invert ? left - center : right - center;
var centerVertex = new UIVertex();
centerVertex.position = center;
centerVertex.uv0 = new Vector4(0.5f, 0);
centerVertex.color = clr;
vertices.Add(centerVertex);
var startIndex = vertices.Length - 1;
var toRadians =
#if ENABLE_MATHMATICS__1_3_1_OR_NEWER
math.TORADIANS;
#else
Mathf.Deg2Rad;
#endif
for (int i = 0; i <= vertexCount; i++)
{
var vector = math.rotate(quaternion.AxisAngle(axis, marginAngle * i * toRadians), arm);
vector = math.normalizesafe(vector);
var ratio = (float)i / vertexCount;
var vert = new UIVertex
{
position = center + vector * radius,
uv0 = new Vector4(0, ratio),
color = clr
};
vertices.Add(vert);
if(i > 0) triangles.Add(new int3(startIndex, startIndex + i, startIndex + i + 1));
}
}
}
[BurstCompile]
public struct EdgePoint : IComparable<EdgePoint>
{
public float t;
public readonly float angle;
public float3 pos;
public float3 tan;
public float3 up;
public readonly float tanInLength;
public readonly float tanOutLength;
public bool smoothed;
public EdgePoint(float t, float angle, float3 pos, float3 tan, float3 up, float tanInLength = 0, float tanOutLength = 0)
{
this.t = t;
this.pos = pos;
this.tan = tan;
this.up = up;
this.angle = angle;
this.tanInLength = tanInLength;
this.tanOutLength = tanOutLength;
smoothed = false;
}
public int CompareTo(EdgePoint other)
{
return t.CompareTo(other.t);
}
}
}
#endif
#endif
#endif
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c38d6e1e178241fca1d16a519603f5f2
timeCreated: 1690397815

View File

@@ -0,0 +1,19 @@
namespace UI_Spline_Renderer
{
public enum LineTexturePreset
{
Default,
UVTest,
Custom
}
public enum StartEndImagePreset
{
None,
Triangle,
Arrow,
EmptyCircle,
FilledCircle,
Custom
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b198343f753f4ee19e85f927f5633d59
timeCreated: 1690038740

View File

@@ -0,0 +1,63 @@
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Splines;
namespace UI_Spline_Renderer
{
public static class SplineExtensions
{
/// <summary>
/// Reorient a single knot to screen direction.
/// </summary>
public static void ReorientKnot(this Spline spline, int index, bool withoutNotify = false)
{
var knot = spline[index];
var rot = (Quaternion)knot.Rotation;
var forward = rot * Vector3.forward;
var projected = Vector3.ProjectOnPlane(forward, Vector3.back);
var targetRotation = Quaternion.LookRotation(projected, Vector3.back);
knot.Rotation = targetRotation;
if(withoutNotify)spline.SetKnotNoNotify(index, knot);
else spline.SetKnot(index, knot);
}
/// <summary>
/// Reorient all knots to screen direction.
/// </summary>
public static void ReorientKnots(this SplineContainer container, bool withoutNotify = false)
{
foreach (var spline in container.Splines)
{
for (int i = 0; i < spline.Count; i++)
{
ReorientKnot(spline, i, withoutNotify);
}
}
}
/// <summary>
/// Reorient all knots to screen direction and make all knots AutoSmooth.
/// </summary>
/// <param name="container"></param>
public static void ReorientKnotsAndSmooth(this SplineContainer container)
{
foreach (var spline in container.Splines)
{
for (int i = 0; i < spline.Count; i++)
{
var knot = spline[i];
var prev = i == 0 ? knot.Position : spline[i - 1].Position;
var next = i == spline.Count - 1 ? spline[i].Position : spline[i + 1].Position;
knot = SplineUtility.GetAutoSmoothKnot(knot.Position, prev, next, new float3(0, 0, -1));
spline.SetKnot(i, knot);
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4eaaadddd7604d6e828c503c60d805f7
timeCreated: 1690239751

View File

@@ -0,0 +1,46 @@
{
"name": "UISplineRenderer",
"rootNamespace": "UI_Spline_Renderer",
"references": [
"GUID:21d1eb854b91ade49bc69a263d12bee2",
"GUID:d8b63aba1907145bea998dd612889d6b",
"GUID:7ab3663edede26740845931880bf22af",
"GUID:e0cd26848372d4e5c891c569017e11f1",
"GUID:2665a8d13d1b3f18800f46e256720795"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.splines",
"expression": "",
"define": "ENABLE_SPLINES"
},
{
"name": "com.unity.collections",
"expression": "",
"define": "ENABLE_COLLECTIONS"
},
{
"name": "com.unity.mathematics",
"expression": "",
"define": "ENABLE_MATHEMATICS"
},
{
"name": "com.unity.mathematics",
"expression": "1.3.1",
"define": "ENABLE_MATHMATICS__1_3_1_OR_NEWER"
},
{
"name": "com.unity.burst",
"expression": "",
"define": "ENABLE_BURST"
}
],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8f24f501fa8e1fb48a03f1d7e6d03db4
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,28 @@
using UnityEngine;
namespace UI_Spline_Renderer
{
public class UISplineRendererSettings : ScriptableObject
{
public static UISplineRendererSettings Instance
{
get
{
if (_instance == null)
{
_instance = Resources.Load<UISplineRendererSettings>("UISplineRenderer Settings");
}
return _instance;
}
}
static UISplineRendererSettings _instance;
public Texture defaultLineTexture;
public Texture uvTestLineTexture;
public Sprite triangleHead;
public Sprite arrowHead;
public Sprite emptyCircleHead;
public Sprite filledCircleHead;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a21f54b05b414b95874ba3e272a365f0
timeCreated: 1690055132

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a6a9662ca71a5c64797955c3833d2c89
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: de2cd6c5e176d6846b6ac52585e8307b
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
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: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: d5d3eb9c021c8d440a2da201a039967c
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
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: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 60e780f6137acf848bd41ff84c4bc3df
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
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: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 6fea2bbbbb345544a81bcfff2f1b1fe1
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
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: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: db0ff1e3668afcf42a93a332c4467ae6
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
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: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 93274609ed24cbe4eb9a22db1a9a0b77
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
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: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: efadc99fe61715743ad8ea30561363be
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
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: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 6869e7e031dd5994f8572f6ebce2bdba
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
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: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 23c2331a5cac12343895afa95b9d5504
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
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: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 9a546562df1161a40b21293b5dadb11c
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 1
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
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: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant: