255 lines
12 KiB
C#
255 lines
12 KiB
C#
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEditorInternal;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Obi
|
|
{
|
|
|
|
/**
|
|
* Custom inspector for ObiSolver components.
|
|
* Allows particle selection and constraint edition.
|
|
*
|
|
* Selection:
|
|
*
|
|
* - To select a particle, left-click on it.
|
|
* - You can select multiple particles by holding shift while clicking.
|
|
* - To deselect all particles, click anywhere on the object except a particle.
|
|
*
|
|
* Constraints:
|
|
*
|
|
* - To edit particle constraints, select the particles you wish to edit.
|
|
* - Constraints affecting any of the selected particles will appear in the inspector.
|
|
* - To add a new pin constraint to the selected particle(s), click on "Add Pin Constraint".
|
|
*
|
|
*/
|
|
[CustomEditor(typeof(ObiSolver)), CanEditMultipleObjects]
|
|
public class ObiSolverEditor : Editor
|
|
{
|
|
|
|
[MenuItem("GameObject/3D Object/Obi/Obi Solver", false, 100)]
|
|
static void CreateObiSolver(MenuCommand menuCommand)
|
|
{
|
|
GameObject go = ObiEditorUtils.CreateNewSolver();
|
|
GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
|
|
Selection.activeGameObject = go;
|
|
}
|
|
|
|
ObiSolver solver;
|
|
|
|
SerializedProperty backend;
|
|
SerializedProperty simulateWhenInvisible;
|
|
SerializedProperty parameters;
|
|
SerializedProperty gravity;
|
|
SerializedProperty gravitySpace;
|
|
SerializedProperty worldLinearInertiaScale;
|
|
SerializedProperty worldAngularInertiaScale;
|
|
|
|
SerializedProperty distanceConstraintParameters;
|
|
SerializedProperty bendingConstraintParameters;
|
|
SerializedProperty particleCollisionConstraintParameters;
|
|
SerializedProperty particleFrictionConstraintParameters;
|
|
SerializedProperty collisionConstraintParameters;
|
|
SerializedProperty frictionConstraintParameters;
|
|
SerializedProperty skinConstraintParameters;
|
|
SerializedProperty volumeConstraintParameters;
|
|
SerializedProperty shapeMatchingConstraintParameters;
|
|
SerializedProperty tetherConstraintParameters;
|
|
SerializedProperty pinConstraintParameters;
|
|
SerializedProperty stitchConstraintParameters;
|
|
SerializedProperty densityConstraintParameters;
|
|
SerializedProperty stretchShearConstraintParameters;
|
|
SerializedProperty bendTwistConstraintParameters;
|
|
SerializedProperty chainConstraintParameters;
|
|
|
|
BooleanPreference solverFoldout;
|
|
BooleanPreference simulationFoldout;
|
|
BooleanPreference collisionsFoldout;
|
|
BooleanPreference constraintsFoldout;
|
|
|
|
GUIContent constraintLabelContent;
|
|
|
|
public void OnEnable()
|
|
{
|
|
solver = (ObiSolver)target;
|
|
constraintLabelContent = new GUIContent();
|
|
|
|
solverFoldout = new BooleanPreference($"{target.GetType()}.solverFoldout", true);
|
|
simulationFoldout = new BooleanPreference($"{target.GetType()}.simulationFoldout", false);
|
|
collisionsFoldout = new BooleanPreference($"{target.GetType()}.collisionsFoldout", false);
|
|
constraintsFoldout = new BooleanPreference($"{target.GetType()}.constraintsFoldout", false);
|
|
|
|
backend = serializedObject.FindProperty("m_Backend");
|
|
simulateWhenInvisible = serializedObject.FindProperty("simulateWhenInvisible");
|
|
parameters = serializedObject.FindProperty("parameters");
|
|
gravity = serializedObject.FindProperty("gravity");
|
|
gravitySpace = serializedObject.FindProperty("gravitySpace");
|
|
worldLinearInertiaScale = serializedObject.FindProperty("worldLinearInertiaScale");
|
|
worldAngularInertiaScale = serializedObject.FindProperty("worldAngularInertiaScale");
|
|
|
|
distanceConstraintParameters = serializedObject.FindProperty("distanceConstraintParameters");
|
|
bendingConstraintParameters = serializedObject.FindProperty("bendingConstraintParameters");
|
|
particleCollisionConstraintParameters = serializedObject.FindProperty("particleCollisionConstraintParameters");
|
|
particleFrictionConstraintParameters = serializedObject.FindProperty("particleFrictionConstraintParameters");
|
|
collisionConstraintParameters = serializedObject.FindProperty("collisionConstraintParameters");
|
|
frictionConstraintParameters = serializedObject.FindProperty("frictionConstraintParameters");
|
|
skinConstraintParameters = serializedObject.FindProperty("skinConstraintParameters");
|
|
volumeConstraintParameters = serializedObject.FindProperty("volumeConstraintParameters");
|
|
shapeMatchingConstraintParameters = serializedObject.FindProperty("shapeMatchingConstraintParameters");
|
|
tetherConstraintParameters = serializedObject.FindProperty("tetherConstraintParameters");
|
|
pinConstraintParameters = serializedObject.FindProperty("pinConstraintParameters");
|
|
stitchConstraintParameters = serializedObject.FindProperty("stitchConstraintParameters");
|
|
densityConstraintParameters = serializedObject.FindProperty("densityConstraintParameters");
|
|
stretchShearConstraintParameters = serializedObject.FindProperty("stretchShearConstraintParameters");
|
|
bendTwistConstraintParameters = serializedObject.FindProperty("bendTwistConstraintParameters");
|
|
chainConstraintParameters = serializedObject.FindProperty("chainConstraintParameters");
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
|
|
serializedObject.UpdateIfRequiredOrScript();
|
|
EditorGUILayout.HelpBox("Particles:" + solver.allocParticleCount +"\n"+
|
|
"Simplices:" + solver.simplexCounts.simplexCount+"\n" +
|
|
"Contacts:" + solver.contactCount + "\n" +
|
|
"Simplex contacts:" + solver.particleContactCount, MessageType.None);
|
|
|
|
solverFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(solverFoldout, "Solver settings");
|
|
if (solverFoldout)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
EditorGUILayout.PropertyField(backend);
|
|
|
|
#if !(OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
|
|
if (backend.enumValueIndex == (int)ObiSolver.BackendType.Burst)
|
|
EditorGUILayout.HelpBox("The Burst backend depends on the following packages: Mathematics, Collections, Jobs and Burst. The default backend (Oni) will be used instead, if possible.", MessageType.Warning);
|
|
#endif
|
|
#if !(OBI_ONI_SUPPORTED)
|
|
if (backend.enumValueIndex == (int)ObiSolver.BackendType.Oni)
|
|
EditorGUILayout.HelpBox("The Oni backend is not compatible with the target platform. Please switch to a compatible platform, or use the Burst backend instead.", MessageType.Warning);
|
|
#endif
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
serializedObject.ApplyModifiedProperties();
|
|
foreach (var t in targets)
|
|
(t as ObiSolver).UpdateBackend();
|
|
}
|
|
|
|
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("mode"));
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("interpolation"));
|
|
}
|
|
EditorGUILayout.EndFoldoutHeaderGroup();
|
|
|
|
simulationFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(simulationFoldout, "Simulation settings");
|
|
if (simulationFoldout)
|
|
{
|
|
EditorGUILayout.PropertyField(gravitySpace);
|
|
EditorGUILayout.PropertyField(gravity);
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("sleepThreshold"));
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("damping"));
|
|
EditorGUILayout.PropertyField(worldLinearInertiaScale);
|
|
EditorGUILayout.PropertyField(worldAngularInertiaScale);
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("maxAnisotropy"));
|
|
EditorGUILayout.PropertyField(simulateWhenInvisible);
|
|
}
|
|
EditorGUILayout.EndFoldoutHeaderGroup();
|
|
|
|
collisionsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(collisionsFoldout, "Collision settings");
|
|
if (collisionsFoldout)
|
|
{
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("continuousCollisionDetection"));
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("collisionMargin"));
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("maxDepenetration"));
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("shockPropagation"));
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("surfaceCollisionIterations"));
|
|
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("surfaceCollisionTolerance"));
|
|
}
|
|
EditorGUILayout.EndFoldoutHeaderGroup();
|
|
|
|
constraintsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(constraintsFoldout, "Constraint settings");
|
|
if (constraintsFoldout)
|
|
{
|
|
constraintLabelContent.text = "Distance";
|
|
EditorGUILayout.PropertyField(distanceConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Bending";
|
|
EditorGUILayout.PropertyField(bendingConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Particle collision / Queries";
|
|
EditorGUILayout.PropertyField(particleCollisionConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Particle friction";
|
|
EditorGUILayout.PropertyField(particleFrictionConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Collision";
|
|
EditorGUILayout.PropertyField(collisionConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Friction";
|
|
EditorGUILayout.PropertyField(frictionConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Skin";
|
|
EditorGUILayout.PropertyField(skinConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Volume";
|
|
EditorGUILayout.PropertyField(volumeConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Shape matching";
|
|
EditorGUILayout.PropertyField(shapeMatchingConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Tether";
|
|
EditorGUILayout.PropertyField(tetherConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Pin";
|
|
EditorGUILayout.PropertyField(pinConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Stitch";
|
|
EditorGUILayout.PropertyField(stitchConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Density";
|
|
EditorGUILayout.PropertyField(densityConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Stretch & Shear";
|
|
EditorGUILayout.PropertyField(stretchShearConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Bend & Twist";
|
|
EditorGUILayout.PropertyField(bendTwistConstraintParameters, constraintLabelContent);
|
|
|
|
constraintLabelContent.text = "Chain";
|
|
EditorGUILayout.PropertyField(chainConstraintParameters, constraintLabelContent);
|
|
}
|
|
EditorGUILayout.EndFoldoutHeaderGroup();
|
|
|
|
// Apply changes to the serializedProperty
|
|
if (GUI.changed)
|
|
{
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
solver.PushSolverParameters();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.InSelectionHierarchy | GizmoType.Selected)]
|
|
static void DrawGizmoForSolver(ObiSolver solver, GizmoType gizmoType)
|
|
{
|
|
|
|
if ((gizmoType & GizmoType.InSelectionHierarchy) != 0)
|
|
{
|
|
|
|
Gizmos.color = new Color(1, 1, 1, 0.5f);
|
|
Bounds bounds = solver.Bounds;
|
|
Gizmos.DrawWireCube(bounds.center, bounds.size);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|