Files
AR-Menu/Library/PackageCache/com.needle.engine-exporter@8c046140a1d9/Samples/SampleInfo.cs
2025-11-30 08:35:03 +02:00

245 lines
7.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.IO;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using Needle.Engine.Utils;
using Newtonsoft.Json;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
using UnityEngine.UIElements;
namespace Needle.Engine.Samples
{
[CreateAssetMenu(menuName = "Needle Engine/Samples/Sample Info")]
internal class SampleInfo : ScriptableObject
{
[UsedImplicitly]
public string Name
{
get => DisplayNameOrName;
set => DisplayName = value;
}
[Serializable]
public class ComponentList
{
public string Component;
public string Path;
public string MoreInfoUrl;
}
[JsonIgnore]
public string DisplayName;
public string Description;
public Texture2D Thumbnail;
[JsonIgnore]
public SceneAsset Scene;
public string LiveUrl;
public int Priority;
[JsonIgnore]
public string DisplayNameOrName => !string.IsNullOrWhiteSpace(DisplayName) ? DisplayName : ObjectNames.NicifyVariableName(name);
public Tag[] Tags;
[JsonIgnore][HideInInspector]
public SampleInfo reference;
public ComponentList[] UsedComponents;
/// <summary>
/// Git directory relative path to the scene
/// </summary>
[JsonProperty("ReadmeUrl")]
private string ReadmeUrl
{
get
{
if (!Scene) return "";
var sceneAssetPath = AssetDatabase.GetAssetPath(Scene);
if (sceneAssetPath == null)
{
Debug.LogError("Missing scene asset path...", this);
return "";
}
return Constants.RepoRoot + MakeGitDirectoryRelative(sceneAssetPath) + "/README.md";
}
}
private string MakeGitDirectoryRelative(string str)
{
var abs = Path.GetDirectoryName(Path.GetFullPath(str))?.Replace("\\", "/");
var dirInfo = new FileInfo(str).Directory;
var gitDirectory = dirInfo;
while (gitDirectory != null && gitDirectory.Exists)
{
var fileOrDir = gitDirectory.GetFileSystemInfos(".git");
if (fileOrDir.Length > 0)
{
break;
}
gitDirectory = gitDirectory.Parent;
}
var gitPath = gitDirectory?.FullName.Replace("\\", "/");
var gitRelative = abs.Substring(gitPath!.Length);
while (gitRelative.StartsWith("/"))
gitRelative = gitRelative.Substring(1);
return gitRelative;
}
private void OnValidate()
{
if (!Scene)
{
var path = AssetDatabase.GetAssetPath(this);
if (string.IsNullOrWhiteSpace(path)) return;
var scenes = AssetDatabase.FindAssets("t:SceneAsset", new[] { Path.GetDirectoryName(path) });
foreach (var guid in scenes)
{
var scene = AssetDatabase.LoadAssetAtPath<SceneAsset>(AssetDatabase.GUIDToAssetPath(guid));
Scene = scene;
if (scene)
break;
}
}
}
#if UNITY_EDITOR
[OnOpenAsset(100)]
private static bool OpenAsset(int instanceID, int line)
{
// Handle SampleInfo assets
if (EditorUtility.InstanceIDToObject(instanceID) is SampleInfo sampleInfo)
{
SamplesWindow.OpenScene(sampleInfo.Scene);
return true;
}
// Handle scenes that are part of a sample / immutable
if (EditorUtility.InstanceIDToObject(instanceID) is SceneAsset sceneAsset)
{
var scenePath = AssetDatabase.GetAssetPath(sceneAsset);
if (PackageUtils.IsMutable(scenePath))
return false;
SamplesWindow.OpenScene(sceneAsset);
return true;
}
return false;
}
#endif
public override string ToString()
{
return DisplayNameOrName + " " + name;
}
#if UNITY_EDITOR
[ContextMenu("Open local Readme")]
void OpenReadme()
{
var readmeFile = Path.GetDirectoryName(AssetDatabase.GetAssetPath(Scene)) + "/README.md";
if (!File.Exists(readmeFile)) return;
AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath<TextAsset>(readmeFile));
}
#endif
}
#if UNITY_EDITOR
[CustomEditor(typeof(SampleInfo), true)]
[CanEditMultipleObjects]
class SampleInfoEditor : Editor
{
public override VisualElement CreateInspectorGUI()
{
// if we have multiple sample assets selected just use the default inspector (for editing multiple tags at once)
if (targets.Length > 1) return null;
var t = target as SampleInfo;
if (!t) return new Label("<null>");
var isSubAsset = AssetDatabase.IsSubAsset(t);
var v = new VisualElement();
foreach (var style in SamplesWindow.StyleSheet)
v.styleSheets.Add(style);
if (!EditorGUIUtility.isProSkin) v.AddToClassList("__light");
var sample = new SamplesWindow.Sample(t);
sample.style.marginLeft = -10;
sample.style.marginRight = -10;
v.Add(sample);
var readmeFile = Path.GetDirectoryName(AssetDatabase.GetAssetPath(t.Scene)) + "/README.md";
var readmeText = File.ReadAllText(readmeFile);
var readmeRichText = ConvertMarkdownToRichText(readmeText);
GUIStyle _readmeStyle = null;
var label = new IMGUIContainer(() =>
{
if (_readmeStyle == null)
{
_readmeStyle= new GUIStyle(GUI.skin.label);
_readmeStyle.wordWrap = true;
_readmeStyle.richText = true;
_readmeStyle.fixedHeight = 0;
_readmeStyle.stretchHeight = true;
}
// Links are not clickable here for some reason...
// with SelectableLabel they are, but then the layout is messed up.
var content = new GUIContent(readmeRichText);
GUILayout.Label(content.text, _readmeStyle);
});
if (!isSubAsset)
{
var container = new IMGUIContainer(() => DrawDefaultInspector());
container.style.marginTop = 20;
v.Add(container);
// Show the readme text
v.Add(label);
}
else
v.style.maxHeight = 500;
return v;
}
// Copied from Readme.cs (different packages)
public static string ConvertMarkdownToRichText(string markdown)
{
// Convert headers
markdown = Regex.Replace(markdown, @"^#\s+(.+)$", "<b><size=24>$1</size></b>", RegexOptions.Multiline);
markdown = Regex.Replace(markdown, @"^##\s+(.+)$", "<b><size=16>$1</size></b>", RegexOptions.Multiline);
markdown = Regex.Replace(markdown, @"^###\s+(.+)$", "<b><size=12>$1</size></b>", RegexOptions.Multiline);
// Convert bold
markdown = Regex.Replace(markdown, @"\*\*(.+?)\*\*", "<b>$1</b>");
markdown = Regex.Replace(markdown, @"__(.+?)__", "<b>$1</b>");
// Convert italic
markdown = Regex.Replace(markdown, @"\*(.+?)\*", "<i>$1</i>");
//markdown = Regex.Replace(markdown, @"_(.+?)_", "<i>$1</i>"); // fails?
// Convert block
markdown = Regex.Replace(markdown, @"```([^`]+)```", "<color=#7894bf><i>\n-----$1-----\n</i></color>");
// Convert inline-block
markdown = Regex.Replace(markdown, @"\`(.+?)\`", "<color=#aaa><i>$1</i></color>");
// Convert lists (assuming unordered lists)
markdown = Regex.Replace(markdown, @"^\s*-\s+(.+)$", "• $1", RegexOptions.Multiline);
// Convert links
markdown = Regex.Replace(markdown, @"\[([^\]]+)\]\(([^\)]+)\)","<a href=\"$2\">$1</a>");
// Replace sequence of at least three --- with a horizontal line
markdown = Regex.Replace(markdown, @"-{3,}", "<color=#fff4></color>");
return markdown;
}
}
#endif
}