Files
HauntedBloodlines/Assets/Obi/Editor/Common/Solver/ObiSolverEditor.cs
2025-05-29 22:31:40 +03:00

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);
}
}
}
}