test
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3dfa3c8fac2134fdda65f882f5a1a014
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,13 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class EditorPreferencesProvider : Editor
|
||||
{
|
||||
[SettingsProvider]
|
||||
public static SettingsProvider CreateEditorPreferencesProvider()
|
||||
{
|
||||
return new EditorPreferencesProviderView();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba9c71f100044b3a9dca49c8f9e489cb
|
||||
timeCreated: 1625864018
|
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
internal class EditorPreferencesProviderView : SettingsProvider
|
||||
{
|
||||
private const string Path = "Preferences/Visual Scripting";
|
||||
private const string Title = "Visual Scripting";
|
||||
private const string ID = "Bolt";
|
||||
private readonly GUIStyle marginStyle = new GUIStyle() { margin = new RectOffset(10, 10, 10, 10) };
|
||||
|
||||
public EditorPreferencesProviderView() : base(Path, SettingsScope.User)
|
||||
{
|
||||
label = Title;
|
||||
}
|
||||
|
||||
private void EnsureConfig()
|
||||
{
|
||||
if (BoltCore.instance == null || BoltCore.Configuration == null)
|
||||
{
|
||||
PluginContainer.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGUI(string searchContext)
|
||||
{
|
||||
EnsureConfig();
|
||||
|
||||
GUILayout.BeginVertical(marginStyle);
|
||||
|
||||
// happens when opening unity with the settings window already opened. there's a delay until the singleton is assigned
|
||||
if (BoltCore.instance == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Loading Configuration...", MessageType.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
var instance = (BoltProduct)ProductContainer.GetProduct(ID);
|
||||
|
||||
instance.configurationPanel.PreferenceItem();
|
||||
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7453dd8d3980405794f631eea9f420e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a06b4d04018343b99f255da7f18559d1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,80 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class AssemblyOptionsSettings
|
||||
{
|
||||
private const string CompleteLabel = "Regenerate Nodes";
|
||||
private readonly PluginConfigurationItemMetadata _assemblyOptionsMetadata;
|
||||
|
||||
private bool _showAssembly = false;
|
||||
private const string TitleAssembly = "Node Library";
|
||||
private const string DescriptionAssembly = "Choose the assemblies in which you want to look for nodes.\n"
|
||||
+ "By default, all project and Unity assemblies are included.\n"
|
||||
+ "Unless you use a third-party plugin distributed as a DLL, you shouldn't need to change this.";
|
||||
|
||||
private ProjectAssemblyOptionsListInspector _assemblyOptionsInspector;
|
||||
|
||||
public AssemblyOptionsSettings(BoltCoreConfiguration coreConfig)
|
||||
{
|
||||
_assemblyOptionsMetadata = coreConfig.GetMetadata(nameof(coreConfig.assemblyOptions));
|
||||
_assemblyOptionsInspector = new ProjectAssemblyOptionsListInspector(_assemblyOptionsMetadata);
|
||||
}
|
||||
|
||||
private static class Styles
|
||||
{
|
||||
public static readonly GUIStyle background;
|
||||
public static readonly GUIStyle defaultsButton;
|
||||
public const float OptionsWidth = 250;
|
||||
|
||||
static Styles()
|
||||
{
|
||||
background = new GUIStyle(LudiqStyles.windowBackground);
|
||||
background.padding = new RectOffset(20, 20, 20, 20);
|
||||
|
||||
defaultsButton = new GUIStyle("Button");
|
||||
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
_showAssembly = EditorGUILayout.Foldout(_showAssembly, new GUIContent(TitleAssembly, DescriptionAssembly));
|
||||
|
||||
if (_showAssembly)
|
||||
{
|
||||
GUILayout.BeginVertical(Styles.background, GUILayout.ExpandHeight(true));
|
||||
|
||||
var height = _assemblyOptionsInspector.GetCachedHeight(Styles.OptionsWidth, GUIContent.none, null);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
var position = GUILayoutUtility.GetRect(Styles.OptionsWidth, height);
|
||||
|
||||
_assemblyOptionsInspector.Draw(position, GUIContent.none);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_assemblyOptionsMetadata.SaveImmediately(true);
|
||||
Codebase.UpdateSettings();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Reset to Defaults", Styles.defaultsButton) && EditorUtility.DisplayDialog("Reset the Node Library", "Reset the Node Library to its default state?", "Reset to Default", "Cancel"))
|
||||
{
|
||||
_assemblyOptionsMetadata.Reset(true);
|
||||
_assemblyOptionsMetadata.SaveImmediately(true);
|
||||
}
|
||||
|
||||
LudiqGUI.EndVertical();
|
||||
}
|
||||
|
||||
if (GUILayout.Button(CompleteLabel, Styles.defaultsButton))
|
||||
{
|
||||
UnitBase.Rebuild();
|
||||
|
||||
EditorUtility.DisplayDialog("Visual Script", "Regenerate Nodes completed", "OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cb1615bd41a3442a8aabbcb872046a3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,46 @@
|
||||
using System.Diagnostics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class BackupSettings
|
||||
{
|
||||
private const string Title = "Backup Graphs";
|
||||
private const string ButtonBackupLabel = "Create Backup";
|
||||
private const string ButtonRestoreLabel = "Restore Backup";
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
GUILayout.Space(5f);
|
||||
|
||||
GUILayout.Label(Title, EditorStyles.boldLabel);
|
||||
|
||||
GUILayout.Space(5f);
|
||||
|
||||
if (GUILayout.Button(ButtonBackupLabel, Styles.defaultsButton))
|
||||
{
|
||||
VSBackupUtility.Backup();
|
||||
|
||||
EditorUtility.DisplayDialog("Backup", "Backup completed successfully.", "OK");
|
||||
}
|
||||
|
||||
if (GUILayout.Button(ButtonRestoreLabel, Styles.defaultsButton))
|
||||
{
|
||||
PathUtility.CreateDirectoryIfNeeded(Paths.backups);
|
||||
Process.Start(Paths.backups);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Styles
|
||||
{
|
||||
static Styles()
|
||||
{
|
||||
defaultsButton = new GUIStyle("Button");
|
||||
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
|
||||
}
|
||||
|
||||
public static readonly GUIStyle defaultsButton;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50455e66302b715488a9218e30b0ab24
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,45 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class CustomPropertyProviderSettings
|
||||
{
|
||||
private const string Title = "Custom Inspector Properties";
|
||||
private const string ButtonLabel = "Generate";
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
GUILayout.Space(5f);
|
||||
|
||||
GUILayout.Label(Title, EditorStyles.boldLabel);
|
||||
|
||||
GUILayout.Space(5f);
|
||||
|
||||
string label = "Inspectors in Visual Scripting plugins can handle many custom types besides Unity primites and objects. ";
|
||||
label += "However, to be compatible with your custom editor drawers, some additional property provider scripts must be generated. ";
|
||||
|
||||
GUILayout.BeginHorizontal(EditorStyles.helpBox);
|
||||
GUILayout.Label(EditorGUIUtility.IconContent("console.infoicon"), GUILayout.ExpandWidth(true));
|
||||
GUILayout.Box(label, EditorStyles.wordWrappedLabel);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (GUILayout.Button(ButtonLabel, Styles.defaultsButton))
|
||||
{
|
||||
SerializedPropertyProviderProvider.instance.GenerateProviderScripts();
|
||||
EditorUtility.DisplayDialog("Custom Inspector Generation", "Custom inspector generation has completed successfully.", "OK");
|
||||
}
|
||||
}
|
||||
|
||||
private static class Styles
|
||||
{
|
||||
static Styles()
|
||||
{
|
||||
defaultsButton = new GUIStyle("Button");
|
||||
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
|
||||
}
|
||||
|
||||
public static readonly GUIStyle defaultsButton;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7da9d8250917648728b856bfab5f1320
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
internal class LinkerPropertyProviderSettings
|
||||
{
|
||||
private readonly PluginConfigurationItemMetadata _linkerSettings;
|
||||
|
||||
private const string Title = "Linker generation settings";
|
||||
|
||||
private readonly GUIContent[] _toggleTargetsLabel =
|
||||
{
|
||||
new GUIContent("Scan graph assets"),
|
||||
new GUIContent("Scan scenes"),
|
||||
new GUIContent("Scan prefabs")
|
||||
};
|
||||
|
||||
private Array _options = Enum.GetValues(typeof(BoltCoreConfiguration.LinkerScanTarget));
|
||||
private List<bool> _settings;
|
||||
|
||||
public LinkerPropertyProviderSettings(BoltCoreConfiguration coreConfig)
|
||||
{
|
||||
_linkerSettings = coreConfig.GetMetadata(nameof(LinkerPropertyProviderSettings));
|
||||
|
||||
_settings = new List<bool>((List<bool>)_linkerSettings.value);
|
||||
}
|
||||
|
||||
private void SaveIfNeeded()
|
||||
{
|
||||
var settings = (List<bool>)_linkerSettings.value;
|
||||
|
||||
if (!_settings.SequenceEqual(settings))
|
||||
{
|
||||
_linkerSettings.value = new List<bool>(_settings);
|
||||
|
||||
_linkerSettings.SaveImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
GUILayout.Space(5f);
|
||||
|
||||
GUILayout.Label(Title, EditorStyles.boldLabel);
|
||||
|
||||
GUILayout.Space(5f);
|
||||
|
||||
var label = "Scan for types to be added to link.xml";
|
||||
|
||||
GUILayout.BeginHorizontal(EditorStyles.helpBox);
|
||||
GUILayout.Label(EditorGUIUtility.IconContent("console.infoicon"), GUILayout.ExpandWidth(true));
|
||||
GUILayout.Box(label, EditorStyles.wordWrappedLabel);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(5f);
|
||||
|
||||
foreach (var option in _options)
|
||||
{
|
||||
_settings[(int)option] = GUILayout.Toggle(_settings[(int)option], _toggleTargetsLabel[(int)option]);
|
||||
GUILayout.Space(5f);
|
||||
}
|
||||
|
||||
SaveIfNeeded();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2e89b748a6ae452488da87a34e25287
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,36 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class ScriptReferenceResolverSettings
|
||||
{
|
||||
private const string Title = "Script Reference Resolver";
|
||||
private const string ButtonLabel = "Fix Missing Scripts";
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
GUILayout.Space(5f);
|
||||
|
||||
GUILayout.Label(Title, EditorStyles.boldLabel);
|
||||
|
||||
GUILayout.Space(5f);
|
||||
|
||||
if (GUILayout.Button(ButtonLabel, Styles.defaultsButton))
|
||||
{
|
||||
ScriptReferenceResolver.Run(ScriptReferenceResolver.Mode.Dialog);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Styles
|
||||
{
|
||||
static Styles()
|
||||
{
|
||||
defaultsButton = new GUIStyle("Button");
|
||||
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
|
||||
}
|
||||
|
||||
public static readonly GUIStyle defaultsButton;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8c0a3364f2ef4e42820eb87b5bdab69
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,69 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class TypeOptionsSettings
|
||||
{
|
||||
private readonly PluginConfigurationItemMetadata _typeOptionsMetadata;
|
||||
|
||||
private bool _showTypeOption = false;
|
||||
private const string TitleTypeOption = "Type Options";
|
||||
private const string DescriptionTypeOption = "Choose the types you want to use for variables and nodes.\n"
|
||||
+ "MonoBehaviour types are always included.";
|
||||
|
||||
private static class Styles
|
||||
{
|
||||
public static readonly GUIStyle background;
|
||||
public static readonly GUIStyle defaultsButton;
|
||||
public const float OptionsWidth = 250;
|
||||
|
||||
static Styles()
|
||||
{
|
||||
background = new GUIStyle(LudiqStyles.windowBackground);
|
||||
background.padding = new RectOffset(20, 20, 20, 20);
|
||||
|
||||
defaultsButton = new GUIStyle("Button");
|
||||
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
public TypeOptionsSettings(BoltCoreConfiguration coreConfig)
|
||||
{
|
||||
_typeOptionsMetadata = coreConfig.GetMetadata(nameof(coreConfig.typeOptions));
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
_showTypeOption = EditorGUILayout.Foldout(_showTypeOption, new GUIContent(TitleTypeOption, DescriptionTypeOption));
|
||||
|
||||
if (_showTypeOption)
|
||||
{
|
||||
GUILayout.BeginVertical(Styles.background, GUILayout.ExpandHeight(true));
|
||||
|
||||
float height =
|
||||
LudiqGUI.GetInspectorHeight(null, _typeOptionsMetadata, Styles.OptionsWidth, GUIContent.none);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
var position = GUILayoutUtility.GetRect(Styles.OptionsWidth, height);
|
||||
|
||||
LudiqGUI.Inspector(_typeOptionsMetadata, position, GUIContent.none);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_typeOptionsMetadata.SaveImmediately(true);
|
||||
Codebase.UpdateSettings();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Reset to Defaults", Styles.defaultsButton) && EditorUtility.DisplayDialog("Reset Included Types", "Reset the included types to their defaults?", "Reset to Default", "Cancel"))
|
||||
{
|
||||
_typeOptionsMetadata.Reset(true);
|
||||
_typeOptionsMetadata.SaveImmediately(true);
|
||||
}
|
||||
|
||||
LudiqGUI.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f061d8e7ad514436d82f47b34306a22c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,13 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class ProjectSettingsProvider : Editor
|
||||
{
|
||||
[SettingsProvider]
|
||||
public static SettingsProvider CreateProjectSettingProvider()
|
||||
{
|
||||
return new ProjectSettingsProviderView();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6a0cc840e6084f62a3e3538f14bf3ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,125 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
internal class ProjectSettingsProviderView : SettingsProvider
|
||||
{
|
||||
private const string Path = "Project/Visual Scripting";
|
||||
private const string Title = "Visual Scripting";
|
||||
private const string TitleGroup = "Generate Nodes";
|
||||
private readonly GUIStyle marginStyle = new GUIStyle() { margin = new RectOffset(10, 10, 10, 10) };
|
||||
|
||||
private AssemblyOptionsSettings _assemblyOptionsSettings;
|
||||
private TypeOptionsSettings _typeOptionsSettings;
|
||||
private CustomPropertyProviderSettings _customPropertyProviderSettings;
|
||||
private LinkerPropertyProviderSettings _linkerPropertyProviderSettings;
|
||||
private BackupSettings _backupSettings;
|
||||
private ScriptReferenceResolverSettings _scriptReferenceResolverSettings;
|
||||
|
||||
private BoltCoreConfiguration _vsCoreConfig = null;
|
||||
|
||||
public ProjectSettingsProviderView() : base(Path, SettingsScope.Project)
|
||||
{
|
||||
label = Title;
|
||||
EditorTypeUtility.Initialize();
|
||||
}
|
||||
|
||||
private void CreateOptionsIfNeeded()
|
||||
{
|
||||
_assemblyOptionsSettings ??= new AssemblyOptionsSettings(_vsCoreConfig);
|
||||
_typeOptionsSettings ??= new TypeOptionsSettings(_vsCoreConfig);
|
||||
_customPropertyProviderSettings ??= new CustomPropertyProviderSettings();
|
||||
_linkerPropertyProviderSettings ??= new LinkerPropertyProviderSettings(_vsCoreConfig);
|
||||
_backupSettings ??= new BackupSettings();
|
||||
_scriptReferenceResolverSettings ??= new ScriptReferenceResolverSettings();
|
||||
}
|
||||
|
||||
private void EnsureConfig()
|
||||
{
|
||||
if (_vsCoreConfig != null)
|
||||
return;
|
||||
|
||||
if (BoltCore.instance == null || BoltCore.Configuration == null)
|
||||
{
|
||||
UnityAPI.Initialize();
|
||||
PluginContainer.Initialize();
|
||||
}
|
||||
|
||||
_vsCoreConfig = BoltCore.Configuration;
|
||||
}
|
||||
|
||||
public override void OnGUI(string searchContext)
|
||||
{
|
||||
GUILayout.BeginVertical(marginStyle);
|
||||
|
||||
if (VSUsageUtility.isVisualScriptingUsed)
|
||||
{
|
||||
EnsureConfig();
|
||||
|
||||
GUILayout.Space(5f);
|
||||
|
||||
GUILayout.Label(TitleGroup, EditorStyles.boldLabel);
|
||||
|
||||
GUILayout.Space(10f);
|
||||
|
||||
// happens when opening unity with the settings window already opened. there's a delay until the singleton is assigned
|
||||
if (_vsCoreConfig == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Loading Configuration...", MessageType.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
CreateOptionsIfNeeded();
|
||||
|
||||
_typeOptionsSettings.OnGUI();
|
||||
|
||||
GUILayout.Space(10f);
|
||||
|
||||
_assemblyOptionsSettings.OnGUI();
|
||||
|
||||
GUILayout.Space(10f);
|
||||
|
||||
_customPropertyProviderSettings.OnGUI();
|
||||
|
||||
GUILayout.Space(10f);
|
||||
|
||||
_linkerPropertyProviderSettings.OnGUI();
|
||||
|
||||
GUILayout.Space(10f);
|
||||
|
||||
_backupSettings.OnGUI();
|
||||
|
||||
GUILayout.Space(10f);
|
||||
|
||||
_scriptReferenceResolverSettings.OnGUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Space(5f);
|
||||
|
||||
GUILayout.BeginHorizontal(EditorStyles.label);
|
||||
if (GUILayout.Button("Initialize Visual Scripting", Styles.defaultsButton))
|
||||
{
|
||||
VSUsageUtility.isVisualScriptingUsed = true;
|
||||
}
|
||||
|
||||
GUILayout.Space(5f);
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private static class Styles
|
||||
{
|
||||
static Styles()
|
||||
{
|
||||
defaultsButton = new GUIStyle("Button");
|
||||
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
|
||||
}
|
||||
|
||||
public static readonly GUIStyle defaultsButton;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4eea00f49056f4ee98c82b6923b44600
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "Unity.VisualScripting.SettingsProvider.Editor",
|
||||
"references": [
|
||||
"Unity.VisualScripting.Core",
|
||||
"Unity.VisualScripting.Core.Editor",
|
||||
"Unity.VisualScripting.Flow",
|
||||
"Unity.VisualScripting.Flow.Editor",
|
||||
"Unity.VisualScripting.State"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2aa54ddaa48744e1caddee916e39805e
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7abb56c9dd89a544a9995a060ab55368
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0a037cc0a236493996d666b0ab8690c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,27 @@
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public abstract class Analyser<TTarget, TAnalysis> : Assigner<TTarget, TAnalysis>, IAnalyser
|
||||
where TAnalysis : class, IAnalysis, new()
|
||||
{
|
||||
protected Analyser(GraphReference reference, TTarget target) : base(target, new TAnalysis())
|
||||
{
|
||||
Ensure.That(nameof(reference)).IsNotNull(reference);
|
||||
|
||||
this.reference = reference;
|
||||
|
||||
// HACK: It makes more sense to think of analysis as reference-bound,
|
||||
// however in practice they are context-bound and therefore it is safe
|
||||
// (and more importantly faster) to cache the context once for recursive
|
||||
// analyses.
|
||||
this.context = reference.Context();
|
||||
}
|
||||
|
||||
public TAnalysis analysis => assignee;
|
||||
|
||||
IAnalysis IAnalyser.analysis => analysis;
|
||||
|
||||
protected IGraphContext context { get; }
|
||||
|
||||
public GraphReference reference { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cf3624e65e804bfb9dd35ee9884f519
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
|
||||
public sealed class AnalyserAttribute : Attribute, IDecoratorAttribute
|
||||
{
|
||||
public AnalyserAttribute(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Type type { get; private set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7663ba3a43454ba48fd2c7c17a0ae75
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class AnalyserProvider : SingleDecoratorProvider<object, IAnalyser, AnalyserAttribute>
|
||||
{
|
||||
protected override bool cache => true;
|
||||
|
||||
public GraphReference reference { get; }
|
||||
|
||||
public AnalyserProvider(GraphReference reference)
|
||||
{
|
||||
this.reference = reference;
|
||||
}
|
||||
|
||||
protected override IAnalyser CreateDecorator(Type decoratorType, object decorated)
|
||||
{
|
||||
return (IAnalyser)decoratorType.Instantiate(true, reference, decorated);
|
||||
}
|
||||
|
||||
public override bool IsValid(object analyzed)
|
||||
{
|
||||
return !analyzed.IsUnityNull();
|
||||
}
|
||||
|
||||
public void Analyze(object analyzed)
|
||||
{
|
||||
GetDecorator(analyzed).isDirty = true;
|
||||
}
|
||||
|
||||
public void AnalyzeAll()
|
||||
{
|
||||
foreach (var analyser in decorators.Values)
|
||||
{
|
||||
analyser.isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class XAnalyserProvider
|
||||
{
|
||||
// Analysis are conceptually reference-bound, but practically context-bound,
|
||||
// so it's faster to avoid the reference-to-context lookup if we can avoid it.
|
||||
|
||||
public static IAnalyser Analyser(this object target, IGraphContext context)
|
||||
{
|
||||
return context.analyserProvider.GetDecorator(target);
|
||||
}
|
||||
|
||||
public static TAnalyser Analyser<TAnalyser>(this object target, IGraphContext context) where TAnalyser : IAnalyser
|
||||
{
|
||||
return context.analyserProvider.GetDecorator<TAnalyser>(target);
|
||||
}
|
||||
|
||||
public static IAnalysis Analysis(this object target, IGraphContext context)
|
||||
{
|
||||
var analyser = target.Analyser(context);
|
||||
analyser.Validate();
|
||||
return analyser.analysis;
|
||||
}
|
||||
|
||||
public static TAnalysis Analysis<TAnalysis>(this object target, IGraphContext context) where TAnalysis : IAnalysis
|
||||
{
|
||||
return (TAnalysis)target.Analysis(context);
|
||||
}
|
||||
|
||||
// Shortcuts, but the above are faster because Context doesn't have to be looked up
|
||||
|
||||
public static IAnalyser Analyser(this object target, GraphReference reference)
|
||||
{
|
||||
return target.Analyser(reference.Context());
|
||||
}
|
||||
|
||||
public static TAnalyser Analyser<TAnalyser>(this object target, GraphReference reference) where TAnalyser : IAnalyser
|
||||
{
|
||||
return target.Analyser<TAnalyser>(reference.Context());
|
||||
}
|
||||
|
||||
public static IAnalysis Analysis(this object target, GraphReference reference)
|
||||
{
|
||||
return target.Analysis(reference.Context());
|
||||
}
|
||||
|
||||
public static TAnalysis Analysis<TAnalysis>(this object target, GraphReference reference) where TAnalysis : IAnalysis
|
||||
{
|
||||
return target.Analysis<TAnalysis>(reference.Context());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c1743061b8e147ff9c808d137b1014e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,6 @@
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public abstract class Analysis : IAnalysis
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f01a1ac261c724daca990596c32f7f10
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public class GraphElementAnalysis : IGraphElementAnalysis
|
||||
{
|
||||
public List<Warning> warnings { get; set; } = new List<Warning>();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ac0dd11da2f64fc5b55b1b8a1d36b55
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,11 @@
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IAnalyser
|
||||
{
|
||||
IAnalysis analysis { get; }
|
||||
|
||||
bool isDirty { get; set; }
|
||||
|
||||
void Validate();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1eb0e9411d1e4ed880da3147ac22dc8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,6 @@
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IAnalysis
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fb36d0252722495cbe1fddf45ba9185
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public interface IGraphElementAnalysis : IAnalysis
|
||||
{
|
||||
List<Warning> warnings { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf7f2015398494d498495147f2028b49
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fae0344df02e74e0988c577297cc556d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine.Analytics;
|
||||
|
||||
namespace Unity.VisualScripting
|
||||
{
|
||||
public sealed class UsageAnalytics
|
||||
{
|
||||
const int k_MaxEventsPerHour = 1000;
|
||||
const int k_MaxNumberOfElements = 1000;
|
||||
const string k_VendorKey = "unity.bolt";
|
||||
const string k_EventName = "BoltUsage";
|
||||
#if !UNITY_2023_2_OR_NEWER
|
||||
static bool isRegistered = false;
|
||||
#endif
|
||||
|
||||
internal static void CollectAndSendForType<T>(string[] paths)
|
||||
{
|
||||
if (!EditorAnalytics.enabled || !VSUsageUtility.isVisualScriptingUsed)
|
||||
return;
|
||||
|
||||
foreach (string path in paths)
|
||||
{
|
||||
Type assetType = AssetDatabase.GetMainAssetTypeAtPath(path);
|
||||
if (assetType == typeof(T))
|
||||
{
|
||||
CollectAndSend();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
public static void CollectAndSend()
|
||||
{
|
||||
if (!EditorAnalytics.enabled || !VSUsageUtility.isVisualScriptingUsed)
|
||||
return;
|
||||
|
||||
EditorAnalytics.SendAnalytic(new UsageAnalytic(CollectData()));
|
||||
}
|
||||
#else
|
||||
public static void CollectAndSend()
|
||||
{
|
||||
if (!EditorAnalytics.enabled || !VSUsageUtility.isVisualScriptingUsed)
|
||||
return;
|
||||
|
||||
if (!RegisterEvent())
|
||||
return;
|
||||
|
||||
var data = CollectData();
|
||||
|
||||
EditorAnalytics.SendEventWithLimit(k_EventName, data);
|
||||
}
|
||||
|
||||
private static bool RegisterEvent()
|
||||
{
|
||||
if (!isRegistered)
|
||||
{
|
||||
var result = EditorAnalytics.RegisterEventWithLimit(k_EventName, k_MaxEventsPerHour, k_MaxNumberOfElements, k_VendorKey);
|
||||
if (result == UnityEngine.Analytics.AnalyticsResult.Ok)
|
||||
{
|
||||
isRegistered = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isRegistered;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static UsageAnalyticsData CollectData()
|
||||
{
|
||||
var data = new UsageAnalyticsData
|
||||
{
|
||||
productVersion = BoltProduct.instance.version.ToString(),
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[AnalyticInfo(eventName: k_EventName, vendorKey: k_VendorKey, maxEventsPerHour:k_MaxEventsPerHour, maxNumberOfElements:k_MaxNumberOfElements)]
|
||||
class UsageAnalytic : IAnalytic
|
||||
{
|
||||
private UsageAnalyticsData data;
|
||||
public UsageAnalytic(UsageAnalyticsData data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public bool TryGatherData(out IAnalytic.IData data, out Exception error)
|
||||
{
|
||||
error = null;
|
||||
data = this.data;
|
||||
return data != null;
|
||||
}
|
||||
}
|
||||
private struct UsageAnalyticsData: IAnalytic.IData
|
||||
#else
|
||||
private struct UsageAnalyticsData
|
||||
#endif
|
||||
{
|
||||
public string productVersion;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59718df20b933421a9c465fcbeff7836
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Unity.VisualScripting.Analytics
|
||||
{
|
||||
internal static class AnalyticsUtilities
|
||||
{
|
||||
internal static string AnonymizeException(Exception e)
|
||||
{
|
||||
const string pathSectionOutsidePackage = "in (?<P>.*)Packages\\\\com.unity.visualscripting";
|
||||
// Placing a '^' character to distinguish these lines from file paths outside our package
|
||||
const string pathSectionOutsidePackageReplacement = "in ^Packages\\com.unity.visualscripting";
|
||||
|
||||
var anonymizedString = Regex.Replace(e.ToString(), pathSectionOutsidePackage, pathSectionOutsidePackageReplacement);
|
||||
|
||||
// Detecting any callstack line that doesn't match our previously anonymized package paths
|
||||
const string filePathsOutsidePackage = ". at.*in (?<P>[^^]*:[0-9]*)";
|
||||
const string filePathsOutsidePackageReplacement = " at <method> in <file>";
|
||||
|
||||
anonymizedString = Regex.Replace(anonymizedString, filePathsOutsidePackage,
|
||||
filePathsOutsidePackageReplacement);
|
||||
|
||||
return anonymizedString;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d2bbdd7f3404e04941d986015e27acb
|
||||
timeCreated: 1621016306
|
@@ -0,0 +1,207 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Analytics;
|
||||
|
||||
namespace Unity.VisualScripting.Analytics
|
||||
{
|
||||
internal static class HotkeyUsageAnalytics
|
||||
{
|
||||
private const int MaxEventsPerHour = 120;
|
||||
private const int MaxNumberOfElements = 1000;
|
||||
private const string VendorKey = "unity.visualscripting";
|
||||
private const string EventName = "VScriptHotkeyUsage";
|
||||
#if !UNITY_2023_2_OR_NEWER
|
||||
private static bool _isRegistered = false;
|
||||
#endif
|
||||
|
||||
private const int HotkeyUseLimitBeforeSend = 10000;
|
||||
private static bool _interruptEventsRegistered = false;
|
||||
private static bool _onControlSchemeEventRegistered = false;
|
||||
private static Data _collectedData = null;
|
||||
// Limiting to stop spam from some continuous events like pan or zoom
|
||||
private const int HotkeyFrameLimit = 2;
|
||||
private static Dictionary<Hotkey, FrameLimiterUtility> _frameLimiters;
|
||||
|
||||
internal static void HotkeyUsed(Hotkey key)
|
||||
{
|
||||
EnsureCollectedDataInitialized();
|
||||
EnsureInterruptEventsRegistered();
|
||||
EnsureOnControlSchemeChangedRegistered();
|
||||
|
||||
_collectedData.canvasControlSchemeName = Enum.GetName(typeof(CanvasControlScheme), BoltCore.Configuration.controlScheme);
|
||||
|
||||
if (!_frameLimiters.ContainsKey(key))
|
||||
_frameLimiters.Add(key, new FrameLimiterUtility(HotkeyFrameLimit));
|
||||
|
||||
if (!_frameLimiters[key].IsWithinFPSLimit()) return;
|
||||
|
||||
var enumStringVal = Enum.GetName(typeof(Hotkey), key);
|
||||
if (enumStringVal == null)
|
||||
return;
|
||||
|
||||
if (!_collectedData.HotkeyUsageCountDict.ContainsKey(enumStringVal))
|
||||
_collectedData.HotkeyUsageCountDict.Add(enumStringVal, 0);
|
||||
|
||||
_collectedData.HotkeyUsageCountDict[enumStringVal]++;
|
||||
|
||||
if (_collectedData.HotkeyUsageCountDict[enumStringVal] >= HotkeyUseLimitBeforeSend)
|
||||
Send();
|
||||
}
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
private static void Send()
|
||||
{
|
||||
if (!EditorAnalytics.enabled)
|
||||
return;
|
||||
|
||||
// Because dicts aren't serializable, convert it to a list right before we send
|
||||
foreach (var count in _collectedData.HotkeyUsageCountDict)
|
||||
{
|
||||
var c = new HotkeyStringUsageCount();
|
||||
c.hotkey = count.Key;
|
||||
c.count = count.Value;
|
||||
_collectedData.hotkeyUsageCount.Add(c);
|
||||
}
|
||||
|
||||
EditorAnalytics.SendAnalytic(new HotkeyUsageAnalytic(_collectedData));
|
||||
|
||||
ResetCollectedData();
|
||||
}
|
||||
#else
|
||||
private static void Send()
|
||||
{
|
||||
if (!EditorAnalytics.enabled)
|
||||
return;
|
||||
|
||||
if (!RegisterEvent())
|
||||
return;
|
||||
|
||||
// Because dicts aren't serializable, convert it to a list right before we send
|
||||
foreach (var count in _collectedData.HotkeyUsageCountDict)
|
||||
{
|
||||
var c = new HotkeyStringUsageCount();
|
||||
c.hotkey = count.Key;
|
||||
c.count = count.Value;
|
||||
_collectedData.hotkeyUsageCount.Add(c);
|
||||
}
|
||||
|
||||
EditorAnalytics.SendEventWithLimit(EventName, _collectedData);
|
||||
|
||||
ResetCollectedData();
|
||||
}
|
||||
|
||||
private static bool RegisterEvent()
|
||||
{
|
||||
if (!_isRegistered)
|
||||
{
|
||||
var result = EditorAnalytics.RegisterEventWithLimit(EventName, MaxEventsPerHour, MaxNumberOfElements, VendorKey);
|
||||
if (result == UnityEngine.Analytics.AnalyticsResult.Ok)
|
||||
{
|
||||
_isRegistered = true;
|
||||
}
|
||||
}
|
||||
|
||||
return _isRegistered;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static void EnsureInterruptEventsRegistered()
|
||||
{
|
||||
if (_interruptEventsRegistered) return;
|
||||
|
||||
EditorApplication.quitting += Send;
|
||||
AssemblyReloadEvents.beforeAssemblyReload += Send;
|
||||
_interruptEventsRegistered = true;
|
||||
}
|
||||
|
||||
private static void EnsureOnControlSchemeChangedRegistered()
|
||||
{
|
||||
if (_onControlSchemeEventRegistered) return;
|
||||
|
||||
BoltCore.Configuration.ControlSchemeChanged += Send;
|
||||
_onControlSchemeEventRegistered = true;
|
||||
}
|
||||
|
||||
private static void EnsureCollectedDataInitialized()
|
||||
{
|
||||
if (_collectedData != null) return;
|
||||
ResetCollectedData();
|
||||
|
||||
_frameLimiters = new Dictionary<Hotkey, FrameLimiterUtility>();
|
||||
}
|
||||
|
||||
private static void ResetCollectedData()
|
||||
{
|
||||
var controlScheme = Enum.GetName(typeof(CanvasControlScheme), BoltCore.Configuration.controlScheme);
|
||||
_collectedData = new Data()
|
||||
{
|
||||
canvasControlSchemeName = controlScheme,
|
||||
hotkeyUsageCount = new List<HotkeyStringUsageCount>(),
|
||||
HotkeyUsageCountDict = new Dictionary<string, int>(),
|
||||
};
|
||||
}
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[AnalyticInfo(eventName: EventName, vendorKey: VendorKey, maxEventsPerHour:MaxEventsPerHour, maxNumberOfElements:MaxNumberOfElements)]
|
||||
class HotkeyUsageAnalytic : IAnalytic
|
||||
{
|
||||
private Data data;
|
||||
public HotkeyUsageAnalytic(Data data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public bool TryGatherData(out IAnalytic.IData data, out Exception error)
|
||||
{
|
||||
error = null;
|
||||
data = this.data;
|
||||
return data != null;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private class Data : IAnalytic.IData
|
||||
#else
|
||||
[Serializable]
|
||||
private class Data
|
||||
#endif
|
||||
{
|
||||
// Note: using strings instead of enums to make it resilient to enum order changing
|
||||
[SerializeField]
|
||||
internal string canvasControlSchemeName;
|
||||
|
||||
[SerializeField]
|
||||
internal List<HotkeyStringUsageCount> hotkeyUsageCount;
|
||||
|
||||
// Not actually sent to analytics because analytics uses UnitySerializer under the hood
|
||||
// which cannot serialize dictionaries
|
||||
internal Dictionary<string, int> HotkeyUsageCountDict;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private struct HotkeyStringUsageCount
|
||||
{
|
||||
[SerializeField] internal string hotkey;
|
||||
[SerializeField] internal int count;
|
||||
}
|
||||
|
||||
internal enum Hotkey
|
||||
{
|
||||
Zoom,
|
||||
Scroll,
|
||||
PanMmb,
|
||||
PanAltLmb,
|
||||
Home,
|
||||
RmbRemoveConnections,
|
||||
Cut,
|
||||
Copy,
|
||||
Paste,
|
||||
Duplicate,
|
||||
Delete,
|
||||
SelectAll,
|
||||
Tab,
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e84744b83a8434ab42fa513f9bf00ad
|
||||
timeCreated: 1617297094
|
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Analytics;
|
||||
|
||||
namespace Unity.VisualScripting.Analytics
|
||||
{
|
||||
internal static class MigrationAnalytics
|
||||
{
|
||||
private const int MaxEventsPerHour = 120;
|
||||
private const int MaxNumberOfElements = 1000;
|
||||
private const string VendorKey = "unity.visualscripting";
|
||||
private const string EventName = "VScriptMigration";
|
||||
#if !UNITY_2023_2_OR_NEWER
|
||||
private static bool _isRegistered = false;
|
||||
#endif
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
internal static void Send(Data data)
|
||||
{
|
||||
if (!EditorAnalytics.enabled)
|
||||
return;
|
||||
|
||||
EditorAnalytics.SendAnalytic(new MigrationAnalytic(data));
|
||||
}
|
||||
#else
|
||||
internal static void Send(Data data)
|
||||
{
|
||||
if (!EditorAnalytics.enabled)
|
||||
return;
|
||||
|
||||
if (!RegisterEvent())
|
||||
return;
|
||||
|
||||
EditorAnalytics.SendEventWithLimit(EventName, data);
|
||||
}
|
||||
|
||||
private static bool RegisterEvent()
|
||||
{
|
||||
if (!_isRegistered)
|
||||
{
|
||||
var result = EditorAnalytics.RegisterEventWithLimit(EventName, MaxEventsPerHour, MaxNumberOfElements, VendorKey);
|
||||
if (result == UnityEngine.Analytics.AnalyticsResult.Ok)
|
||||
{
|
||||
_isRegistered = true;
|
||||
}
|
||||
}
|
||||
|
||||
return _isRegistered;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[AnalyticInfo(eventName: EventName, vendorKey: VendorKey, maxEventsPerHour:MaxEventsPerHour, maxNumberOfElements:MaxNumberOfElements)]
|
||||
class MigrationAnalytic : IAnalytic
|
||||
{
|
||||
private Data data;
|
||||
public MigrationAnalytic(Data data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public bool TryGatherData(out IAnalytic.IData data, out Exception error)
|
||||
{
|
||||
error = null;
|
||||
data = this.data;
|
||||
return data != null;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class Data : IAnalytic.IData
|
||||
#else
|
||||
[Serializable]
|
||||
internal class Data
|
||||
#endif
|
||||
{
|
||||
[SerializeField]
|
||||
internal MigrationStepAnalyticsData total;
|
||||
[SerializeField]
|
||||
internal List<MigrationStepAnalyticsData> steps;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class MigrationStepAnalyticsData
|
||||
{
|
||||
[SerializeField]
|
||||
internal string pluginId;
|
||||
[SerializeField]
|
||||
internal string from;
|
||||
[SerializeField]
|
||||
internal string to;
|
||||
[SerializeField]
|
||||
internal bool success;
|
||||
[SerializeField]
|
||||
internal string exception;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user