This repository has been archived on 2025-04-28. You can view files and clone it, but cannot push or open issues or pull requests.
ARPlusSystem/ARPlusSystem-250418/Library/PackageCache/com.unity.xr.arsubsystems@4.../Editor/XRReferenceImageLibraryEdit...

308 lines
12 KiB
C#
Raw Normal View History

using System;
using UnityEngine;
using UnityEditor.XR.ARSubsystems.InternalBridge;
using UnityEngine.XR.ARSubsystems;
namespace UnityEditor.XR.ARSubsystems
{
[CustomEditor(typeof(XRReferenceImageLibrary))]
class XRReferenceImageLibraryEditor : Editor
{
static class Content
{
static readonly int s_AddImageControlId;
static readonly GUIContent s_AddButtonContent;
static readonly GUIContent s_RemoveButtonContent;
static Content()
{
s_AddButtonContent = new GUIContent("Add Image");
s_AddImageControlId = GUIUtility.GetControlID(s_AddButtonContent, FocusType.Keyboard);
s_RemoveButtonContent = new GUIContent(
string.Empty,
EditorGUIUtility.FindTexture("d_winbtn_win_close"),
"Remove this image from the database");
}
public static readonly GUIContent keepTexture = new GUIContent(
"Keep Texture at Runtime",
"If enabled, the texture will be available in the Player. Otherwise, the texture will be null in the Player.");
public static readonly GUIContent name = new GUIContent(
"Name",
"The name of the reference image. This can useful for matching detected images with their reference image at runtime.");
public static readonly GUIContent specifySize = new GUIContent(
"Specify Size",
"If enabled, you can specify the physical dimensions of the image in meters. Some platforms require this.");
public static readonly GUIContent sizePixels = new GUIContent(
"Texture Size (pixels)",
"The texture dimensions, in pixels.");
public static readonly GUIContent sizeMeters = new GUIContent(
"Physical Size (meters)",
"The dimensions of the physical image, in meters.");
public static int addImageControlId
{
get
{
return s_AddImageControlId;
}
}
public static bool addButton
{
get
{
return GUILayout.Button(s_AddButtonContent);
}
}
public static bool removeButton
{
get
{
return GUI.Button(
GUILayoutUtility.GetRect(s_RemoveButtonContent, GUI.skin.button, GUILayout.ExpandWidth(false)),
s_RemoveButtonContent,
GUI.skin.button);
}
}
}
SerializedProperty m_ReferenceImages;
void OnEnable()
{
m_ReferenceImages = serializedObject.FindProperty("m_Images");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
int indexToRemove = -1;
for (int i = 0; i < m_ReferenceImages.arraySize; ++i)
{
var shouldRemove = ReferenceImageField(i);
if (shouldRemove)
{
indexToRemove = i;
}
EditorGUILayout.Separator();
if (i < m_ReferenceImages.arraySize - 1)
EditorGUILayout.LabelField(string.Empty, GUI.skin.horizontalSlider);
}
if (indexToRemove > -1)
m_ReferenceImages.DeleteArrayElementAtIndex(indexToRemove);
serializedObject.ApplyModifiedProperties();
if (Content.addButton)
{
Undo.RecordObject(target, "Add reference image");
(target as XRReferenceImageLibrary).Add();
EditorUtility.SetDirty(target);
}
}
/// <summary>
/// Generates the GUI for a reference image at index <paramref name="index"/>.
/// </summary>
/// <param name="index">The index of the reference image in the <see cref="XRReferenceImageLibrary"/>.</param>
/// <returns>True if the image should be removed.</returns>
bool ReferenceImageField(int index)
{
var library = target as XRReferenceImageLibrary;
var referenceImageProperty = m_ReferenceImages.GetArrayElementAtIndex(index);
var sizeProperty = referenceImageProperty.FindPropertyRelative("m_Size");
var specifySizeProperty = referenceImageProperty.FindPropertyRelative("m_SpecifySize");
var nameProperty = referenceImageProperty.FindPropertyRelative("m_Name");
var referenceImage = library[index];
var texturePath = AssetDatabase.GUIDToAssetPath(referenceImage.textureGuid.ToString("N"));
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath);
bool shouldRemove = false;
bool wasTextureUpdated = false;
using (new EditorGUILayout.HorizontalScope())
{
using (var textureCheck = new EditorGUI.ChangeCheckScope())
{
texture = TextureField(texture);
wasTextureUpdated = textureCheck.changed;
}
shouldRemove = Content.removeButton;
}
EditorGUILayout.PropertyField(nameProperty, Content.name);
EditorGUILayout.PropertyField(specifySizeProperty, Content.specifySize);
if (specifySizeProperty.boolValue)
{
using (new EditorGUI.IndentLevelScope())
{
using (new EditorGUI.DisabledScope(true))
{
var imageDimensions = (texture == null) ? Vector2Int.zero : GetTextureSize(texture);
EditorGUILayout.Vector2IntField(Content.sizePixels, imageDimensions);
}
using (var changeCheck = new EditorGUI.ChangeCheckScope())
{
EditorGUILayout.PropertyField(sizeProperty, Content.sizeMeters);
// Prevent dimensions from going below zero.
var size = new Vector2(
Mathf.Max(0f, sizeProperty.vector2Value.x),
Mathf.Max(0f, sizeProperty.vector2Value.y));
if ((sizeProperty.vector2Value.x < 0f) ||
(sizeProperty.vector2Value.y < 0f))
{
sizeProperty.vector2Value = size;
}
if (changeCheck.changed)
{
if (texture == null)
{
// If the texture is null, then we just set whatever the user specifies
sizeProperty.vector2Value = size;
}
else
{
// Otherwise, maintain the aspect ratio
var delta = referenceImage.size - size;
delta = new Vector2(Mathf.Abs(delta.x), Mathf.Abs(delta.y));
// Determine which dimension has changed and compute the unchanged dimension
if (delta.x > delta.y)
{
sizeProperty.vector2Value = SizeFromWidth(texture, size);
}
else if (delta.y > 0f)
{
sizeProperty.vector2Value = SizeFromHeight(texture, size);
}
}
}
else if (wasTextureUpdated && texture != null)
{
// If the texture changed, re-compute width / height
if (size.x == 0f)
{
sizeProperty.vector2Value = SizeFromHeight(texture, size);
}
else
{
sizeProperty.vector2Value = SizeFromWidth(texture, size);
}
}
}
if ((sizeProperty.vector2Value.x <= 0f) || (sizeProperty.vector2Value.y <= 0f))
{
EditorGUILayout.HelpBox("Dimensions must be greater than zero.", MessageType.Warning);
}
}
}
using (new EditorGUI.DisabledScope(texture == null))
using (var changeCheck = new EditorGUI.ChangeCheckScope())
{
bool keepTexture = EditorGUILayout.Toggle(Content.keepTexture, referenceImage.texture != null);
if (changeCheck.changed || wasTextureUpdated)
{
// Auto-populate the name from the texture's name if it is not set already.
if (string.IsNullOrEmpty(nameProperty.stringValue) && texture != null)
{
nameProperty.stringValue = texture.name;
}
// Apply properties for anything that may have been modified, otherwise
// the texture change may be overwritten.
serializedObject.ApplyModifiedProperties();
// Create an undo entry, modify, set dirty
Undo.RecordObject(target, "Update reference image texture");
library.SetTexture(index, texture, keepTexture);
EditorUtility.SetDirty(target);
}
}
return shouldRemove;
}
/// <summary>
/// Computes a new size using the width and aspect ratio from the Texture2D.
/// Width remains the same as before; height is recalculated.
/// </summary>
static Vector2 SizeFromWidth(Texture2D texture, Vector2 size)
{
var textureSize = GetTextureSize(texture);
return new Vector2(size.x, size.x * (float)textureSize.y / (float)textureSize.x);
}
/// <summary>
/// Computes a new size using the height and aspect ratio from the Texture2D.
/// Height remains the same as before; width is recalculated.
/// </summary>
static Vector2 SizeFromHeight(Texture2D texture, Vector2 size)
{
var textureSize = GetTextureSize(texture);
return new Vector2(size.y * (float)textureSize.x / (float)textureSize.y, size.y);
}
static Vector2Int GetTextureSize(Texture2D texture)
{
if (texture == null)
throw new ArgumentNullException(nameof(texture));
var textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter;
if (textureImporter == null)
{
return new Vector2Int(texture.width, texture.height);
}
else
{
#if UNITY_2021_2_OR_NEWER
textureImporter.GetSourceTextureWidthAndHeight(out var width, out var height);
return new Vector2Int(width, height);
#else
return TextureImporterInternals.GetSourceTextureDimensions(textureImporter);
#endif
}
}
static Texture2D TextureField(Texture2D texture)
{
const int k_MaxSideLength = 64;
int width = k_MaxSideLength, height = k_MaxSideLength;
if (texture != null)
{
var textureSize = GetTextureSize(texture);
if (textureSize.x > textureSize.y)
height = width * textureSize.y / textureSize.x;
else
width = height * textureSize.x / textureSize.y;
}
return (Texture2D)EditorGUILayout.ObjectField(
texture,
typeof(Texture2D),
true,
GUILayout.Width(width),
GUILayout.Height(height));
}
}
}