Added Unity project files

This commit is contained in:
2026-06-07 16:58:24 +01:00
parent 3cc05d260b
commit 23bbcab156
3942 changed files with 453676 additions and 0 deletions

View File

@ -0,0 +1,113 @@
using System;
using UnityEditor;
using UnityEngine;
using VRC.SDKBase;
namespace VRC.SDKBase.Editor.Versioning
{
/// <summary>
/// Abstract base class for component version migration logic.
/// Provides sensible defaults for common scenarios while allowing full customization.
/// </summary>
public abstract class ComponentVersionMigrator<TVersion> where TVersion : Enum
{
/// <summary>
/// Core migration logic - must be implemented by each component
/// </summary>
/// <param name="version">Target version to migrate to</param>
/// <param name="serializedObject">Component's serialized object</param>
public abstract void MigrateToVersion(TVersion oldVersion, TVersion newVersion, SerializedObject serializedObject);
/// <summary>
/// Gets a message describing what changes were made during an upgrade
/// Must be implemented to provide component-specific upgrade details
/// </summary>
/// <param name="oldVersion">Version before upgrade</param>
/// <param name="newVersion">Version after upgrade</param>
/// <param name="serializedObject">Component's serialized object</param>
/// <returns>Message describing changes made, or null if no message needed</returns>
public abstract string GetUpgradeChangesMessage(TVersion oldVersion, TVersion newVersion, SerializedObject serializedObject);
/// <summary>
/// Gets the latest version available for this component.
/// Default implementation automatically detects the highest enum value using VersionHelper.
/// Override only if you need custom latest version logic.
/// </summary>
/// <returns>Latest version enum value</returns>
public virtual TVersion GetLatestVersion()
{
return VersionHelper.GetLatestVersion<TVersion>();
}
/// <summary>
/// Gets a warning message for version downgrades
/// Override to provide component-specific downgrade warnings
/// </summary>
/// <param name="oldVersion">Current version</param>
/// <param name="newVersion">Target downgrade version</param>
/// <returns>Warning message, or null if no warning needed</returns>
public virtual string GetDowngradeWarning(TVersion oldVersion, TVersion newVersion)
{
return "Changing to an older version may reintroduce issues that were fixed in newer versions.\n" +
"Consider keeping the current version for best compatibility.";
}
/// <summary>
/// Gets the text to display in the upgrade prompt info box
/// Override to provide component-specific upgrade messaging
/// </summary>
/// <param name="currentVersion">Current version</param>
/// <param name="latestVersion">Latest available version</param>
/// <returns>Text for the upgrade prompt</returns>
public virtual string GetUpgradePromptText(TVersion currentVersion, TVersion latestVersion)
{
return $"This component uses an older version. Upgrade to {GetVersionDisplayName(latestVersion)} for improved compatibility.";
}
/// <summary>
/// Determines if an upgrade prompt should be shown for the current state
/// Default implementation shows prompt if not at latest version
/// Override for component-specific upgrade prompt logic
/// </summary>
/// <param name="version">Current version</param>
/// <param name="serializedObject">Component's serialized object</param>
/// <returns>True if upgrade prompt should be shown</returns>
public virtual bool ShouldShowUpgradePrompt(TVersion version, SerializedObject serializedObject)
{
return Convert.ToInt32(version) < Convert.ToInt32(GetLatestVersion());
}
/// <summary>
/// Called after a version change is applied to refresh version-dependent UI
/// </summary>
/// <param name="version">New version</param>
/// <param name="serializedObject">Component's serialized object</param>
public virtual void OnVersionChanged(TVersion version, SerializedObject serializedObject)
{
// Override in derived classes if needed
}
/// <summary>
/// Gets a display name for a version, using InspectorName attribute if available
/// </summary>
/// <param name="version">Version to get display name for</param>
/// <returns>Display name for the version</returns>
public string GetVersionDisplayName(TVersion version)
{
var enumType = typeof(TVersion);
var enumName = Enum.GetName(enumType, version);
var field = enumType.GetField(enumName);
if (field != null)
{
var inspectorNameAttr = field.GetCustomAttributes(typeof(InspectorNameAttribute), false);
if (inspectorNameAttr.Length > 0)
{
return ((InspectorNameAttribute)inspectorNameAttr[0]).displayName;
}
}
return enumName;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3d4e5f6789012345678901234abcdef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,184 @@
using System;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace VRC.SDKBase.Editor.Versioning
{
/// <summary>
/// Reusable UI system for component version management
/// </summary>
public class ComponentVersionUI<TVersion> where TVersion : Enum
{
private readonly SerializedProperty versionProperty;
private readonly ComponentVersionMigrator<TVersion> migrator;
private readonly string documentationUrl;
private readonly TVersion latestVersion;
private EnumField versionField;
private VisualElement versionUpgradeInfo;
public ComponentVersionUI(SerializedProperty versionProperty, ComponentVersionMigrator<TVersion> migrator, TVersion latestVersion, string documentationUrl = null)
{
this.versionProperty = versionProperty;
this.migrator = migrator;
this.latestVersion = latestVersion;
this.documentationUrl = documentationUrl;
}
/// <summary>
/// Creates the version dropdown field with help button
/// </summary>
public void CreateVersionField(VisualElement root)
{
var versionContainer = new VisualElement();
versionContainer.style.flexDirection = FlexDirection.Row;
versionContainer.style.marginBottom = 10;
// Use the version value from the component
TVersion defaultVersion = (TVersion)Enum.ToObject(typeof(TVersion), versionProperty.enumValueIndex);
// Create version enum field
versionField = new EnumField("Version", defaultVersion);
versionField.style.flexGrow = 1;
versionField.RegisterValueChangedCallback(OnVersionChanged);
versionContainer.Add(versionField);
// Create help button if documentation URL provided
if (!string.IsNullOrEmpty(documentationUrl))
{
var helpButton = new Button(() => {
Application.OpenURL(documentationUrl);
})
{
text = "?",
style = { width = 30 }
};
versionContainer.Add(helpButton);
}
root.Insert(0, versionContainer);
}
/// <summary>
/// Creates the upgrade info box (initially hidden)
/// </summary>
public void CreateUpgradeInfo(VisualElement root)
{
if (versionUpgradeInfo != null) return;
versionUpgradeInfo = new VisualElement()
{
name = "versionUpgradeInfo"
};
versionUpgradeInfo.style.marginBottom = 10;
versionUpgradeInfo.style.marginTop = 5;
versionUpgradeInfo.style.display = DisplayStyle.None;
var currentVersion = (TVersion)Enum.ToObject(typeof(TVersion), versionProperty.enumValueIndex);
var helpBox = new HelpBox(
migrator.GetUpgradePromptText(currentVersion, latestVersion),
HelpBoxMessageType.Info
);
versionUpgradeInfo.Add(helpBox);
var upgradeButton = new Button(() =>
{
// Trigger version change via the dropdown (this will handle the popup)
if (versionField != null)
{
versionField.value = latestVersion;
}
})
{
text = $"Upgrade to {migrator.GetVersionDisplayName(latestVersion)}",
style = { marginTop = 5 }
};
versionUpgradeInfo.Add(upgradeButton);
// Insert at the top after the version field
root.Insert(1, versionUpgradeInfo);
}
/// <summary>
/// Updates the visibility and content of the upgrade info box
/// </summary>
public void RefreshUpgradeInfo()
{
if (versionUpgradeInfo == null) return;
var currentVersion = (TVersion)Enum.ToObject(typeof(TVersion), versionProperty.enumValueIndex);
bool shouldShow = migrator.ShouldShowUpgradePrompt(currentVersion, versionProperty.serializedObject);
versionUpgradeInfo.style.display = shouldShow ? DisplayStyle.Flex : DisplayStyle.None;
// Always update the help box text when the upgrade info exists
var helpBox = versionUpgradeInfo.Query<HelpBox>().First();
if (helpBox != null)
{
helpBox.text = migrator.GetUpgradePromptText(currentVersion, latestVersion);
}
}
private void OnVersionChanged(ChangeEvent<Enum> evt)
{
var newVersion = (TVersion)evt.newValue;
var oldVersion = (TVersion)evt.previousValue;
if (!newVersion.Equals(oldVersion))
{
// Get appropriate message (warning for downgrade, changes for upgrade)
string message = GetVersionChangeMessage(oldVersion, newVersion);
if (!string.IsNullOrEmpty(message))
{
bool isDowngrade = Convert.ToInt32(newVersion) < Convert.ToInt32(oldVersion);
string title = isDowngrade ? "Version Downgrade Warning" : "Upgrade Complete";
string okButton = isDowngrade ? "Continue" : "OK";
string cancelButton = isDowngrade ? "Cancel" : null;
bool proceed = cancelButton != null ?
EditorUtility.DisplayDialog(title, message, okButton, cancelButton) :
EditorUtility.DisplayDialog(title, message, okButton);
if (!proceed && cancelButton != null)
{
// User cancelled downgrade, revert the change
versionField.SetValueWithoutNotify(oldVersion);
return;
}
}
// Update version in the component and apply changes
versionProperty.serializedObject.Update();
versionProperty.enumValueIndex = Convert.ToInt32(newVersion);
versionProperty.serializedObject.ApplyModifiedProperties();
// Apply migration and refresh UI
migrator.MigrateToVersion(oldVersion, newVersion, versionProperty.serializedObject);
migrator.OnVersionChanged(newVersion, versionProperty.serializedObject);
RefreshUpgradeInfo();
}
}
private string GetVersionChangeMessage(TVersion oldVersion, TVersion newVersion)
{
bool isUpgrade = Convert.ToInt32(newVersion) > Convert.ToInt32(oldVersion);
bool isDowngrade = Convert.ToInt32(newVersion) < Convert.ToInt32(oldVersion);
if (isDowngrade)
{
return migrator.GetDowngradeWarning(oldVersion, newVersion);
}
else if (isUpgrade)
{
return migrator.GetUpgradeChangesMessage(oldVersion, newVersion, versionProperty.serializedObject);
}
return null; // No message for same version
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d4e5f6789012345678901234abcdef01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: