修改mesh

This commit is contained in:
2025-11-04 23:11:56 +08:00
parent 32f07eb14e
commit e8f6308580
93 changed files with 1587 additions and 491 deletions

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace NBF
{
public class DisableInPlayModeAttribute : PropertyAttribute
{
public DisableInPlayModeAttribute()
{ }
}
}

View File

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

View File

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

View File

@@ -0,0 +1,44 @@
using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;
namespace NBF
{
[CustomPropertyDrawer(typeof(DisableInPlayModeAttribute))]
public class BeginLockInPlayModeDecoratorDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property, label, true);
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var playing = Application.isPlaying;
if (playing)
{
GUI.enabled = false;
}
var ranges = fieldInfo.GetCustomAttributes(typeof(RangeAttribute), true);
var range = ranges != null && ranges.Length > 0 ? ranges[0] as RangeAttribute : null;
if (range != null && property.propertyType == SerializedPropertyType.Float)
{
EditorGUI.Slider(position, property, range.min, range.max);
}
else if (range != null && property.propertyType == SerializedPropertyType.Integer)
{
EditorGUI.IntSlider(position, property, (int)range.min, (int)range.max);
}
else
{
EditorGUI.PropertyField(position, property, label, true);
}
if (playing)
{
GUI.enabled = true;
}
}
}
}

View File

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

View File

@@ -0,0 +1,80 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using Unity.Collections;
using Unity.Mathematics;
namespace NBF
{
[CustomEditor(typeof(Rope)), CanEditMultipleObjects]
public class RopeEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
}
public void OnSceneGUI()
{
if (Application.isPlaying)
{
return;
}
var rope = target as Rope;
if (rope == null)
{
return;
}
// Draw floating window with buttons
if (Selection.objects.Length == 1)
{
Handles.BeginGUI();
GUI.skin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene);
var lastSpawn = rope.spawnPoints.Count > 0 ? rope.spawnPoints[rope.spawnPoints.Count - 1] : float3.zero;
var location = HandleUtility.WorldToGUIPoint(rope.transform.TransformPoint(lastSpawn)) + Vector2.right * 64.0f;
GUILayout.Window(0, new Rect(location, Vector2.one), (id) =>
{
if (GUILayout.Button("Push spawn point"))
{
Undo.RecordObject(rope, "Push Rope Spawn Point");
rope.PushSpawnPoint();
}
if (rope.spawnPoints.Count > 2 && GUILayout.Button("Pop spawn point"))
{
Undo.RecordObject(rope, "Pop Rope Spawn Point");
rope.PopSpawnPoint();
}
}, rope.gameObject.name);
Handles.EndGUI();
}
// Draw position handles
Handles.color = Rope.Colors.spawnPointHandle;
for (int i = 0; i < rope.spawnPoints.Count; i++)
{
var spawnPoint = rope.spawnPoints[i];
var position = rope.transform.TransformPoint(spawnPoint);
EditorGUI.BeginChangeCheck();
if (Event.current.modifiers.HasFlag(EventModifiers.Shift))
{
position = Handles.PositionHandle(position, Quaternion.identity);
}
else
{
var fmh_69_65_638978072337815361 = Quaternion.identity; position = Handles.FreeMoveHandle(position, rope.radius * 4.0f, Vector3.one * 0.5f, Handles.SphereHandleCap);
}
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(rope, "Move Rope Spawn Point");
spawnPoint = rope.transform.InverseTransformPoint(position);
rope.spawnPoints[i] = spawnPoint;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,206 @@
using UnityEngine;
using Unity.Mathematics;
using Unity.Collections;
using System.Collections.Generic;
using System.Linq;
namespace NBF
{
public static class PointsExtensions
{
// Curve length
public static float GetLengthOfCurve(this NativeArray<float3> curve, ref float4x4 transform, bool isLoop = false)
{
if (curve == null || curve.Length == 0)
{
return 0.0f;
}
var sum = 0.0f;
var firstPoint = math.mul(transform, new float4(curve[0], 1.0f)).xyz;
var lastPoint = firstPoint;
for (int i = 1; i < curve.Length; i++)
{
var point = math.mul(transform, new float4(curve[i], 1.0f)).xyz;
sum += math.distance(lastPoint, point);
lastPoint = point;
}
if (isLoop)
{
sum += math.distance(lastPoint, firstPoint);
}
return sum;
}
public static float GetLengthOfCurve(this NativeArray<float3> curve, bool isLoop = false)
{
var transform = float4x4.identity;
return curve.GetLengthOfCurve(ref transform, isLoop);
}
public static float GetLengthOfCurve(this IEnumerable<float3> curve, ref float4x4 transform, bool isLoop = false)
{
var array = new NativeArray<float3>(curve.ToArray(), Allocator.Temp);
var sum = array.GetLengthOfCurve(ref transform, isLoop);
array.Dispose();
return sum;
}
public static float GetLengthOfCurve(this IEnumerable<float3> curve, bool isLoop = false)
{
var transform = float4x4.identity;
return curve.GetLengthOfCurve(ref transform, isLoop);
}
// Curve points
private static void GetPointAlongCurve(this NativeArray<float3> curve, ref float4x4 transform, float distance, out float3 point, ref int currentTargetIndex, ref float accumulatedLength)
{
if (curve.Length < 2)
{
throw new System.ArgumentException(nameof(curve));
}
if (currentTargetIndex < 1 || currentTargetIndex >= curve.Length)
{
throw new System.ArgumentOutOfRangeException(nameof(currentTargetIndex));
}
var previousTarget = curve[currentTargetIndex - 1];
while (currentTargetIndex < curve.Length)
{
var target = curve[currentTargetIndex];
var segmentLength = math.distance(previousTarget, target);
if (distance <= accumulatedLength + segmentLength)
{
var interpolated = math.lerp(previousTarget, target, (distance - accumulatedLength) / segmentLength);
point = math.mul(transform, new float4(interpolated, 1.0f)).xyz;
return;
}
currentTargetIndex++;
accumulatedLength += segmentLength;
previousTarget = target;
}
// numerical precision made this happen, just return last point
currentTargetIndex = curve.Length - 1;
point = math.mul(transform, new float4(previousTarget, 1.0f)).xyz;
}
public static void GetPointAlongCurve(this NativeArray<float3> curve, ref float4x4 transform, float distance, out float3 point)
{
var currentTargetIndex = 1;
var accumulatedLength = 0.0f;
curve.GetPointAlongCurve(ref transform, distance, out point, ref currentTargetIndex, ref accumulatedLength);
}
public static void GetPointAlongCurve(this NativeArray<float3> curve, float distance, out float3 point)
{
var transform = float4x4.identity;
curve.GetPointAlongCurve(ref transform, distance, out point);
}
public static void GetPointAlongCurve(this IEnumerable<float3> curve, ref float4x4 transform, float distance, out float3 point)
{
var array = new NativeArray<float3>(curve.ToArray(), Allocator.Temp);
array.GetPointAlongCurve(ref transform, distance, out point);
array.Dispose();
}
public static void GetPointAlongCurve(this IEnumerable<float3> curve, float distance, out float3 point)
{
var transform = float4x4.identity;
curve.GetPointAlongCurve(ref transform, distance, out point);
}
public static void GetPointsAlongCurve(this NativeArray<float3> curve, ref float4x4 transform, float desiredPointDistance, NativeArray<float3> result)
{
var currentTargetIndex = 1;
var accumulatedLength = 0.0f;
for (int i = 0; i < result.Length; i++)
{
curve.GetPointAlongCurve(ref transform, desiredPointDistance * i, out float3 point, ref currentTargetIndex, ref accumulatedLength);
result[i] = point;
}
}
public static void GetPointsAlongCurve(this NativeArray<float3> curve, float desiredPointDistance, NativeArray<float3> result)
{
var transform = float4x4.identity;
curve.GetPointsAlongCurve(ref transform, desiredPointDistance, result);
}
public static void GetPointsAlongCurve(this IEnumerable<float3> curve, ref float4x4 transform, float desiredPointDistance, NativeArray<float3> result)
{
var array = new NativeArray<float3>(curve.ToArray(), Allocator.Temp);
array.GetPointsAlongCurve(ref transform, desiredPointDistance, result);
array.Dispose();
}
public static void GetPointsAlongCurve(this IEnumerable<float3> curve, float desiredPointDistance, NativeArray<float3> result)
{
var transform = float4x4.identity;
curve.GetPointsAlongCurve(ref transform, desiredPointDistance, result);
}
// Closest point
public static void GetClosestPoint(this NativeArray<float3> curve, float3 point, out int index, out float distance)
{
index = 0;
var closestDistanceSq = math.distancesq(curve[0], point);
for (int i = 1; i < curve.Length; i++)
{
var distSq = math.distancesq(curve[i], point);
if (distSq < closestDistanceSq)
{
index = i;
closestDistanceSq = distSq;
}
}
distance = math.sqrt(closestDistanceSq);
}
public static void GetClosestPoint(this NativeArray<float3> curve, Ray ray, out int index, out float distance, out float distanceAlongRay)
{
index = 0;
var origin = (float3)ray.origin;
var dir = math.normalizesafe(ray.direction);
var closestDistanceAlongRay = math.dot(curve[0] - origin, dir);
var closestDistanceSq = math.distancesq(origin + closestDistanceAlongRay * dir, curve[0]);
for (int i = 1; i < curve.Length; i++)
{
var position = curve[i];
var rayDist = math.dot(position - origin, dir);
var distSq = math.distancesq(origin + rayDist * dir, position);
if (distSq < closestDistanceSq)
{
index = i;
closestDistanceAlongRay = rayDist;
closestDistanceSq = distSq;
}
}
distance = math.sqrt(closestDistanceSq);
distanceAlongRay = closestDistanceAlongRay;
}
// Distance
public static void KeepAtDistance(this ref float3 point, ref float3 otherPoint, float distance, float stiffness = 1.0f)
{
var delta = otherPoint - point;
var currentDistance = math.length(delta);
if (currentDistance > 0.0f)
{
delta /= currentDistance;
}
else
{
delta = float3.zero;
}
delta *= (currentDistance - distance) * stiffness;
point += delta;
otherPoint -= delta;
}
}
}

View File

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

View File

@@ -0,0 +1,92 @@
using UnityEngine;
using Unity.Mathematics;
using Unity.Collections;
using System.Collections.Generic;
using System.Linq;
namespace NBF
{
public static class RigidbodyExtensions
{
public static void GetLocalInertiaTensor(this Rigidbody rb, out float3x3 localInertiaTensor)
{
var rot = new float3x3(rb.inertiaTensorRotation);
var invRot = math.transpose(rot);
localInertiaTensor = math.mul(math.mul(rot, float3x3.Scale(rb.inertiaTensor)), invRot);
}
public static void GetInertiaTensor(this Rigidbody rb, out float3x3 inertiaTensor)
{
rb.GetLocalInertiaTensor(out float3x3 localInertiaTensor);
var rot = new float3x3(rb.rotation);
var invRot = math.transpose(rot);
inertiaTensor = math.mul(math.mul(rot, localInertiaTensor), invRot);
}
public static void GetInvInertiaTensor(this Rigidbody rb, out float3x3 invInertiaTensor)
{
rb.GetLocalInertiaTensor(out float3x3 localTensor);
float3x3 invLocalTensor = float3x3.zero;
if (math.determinant(localTensor) != 0.0f)
{
invLocalTensor = math.inverse(localTensor);
}
var rot = new float3x3(rb.rotation);
var invRot = math.transpose(rot);
invInertiaTensor = math.mul(math.mul(rot, invLocalTensor), invRot);
}
public static void ApplyImpulseNow(this Rigidbody rb, ref float3x3 invInertiaTensor, float3 point, float3 impulse)
{
if (rb.mass == 0.0f)
{
return;
}
var relativePoint = point - (float3)rb.worldCenterOfMass;
var angularMomentumChange = math.cross(relativePoint, impulse);
var angularVelocityChange = math.mul(invInertiaTensor, angularMomentumChange);
rb.linearVelocity += (Vector3)impulse / rb.mass;
rb.angularVelocity += (Vector3)angularVelocityChange;
}
public static void ApplyImpulseNow(this Rigidbody rb, float3 point, float3 impulse)
{
rb.GetInvInertiaTensor(out float3x3 invInertiaTensor);
rb.ApplyImpulseNow(ref invInertiaTensor, point, impulse);
}
public static void SetPointVelocityNow(this Rigidbody rb, ref float3x3 invInertiaTensor, float3 point, float3 normal, float desiredSpeed, float damping = 1.0f)
{
if (rb.mass == 0.0f)
{
return;
}
var velocityChange = desiredSpeed - math.dot(rb.GetPointVelocity(point), normal) * damping;
var relativePoint = point - (float3)rb.worldCenterOfMass;
var denominator = (1.0f / rb.mass) + math.dot(math.cross(math.mul(invInertiaTensor, math.cross(relativePoint, normal)), relativePoint), normal);
if (denominator == 0.0f)
{
return;
}
var j = velocityChange / denominator;
rb.ApplyImpulseNow(ref invInertiaTensor, point, j * normal);
}
public static void SetPointVelocityNow(this Rigidbody rb, float3 point, float3 normal, float desiredSpeed, float damping = 1.0f)
{
rb.GetInvInertiaTensor(out float3x3 invInertiaTensor);
rb.SetPointVelocityNow(ref invInertiaTensor, point, normal, desiredSpeed, damping);
}
}
}

View File

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