VR4RoboticArm2/VR4RoboticArm/Library/PackageCache/com.meta.xr.sdk.audio/editor/MetaXRAcousticGeometryEditor.cs
IonutMocanu d7aba243a2 Main
2025-09-08 11:04:02 +03:00

275 lines
12 KiB
C#

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/************************************************************************************
* Filename : MetaXRAcousticGeometryEditor.cs
* Content : Geometry editor class
Attach to geometry to define material properties
***********************************************************************************/
//#define ENABLE_DEBUG_EXPORT_OBJ
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(MetaXRAcousticGeometry))]
public class MetaXRAcousticGeometryEditor : Editor
{
private bool showAdvancedControls = false;
private bool needsRebake = false;
private void OnEnable()
{
MetaXRAcousticGeometry geo = target as MetaXRAcousticGeometry;
// Determine if the geometry needs rebaking based on time stamp.
bool isInvalid = geo.VertexCount == 0;
DateTime timeStamp = DateTime.MinValue;
string newFilePath = geo.AbsoluteFilePath;
if (newFilePath != null)
{
// Get file time stamp.
FileInfo fileInfo = new FileInfo(newFilePath);
long fileSize = fileInfo.Exists ? fileInfo.Length : 0;
timeStamp = System.IO.File.GetLastWriteTime(newFilePath);
isInvalid = isInvalid && (fileSize == 0);
}
// The .IsOlder() function can take a long time. Call it just once when GUI is enabled.
needsRebake = isInvalid ? true : geo.IsOlder(timeStamp);
}
public override void OnInspectorGUI()
{
MetaXRAcousticGeometry geo = (MetaXRAcousticGeometry)target;
EditorGUI.BeginChangeCheck();
bool newIncludeChildMeshes = EditorGUILayout.Toggle(new GUIContent("Include Child Meshes", "Include all child meshes into single geometry instance"), geo.IncludeChildMeshes);
// Update controls to change Mesh Simplification Flags
bool newEnableDiffraction = geo.EnableDiffraction;
// Use default setting for advanced parameters if the settings are hidden
float newMaxSimplifyError = geo.MaxSimplifyError;
float newMinDiffractionEdgeAngle = geo.MinDiffractionEdgeAngle;
float newMinDiffractionEdgeLength = geo.MinDiffractionEdgeLength;
float newFlagLength = geo.FlagLength;
bool newEnableMeshSimplification = geo.EnableSimplification;
int newLODSelection = geo.LodSelection;
bool newUseColliders = geo.UseColliders;
bool newOverrideExcludeTagsEnabled = geo.OverrideExcludeTagsEnabled;
string[] newOverrideExcludeTags = geo.ExcludeTags;
bool newFileEnabled = geo.FileEnabled;
bool pathChanged = false;
string newFilePath = geo.AbsoluteFilePath;
bool shouldWriteMesh = false;
showAdvancedControls = EditorGUILayout.Foldout(showAdvancedControls, "Advanced Controls");
if (showAdvancedControls)
{
EditorGUI.indentLevel++;
newUseColliders = EditorGUILayout.Toggle(new GUIContent("Use Colliders", "Use the physics MeshColliders instead of the Visual geometry."), newUseColliders);
newOverrideExcludeTagsEnabled = EditorGUILayout.Toggle(new GUIContent("Override Exclude Tags", "Override the Project Settings exclude tags to define custom exclude tags only for this geometry."), newOverrideExcludeTagsEnabled);
using (new EditorGUI.DisabledGroupScope(!newOverrideExcludeTagsEnabled))
{
newOverrideExcludeTags = MetaXRAcousticSettingsProvider.ExcludeTagAsFlagsField(newOverrideExcludeTags);
}
Separator();
EditorGUILayout.LabelField("Mesh Simplification", EditorStyles.boldLabel);
newMaxSimplifyError = EditorGUILayout.Slider(new GUIContent("Max Error", "Maximum tolerable mesh simplification error in mesh-local units"), newMaxSimplifyError, 0.0f, 1.0f);
newEnableMeshSimplification = (newMaxSimplifyError > 0.0f);
const int LOD_LEVEL_MAX = 7; // https://docs.unity3d.com/Manual/LevelOfDetail.html
newLODSelection = EditorGUILayout.IntSlider(new GUIContent("LOD", "Which LOD to use for the acoustic geometry when using an LOD Group. The lowest value of 0 corresponds to the highest quality mesh."), newLODSelection, 0, LOD_LEVEL_MAX);
Separator();
using (new EditorGUI.DisabledGroupScope(Application.isPlaying))
{
bool showFilePicker = false;
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PrefixLabel(new GUIContent("File Path:", "The path to the serialized mesh file, relative to the StreamingAssets directory"));
int indentLevelPrev = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
EditorGUILayout.LabelField(geo.RelativeFilePath, EditorStyles.wordWrappedLabel);
if (GUILayout.Button("...", GUILayout.ExpandWidth(false)))
{
// defer displaying dialog to avoid layout error
showFilePicker = true;
}
EditorGUI.indentLevel = indentLevelPrev;
}
if (showFilePicker)
{
if (!System.IO.Directory.Exists(Application.streamingAssetsPath))
{
System.IO.Directory.CreateDirectory(Application.streamingAssetsPath);
}
string directory = Application.streamingAssetsPath;
string fileName = geo.gameObject.name + "." + MetaXRAcousticGeometry.FILE_EXTENSION;
if (newFilePath != "")
{
string suggestedDirectory = System.IO.Path.GetDirectoryName(newFilePath);
while (!System.IO.Directory.Exists(suggestedDirectory))
{
suggestedDirectory = System.IO.Path.GetFullPath(suggestedDirectory + "/..");
Debug.Log($"suggest: {suggestedDirectory}");
}
directory = suggestedDirectory;
fileName = System.IO.Path.GetFileName(newFilePath);
}
newFilePath = EditorUtility.SaveFilePanel(
"Save baked mesh to file", directory, fileName,
MetaXRAcousticGeometry.FILE_EXTENSION);
// If the user canceled, use the old path.
if (string.IsNullOrEmpty(newFilePath))
newFilePath = geo.AbsoluteFilePath;
else
pathChanged = true;
}
#if ENABLE_DEBUG_EXPORT_OBJ
// this allows you to export the geometry to a .obj for viewing
// in an external model viewer for debugging/validation
if (GUILayout.Button("Write to .obj (debug)"))
{
mesh.WriteToObj();
}
#endif
}
EditorGUI.indentLevel--;
} // Advanced Controls
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PrefixLabel(" ");
shouldWriteMesh = GUILayout.Button("Bake Mesh");
}
//*****************************************************************************
// Statistics
bool isInvalid = geo.VertexCount == 0;
DateTime timeStamp = DateTime.MinValue;
EditorGUILayout.LabelField(new GUIContent("Vertices:", "The number of precomputed data points"), new GUIContent(geo.VertexCount.ToString()));
if (newFilePath != null)
{
FileInfo fileInfo = new FileInfo(newFilePath);
long fileSize = fileInfo.Exists ? fileInfo.Length : 0;
timeStamp = System.IO.File.GetLastWriteTime(newFilePath);
isInvalid = isInvalid && (fileSize == 0);
EditorGUILayout.LabelField(new GUIContent("Data Size:", "The total size of the serialized data"), new GUIContent(MetaXRAcousticMapEditor.GetSizeString(fileSize)));
}
if (isInvalid)
{
char warning = '\u26A0';
EditorGUILayout.LabelField($"{warning} Geometry contains no mesh data!", new GUIStyle
{
alignment = TextAnchor.MiddleLeft,
fontStyle = FontStyle.Bold,
wordWrap = true,
normal = new GUIStyleState { textColor = Color.yellow },
});
}
else if (needsRebake)
{
char warning = '\u24D8';
EditorGUILayout.LabelField($"{warning} Geometry stale, needs rebake!", new GUIStyle
{
alignment = TextAnchor.MiddleLeft,
fontStyle = FontStyle.Bold,
wordWrap = true,
normal = new GUIStyleState { textColor = Color.cyan },
});
}
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(geo, "Edited MetaXRAcousticGeometry");
geo.IncludeChildMeshes = newIncludeChildMeshes;
geo.FileEnabled = newFileEnabled;
geo.EnableSimplification = newEnableMeshSimplification;
geo.EnableDiffraction = newEnableDiffraction;
geo.MaxSimplifyError = newMaxSimplifyError;
geo.MinDiffractionEdgeAngle = newMinDiffractionEdgeAngle;
geo.MinDiffractionEdgeLength = newMinDiffractionEdgeLength;
geo.FlagLength = newFlagLength;
geo.LodSelection = newLODSelection;
geo.UseColliders = newUseColliders;
geo.OverrideExcludeTagsEnabled = newOverrideExcludeTagsEnabled;
if (newOverrideExcludeTags != null)
geo.OverrideExcludeTags = newOverrideExcludeTags;
if (pathChanged)
{
string prevPath = geo.AbsoluteFilePath;
string newRelativeFilePath = newFilePath.Substring(Application.dataPath.Length + 1).Replace('\\', '/');
if (File.Exists(prevPath) && string.Compare(newRelativeFilePath, geo.RelativeFilePath, true) != 0)
{
Debug.Log($"Move/rename Geometry file\n to:\t{newRelativeFilePath} from:\t{geo.RelativeFilePath}\n");
if (UnityEditor.VersionControl.Provider.isActive)
{
UnityEditor.VersionControl.Provider.Move(prevPath, newFilePath);
}
else
{
File.Move(prevPath, newFilePath);
if (File.Exists(prevPath + ".meta"))
File.Move(prevPath + ".meta", newFilePath + ".meta");
}
}
geo.AbsoluteFilePath = newFilePath;
}
if (pathChanged || shouldWriteMesh)
{
if (geo.WriteFile())
{
needsRebake = false;
}
}
}
if (Application.isPlaying && GUILayout.Button("Upload Mesh"))
{
geo.GatherGeometryRuntime();
}
}
public static void Separator()
{
GUI.color = new Color(1, 1, 1, 0.25f);
GUILayout.Box("", "HorizontalSlider", GUILayout.Height(16));
GUI.color = Color.white;
}
}