Initial Commit

This commit is contained in:
Sebastian Cabrera 2021-08-02 05:44:37 -04:00
parent 53eb92e9af
commit 270ab7d11f
15341 changed files with 700234 additions and 0 deletions

View file

@ -0,0 +1 @@
# For dev package builds ignore the following

View file

@ -0,0 +1,6 @@
# For release package builds ignore the following
Samples/**
Samples.meta
Samples~/**
Samples~.meta
.npmignore.dev

View file

@ -0,0 +1,87 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
## [1.5.2] - 2021-05-05
### Changed
- User interface updated
- Names in different UI elements made to be more consistent with new naming schemes
## [1.5.1] - 2021-02-23
### Added
- Warn the user when an Input System Package event is referencing an action of the wrong type for that event
- A warning is raised when adding more than one Input unit in a SuperUnit
- "Open" inspector button and double clicking a graph in the project browser now opens the visual scripting editor
### Fixed
- Fixed "Restore to Defaults" buttons in the Project Settings window
- Fixed ThreadAbortException when entering Play Mode while searching in the Fuzzy Finder
- Fixed Visual Scripting Preferences being searchable [BOLT-1218](https://issuetracker.unity3d.com/issues/visual-scripting-preferences-are-not-searchable-when-using-search-in-the-preferences-window)
- Fixed ScalarAdd unit migration from 1.4.13 to 1.4.14 and above
- Fixed Open the graph window no longer causes Unity UI stop processing mouse click [BOLT-1159](https://issuetracker.unity3d.com/product/unity/issues/guid/BOLT-1159),
- Fixed Fuzzy finder no longer blinks when trying to add a node [BOLT-1157](https://issuetracker.unity3d.com/product/unity/issues/guid/BOLT-1157),
- Fixed Fuzzy search no longer drops keyboard inputs and respond slowly [BOLT-1214](https://issuetracker.unity3d.com/product/unity/issues/guid/BOLT-1214),
- Fixed Fuzzy finder search window no longer remains above all other windows [BOLT-1197](https://issuetracker.unity3d.com/product/unity/issues/guid/BOLT-1197)"
- Fixed Dropdown icon is not clipped with TextField under "Get Variable"
- Fixed Scale groups when zoom is not at 1x
- Fixed graph getting corrupted when adding "Get Action Map" unit
- Fixed node description being sometimes clipped
- Fixed warnings overflow in the console when deleting and adding a boolean variable in the blackboard
- Fixed warnings when entering play mode when the "Script Changes While Playing" is set to Recompile And Continue Playing
- Fixed resize cursor rect on group when graph window is zoomed
- Fixed VisualScripting.Generated folder is removed when removing the VisualScripting package.
- Fixed error when executing "Fix Missing Scripts" in a HDRP project
- Visual Scripting Preferences spacing has been adjusted to avoid overlaps
- Fixed rendering of inactive ObjectFields
- Fixed sidebar (graph inspector/blackboard) resize when a vertical scrollbar is needed
- Fixed variable type reset to Enum when changing from Enum to GameObject when both Blackbaord and Variables inspector are displayed
- Help button in the visual scripting Assets and Behaviours inspector now link to the package documentation.
- FlowMachine type is now back in usable types.
- Fixed GraphPointerException occurs when nesting graph within itself [BOLT-1257](https://issuetracker.unity3d.com/issues/visual-scripting-graphpointerexception-occurs-when-nesting-graph-within-itself)
- Fixed RenamedFrom attribute does not function correctly on array references to a renamed type [BOLT-1149](https://issuetracker.unity3d.com/product/unity/issues/guid/BOLT-1149)
- Fixed error message when custom inspectors are generated
- Fixed missing succession for Cooldown. Output of Cooldown completed is treated as unentered. [BOLT-725](https://issuetracker.unity3d.com/issues/bolt-1-output-of-cooldown-completed-is-treated-as-unentered)
- Fixed Object Variables tabs not updated when creating a Prefab
- Fixed console errors when deleting a Prefab with a Visual Script
- Fixed console errors when editing nested graphs during Play Mode
## [1.5.1-pre.3] - 2020-12-07
### Added
- Added Visual Scripting as built-in package as of Unity 2021.1
- Added New Input System Support. You can import the Input System package, activate the back-end and regenerate units to use.
- Added AOT Pre-Compile to automatically run when building AOT platforms
- Improved UI for deprecated built-in nodes
- Added automatic unit generation the first time the graph window is opened
### Changed
- Switched to delivering source instead of pre-built .NET 3/4 assemblies
- Updated Documentation
- Renamed assemblies to match Unity.VisualScripting naming scheme (Ex: Bolt.Core -> Unity.VisualScripting.Core)
- Merged Ludiq.Core and Ludiq.Graphs into Unity.VisualScripting.Core
- Moved Setup Wizard contents from pop-up on Editor startup to Player Settings. You can change the default settings from "Player Settings > Visual Scripting"
- Renamed "Assembly Options" to "Node Library"
- Renamed "Flow Graph" to "Script Graph"
- Renamed "Flow Machine" to "Script Machine"
- Renamed "Macro" graphs to "Graph" in machine source configuration and "GraphAsset" in Assets
- Renamed "Control Input/Output" to "Trigger Input/Output"
- Renamed "Value Input/Output" to "Data Input/Output"
- Updated built-in nodes. The Fuzzy Finder still accepts earlier version names of nodes.
- Renamed "Branch" node to "If"
- Renamed "Self" node to "This"
- Deprecated the previous Add unit. The Sum unit has been renamed to Add.
- Updated Window Naming
- Changed "Variables" window to "Blackboard"
- Changed "Graph" window to "Script Graph" and "State Graph"
- Updated Bolt Preferences
- Renamed Bolt Preferences to "Visual Scripting"
- Removed BoltEx
- Moved settings previously accessed from "Window > Bolt" to preferences
- Renamed Control Schemes from "Unity/Unreal" to "Default/Alternate" (Neither control scheme currently matches their respective editors' controls and will be updated in a future release)
- Consolidated Graph editor, Blackboard and Graph Inspector into a single window
- Updated Third-Party Notices
### Fixed
- Corrected UGUI event management to trickle down correctly when the hierarchy contains a Unity Message Listener [BOLT-2](https://issuetracker.unity3d.com/issues/bolt-1-unity-message-listener-blocks-proper-trickling-of-ugui-events-in-hierarchies)
- Fixed backup failures with large projects [BOLT-10](https://issuetracker.unity3d.com/issues/bolt-1-backup-fails-to-complete)
- Fixed "Null Reference" when opening the Graph Window for the first time [BOLT-996](https://issuetracker.unity3d.com/issues/nullreferenceexception-when-graph-window-is-opened-on-a-new-project)
- Fixed IL2CPP build crash on startup [BOLT-1036](https://issuetracker.unity3d.com/issues/bolt-bolt-1-il2cpp-release-build-crashes-on-startup-when-there-is-at-least-1-node-present-in-a-graph)
- Fixed IL2CPP issue around converting certain managed types [BOLT-8](https://issuetracker.unity3d.com/issues/bolt-1-il2cpp-encountered-a-managed-type-which-it-cannot-convert-ahead-of-time)
- Fixed deserialization issues when undoing graphs with Wait nodes [BOLT-679](https://issuetracker.unity3d.com/issues/bolt-deserialization-error-and-nodes-missing-after-pressing-undo-when-update-coroutine-with-wait-node-is-present-in-graph)
- Fixed "SelectOnEnum" node behaviour enums containing non-unique values e.g. "RuntimePlatform" [BOLT-688](https://issuetracker.unity3d.com/issues/select-on-enum-doesnt-work-with-the-runtimeplatform-enum)

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e943e3d5ede9d0848a8e889af1e6656c
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ee9f54d6cd5a17045a3f1c9877d4b7e6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
<<<<<<< HEAD:Package-Old/Bolt/Documentation/1. Introduction.meta
guid: 3804c151c03f29547b6b564ccc05bde0
=======
guid: 3dfa3c8fac2134fdda65f882f5a1a014
>>>>>>> [1010] Visual Script Project Settings UI Change:Packages/com.unity.bolt/VSSettingsProvider.meta
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,14 @@
using System.Collections.Generic;
using UnityEditor;
namespace Unity.VisualScripting
{
public class VSProjectSettingsProvider : Editor
{
[SettingsProvider]
public static SettingsProvider CreateProjectSettingProvider()
{
return new VSProjectSettingsProviderView();
}
}
}

View file

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

View file

@ -0,0 +1,97 @@
using UnityEngine;
using UnityEditor;
namespace Unity.VisualScripting
{
class VSProjectSettingsProviderView : SettingsProvider
{
private const string path = "Project/Visual Scripting";
private const string title = "Visual Scripting";
private const string titleGroup = "Generate Units";
VSSettingsAssembly vsSettingsAssembly;
VSSettingsTypeOption vsSettingsTypeOption;
VSSettingsCustomProperty vsSettingsCustomProperty;
VSSettingsBackup vsSettingsBackup;
VSSettingsScriptReferenceResolver vsSettingsScriptReferenceResolver;
VSSettingsUpdate vsSettingsUpdate;
public VSProjectSettingsProviderView() : base(path, SettingsScope.Project)
{
label = title;
}
private void CreateOptionsIfNeeded()
{
if (vsSettingsAssembly == null)
{
vsSettingsAssembly = new VSSettingsAssembly();
}
if (vsSettingsTypeOption == null)
{
vsSettingsTypeOption = new VSSettingsTypeOption();
}
if (vsSettingsCustomProperty == null)
{
vsSettingsCustomProperty = new VSSettingsCustomProperty();
}
if (vsSettingsBackup == null)
{
vsSettingsBackup = new VSSettingsBackup();
}
if (vsSettingsScriptReferenceResolver == null)
{
vsSettingsScriptReferenceResolver = new VSSettingsScriptReferenceResolver();
}
if (vsSettingsUpdate == null)
{
vsSettingsUpdate = new VSSettingsUpdate();
}
}
public override void OnGUI(string searchContext)
{
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 (BoltCore.instance == null)
{
EditorGUILayout.HelpBox("Loading Configuration...", MessageType.Info);
return;
}
CreateOptionsIfNeeded();
vsSettingsTypeOption.OnGUI();
GUILayout.Space(10f);
vsSettingsAssembly.OnGUI();
GUILayout.Space(10f);
vsSettingsCustomProperty.OnGUI();
GUILayout.Space(10f);
vsSettingsBackup.OnGUI();
GUILayout.Space(10f);
vsSettingsScriptReferenceResolver.OnGUI();
GUILayout.Space(10f);
vsSettingsUpdate.OnGUI();
}
}
}

View file

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

View file

@ -0,0 +1,76 @@
using UnityEngine;
using UnityEditor;
namespace Unity.VisualScripting
{
public class VSSettingsAssembly
{
private const string completeLabel = "Regenerate Units";
private 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 units.\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.";
public VSSettingsAssembly()
{
assemblyOptionsMetadata = BoltCore.Configuration.GetMetadata(nameof(BoltCoreConfiguration.assemblyOptions));
}
static class Styles
{
public static readonly GUIStyle background;
public static readonly GUIStyle defaultsButton;
public static readonly 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));
float height = LudiqGUI.GetInspectorHeight(null, assemblyOptionsMetadata, Styles.optionsWidth, GUIContent.none);
EditorGUI.BeginChangeCheck();
var position = GUILayoutUtility.GetRect(Styles.optionsWidth, height);
LudiqGUI.Inspector(assemblyOptionsMetadata, position, GUIContent.none);
if (EditorGUI.EndChangeCheck())
{
assemblyOptionsMetadata.Save();
Codebase.UpdateSettings();
}
if (GUILayout.Button("Reset to Defaults", Styles.defaultsButton))
{
assemblyOptionsMetadata.Reset(true);
assemblyOptionsMetadata.Save();
}
LudiqGUI.EndVertical();
}
if (GUILayout.Button(completeLabel, Styles.defaultsButton))
{
UnitBase.Rebuild();
EditorUtility.DisplayDialog("Visual Script", "Regenerate Units completed", "OK");
}
}
}
}

View file

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

View file

@ -0,0 +1,46 @@
using System.Diagnostics;
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
public class VSSettingsBackup
{
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);
}
}
public static class Styles
{
static Styles()
{
defaultsButton = new GUIStyle("Button");
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
}
public static readonly GUIStyle defaultsButton;
}
}
}

View file

@ -0,0 +1,15 @@
fileFormatVersion: 2
<<<<<<< HEAD:Packages/com.unity.bolt/Editor/Bolt.Core/BoltGUI.cs.meta
guid: 50455e66302b715488a9218e30b0ab24
=======
guid: 9b13d76d6b80b4b1ab4d0fac8c174df4
>>>>>>> [1010] Visual Script Project Settings UI Change:Packages/com.unity.bolt/VSSettingsProvider/VSSettingsBackup.cs.meta
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,49 @@
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
public class VSSettingsCustomProperty
{
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 Bolt 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");
}
}
public static class Styles
{
static Styles()
{
defaultsButton = new GUIStyle("Button");
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
regenerateLabel = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
regenerateLabel.wordWrap = true;
}
public static readonly GUIStyle defaultsButton;
public static readonly GUIStyle regenerateLabel;
}
}
}

View file

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

View file

@ -0,0 +1,21 @@
{
"name": "VSSettingsProvider",
"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
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2aa54ddaa48744e1caddee916e39805e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,40 @@
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
public class VSSettingsScriptReferenceResolver
{
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();
}
}
public static class Styles
{
static Styles()
{
defaultsButton = new GUIStyle("Button");
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
regenerateLabel = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
regenerateLabel.wordWrap = true;
}
public static readonly GUIStyle defaultsButton;
public static readonly GUIStyle regenerateLabel;
}
}
}

View file

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

View file

@ -0,0 +1,68 @@
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
public class VSSettingsTypeOption
{
private readonly PluginConfigurationItemMetadata typeOptionsMetadata;
bool showTypeOption = false;
private const string titleTypeOption = "Type Options";
private const string descriptionTypeOption = "Choose the types you want to use for variables and units.\n"
+ "MonoBehaviour types are always included.";
static class Styles
{
public static readonly GUIStyle background;
public static readonly GUIStyle defaultsButton;
public static readonly 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 VSSettingsTypeOption()
{
typeOptionsMetadata = BoltCore.Configuration.GetMetadata(nameof(BoltCoreConfiguration.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.Save();
Codebase.UpdateSettings();
}
if (GUILayout.Button("Reset to Defaults", Styles.defaultsButton))
{
typeOptionsMetadata.Reset(true);
typeOptionsMetadata.Save();
}
LudiqGUI.EndVertical();
}
}
}
}

View file

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

View file

@ -0,0 +1,170 @@
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace Unity.VisualScripting
{
public class VSSettingsUpdate
{
private const string title = "Plugins Update";
private const string buttonLabel = "Update";
private readonly List<Plugin> plugins;
public VSSettingsUpdate()
{
IEnumerable<Plugin> allPlugins = PluginContainer.GetAllPlugins();
Ensure.That(nameof(allPlugins)).IsNotNull(allPlugins);
plugins = new List<Plugin>(allPlugins.OrderByDependencies());
}
public void OnGUI()
{
GUILayout.Space(5f);
GUILayout.Label(title, EditorStyles.boldLabel);
GUILayout.Space(5f);
GUILayout.BeginVertical();
if (plugins.All(plugin => plugin.manifest.savedVersion == plugin.manifest.currentVersion))
{
string label = "All your plugins are up to date.";
GUILayout.BeginHorizontal(EditorStyles.helpBox);
GUILayout.Label(EditorGUIUtility.IconContent("console.infoicon"), GUILayout.ExpandWidth(false));
GUILayout.Box(label, EditorStyles.wordWrappedLabel);
GUILayout.EndHorizontal();
}
GUILayout.Space(5f);
DrawPluginVersionTable(plugins);
GUILayout.Space(5f);
if (plugins.Any(plugin => plugin.manifest.savedVersion != plugin.manifest.currentVersion))
{
if (GUILayout.Button(buttonLabel, Styles.defaultsButton))
{
VSBackupUtility.Backup();
(new VSMigrationUtility()).OnUpdate();
}
}
LudiqGUI.EndVertical();
}
private static void DrawPluginVersionTable(IEnumerable<Plugin> plugins)
{
var savedColumnHeader = new GUIContent("Saved");
var installedColumnHeader = new GUIContent("Installed");
var pluginsColumnWidth = 0f;
var savedColumnWidth = Styles.columnHeader.CalcSize(savedColumnHeader).x;
var installedColumnWidth = Styles.columnHeader.CalcSize(installedColumnHeader).x;
var stateColumnWidth = 0f;
foreach (var plugin in plugins)
{
pluginsColumnWidth = Mathf.Max(pluginsColumnWidth, Styles.pluginName.CalcSize(new GUIContent(plugin.manifest.name)).x);
savedColumnWidth = Mathf.Max(savedColumnWidth, Styles.version.CalcSize(new GUIContent(plugin.manifest.savedVersion.ToString())).x);
installedColumnWidth = Mathf.Max(installedColumnWidth, Styles.version.CalcSize(new GUIContent(plugin.manifest.currentVersion.ToString())).x);
stateColumnWidth = Mathf.Max(stateColumnWidth, Styles.state.CalcSize(VersionStateContent(plugin)).x);
}
LudiqGUI.BeginVertical();
// Header row
LudiqGUI.BeginHorizontal();
LudiqGUI.FlexibleSpace();
GUILayout.Label(GUIContent.none, Styles.columnHeader, GUILayout.Width(pluginsColumnWidth));
LudiqGUI.Space(Styles.columnSpacing);
GUILayout.Label(savedColumnHeader, Styles.columnHeader, GUILayout.Width(savedColumnWidth));
LudiqGUI.Space(Styles.columnSpacing);
GUILayout.Label(installedColumnHeader, Styles.columnHeader, GUILayout.Width(installedColumnWidth));
LudiqGUI.Space(Styles.columnSpacing);
GUILayout.Label(GUIContent.none, Styles.state, GUILayout.Width(stateColumnWidth));
LudiqGUI.FlexibleSpace();
LudiqGUI.EndHorizontal();
// Plugin rows
foreach (var plugin in plugins)
{
LudiqGUI.Space(Styles.rowSpacing);
LudiqGUI.BeginHorizontal();
LudiqGUI.FlexibleSpace();
GUILayout.Label(new GUIContent(plugin.manifest.name), Styles.pluginName, GUILayout.Width(pluginsColumnWidth));
LudiqGUI.Space(Styles.columnSpacing);
GUILayout.Label(new GUIContent(plugin.manifest.savedVersion.ToString()), Styles.version, GUILayout.Width(savedColumnWidth));
LudiqGUI.Space(Styles.columnSpacing);
GUILayout.Label(new GUIContent(plugin.manifest.currentVersion.ToString()), Styles.version, GUILayout.Width(installedColumnWidth));
LudiqGUI.Space(Styles.columnSpacing);
GUILayout.Label(VersionStateContent(plugin), Styles.state, GUILayout.Width(stateColumnWidth));
LudiqGUI.FlexibleSpace();
LudiqGUI.EndHorizontal();
}
LudiqGUI.EndVertical();
}
private static GUIContent VersionStateContent(Plugin plugin)
{
if (plugin.manifest.savedVersion < plugin.manifest.currentVersion)
{
return new GUIContent("New version", BoltCore.Icons.upgrade?[IconSize.Small]);
}
else if (plugin.manifest.savedVersion == plugin.manifest.currentVersion)
{
return new GUIContent("Up to date", BoltCore.Icons.upToDate?[IconSize.Small]);
}
else if (plugin.manifest.savedVersion > plugin.manifest.currentVersion)
{
return new GUIContent("Downgrade", BoltCore.Icons.downgrade?[IconSize.Small]);
}
else
{
return new GUIContent("Unknown");
}
}
public static class Styles
{
static Styles()
{
defaultsButton = new GUIStyle("Button");
defaultsButton.padding = new RectOffset(10, 10, 4, 4);
pluginName = new GUIStyle(EditorStyles.label);
pluginName.alignment = TextAnchor.MiddleRight;
version = new GUIStyle(EditorStyles.label);
version.alignment = TextAnchor.MiddleCenter;
columnHeader = new GUIStyle(EditorStyles.label);
columnHeader.alignment = TextAnchor.LowerCenter;
columnHeader.fontStyle = FontStyle.Bold;
state = new GUIStyle();
state.fixedWidth = IconSize.Small;
state.fixedHeight = IconSize.Small;
state.imagePosition = ImagePosition.ImageOnly;
state.alignment = TextAnchor.MiddleCenter;
}
public static readonly GUIStyle defaultsButton;
public static readonly GUIStyle pluginName;
public static readonly GUIStyle columnHeader;
public static readonly GUIStyle version;
public static readonly GUIStyle state;
public static readonly float columnSpacing = 10;
public static readonly float rowSpacing = 10;
}
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7abb56c9dd89a544a9995a060ab55368
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a0a037cc0a236493996d666b0ab8690c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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; }
}
}

View file

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

View file

@ -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; }
}
}

View file

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

View file

@ -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());
}
}
}

View file

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

View file

@ -0,0 +1,6 @@
namespace Unity.VisualScripting
{
public abstract class Analysis : IAnalysis
{
}
}

View file

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

View file

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public class GraphElementAnalysis : IGraphElementAnalysis
{
public List<Warning> warnings { get; set; } = new List<Warning>();
}
}

View file

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

View file

@ -0,0 +1,11 @@
namespace Unity.VisualScripting
{
public interface IAnalyser
{
IAnalysis analysis { get; }
bool isDirty { get; set; }
void Validate();
}
}

View file

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

View file

@ -0,0 +1,6 @@
namespace Unity.VisualScripting
{
public interface IAnalysis
{
}
}

View file

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

View file

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public interface IGraphElementAnalysis : IAnalysis
{
List<Warning> warnings { get; }
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fae0344df02e74e0988c577297cc556d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,55 @@
using UnityEditor;
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";
static bool isRegistered = false;
public static void CollectAndSend()
{
if (!EditorAnalytics.enabled)
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;
}
private static UsageAnalyticsData CollectData()
{
var data = new UsageAnalyticsData
{
productVersion = BoltProduct.instance.version.ToString(),
};
return data;
}
private struct UsageAnalyticsData
{
public string productVersion;
}
}
}

View file

@ -0,0 +1,15 @@
fileFormatVersion: 2
<<<<<<< HEAD:Packages/com.unity.bolt/Editor/Bolt.Core/Analytics/Analytics.cs.meta
guid: 59718df20b933421a9c465fcbeff7836
=======
guid: b26c0afd728514b08ae2eb47fdd61013
>>>>>>> [1010] Visual Script Project Settings UI Change:Packages/com.unity.bolt/VSSettingsProvider/VSBackupUtility.cs.meta
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 662cc5e740e0841e1bb91853ab803f33
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Unity.VisualScripting
{
public abstract class Assigner<TTarget, TAssignee> : IAssigner
where TAssignee : class
{
protected Assigner(TTarget target, TAssignee assignee)
{
Ensure.That(nameof(target)).IsNotNull(target);
Ensure.That(nameof(assignee)).IsNotNull(assignee);
this.target = target;
this.assignee = assignee;
var assignerType = GetType();
if (!_assignments.ContainsKey(assignerType))
{
_assignments.Add(assignerType, Assignment.Fetch(assignerType, typeof(TAssignee)).ToArray());
_transientAssignments.Add(assignerType, _assignments[assignerType].Where(a => !a.cache).ToArray());
}
}
public TTarget target { get; }
public TAssignee assignee { get; }
public bool isDirty { get; set; } = true;
public void Validate()
{
if (isDirty)
{
AssignAll();
}
else
{
AssignTransient();
}
}
protected void AssignAll()
{
isDirty = false;
foreach (var assignment in assignments)
{
assignment.Run(this, assignee);
}
}
protected void AssignTransient()
{
foreach (var assignment in transientAssignments)
{
assignment.Run(this, assignee);
}
}
public virtual void ValueChanged() { }
public Assignment[] assignments => _assignments[GetType()];
public Assignment[] transientAssignments => _transientAssignments[GetType()];
private static readonly Dictionary<Type, Assignment[]> _assignments = new Dictionary<Type, Assignment[]>();
private static readonly Dictionary<Type, Assignment[]> _transientAssignments = new Dictionary<Type, Assignment[]>();
}
}

View file

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

View file

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Unity.VisualScripting
{
public sealed class Assignment
{
public Assignment(Member assigner, Type assigneeType)
{
Ensure.That(nameof(assigneeType)).IsNotNull(assigneeType);
this.assigner = assigner;
var assignsAttribute = assigner.info.GetAttribute<AssignsAttribute>();
assignee = new Member(assigneeType, assignsAttribute?.memberName ?? assigner.name.FirstCharacterToLower());
requiresAPI = assigner.info.HasAttribute<RequiresUnityAPIAttribute>();
cache = assignsAttribute?.cache ?? true;
assigner.Prewarm();
assignee.Prewarm();
}
public Member assigner { get; }
public Member assignee { get; }
public bool requiresAPI { get; }
public bool cache { get; }
public void Run(object assigner, object assignee)
{
if (requiresAPI)
{
UnityAPI.Async(() => _Run(assigner, assignee));
}
else
{
_Run(assigner, assignee);
}
}
private void _Run(object assigner, object assignee)
{
var oldValue = this.assignee.Get(assignee);
var newValue = ConversionUtility.Convert(this.assigner.Invoke(assigner), this.assignee.type);
this.assignee.Set(assignee, newValue);
if (!Equals(oldValue, newValue))
{
if (assigner is IAssigner _assigner)
{
_assigner.ValueChanged();
}
}
}
public static IEnumerable<Assignment> Fetch(Type descriptorType, Type descriptionType)
{
var bindingFlags = BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic;
return descriptorType.GetMethods(bindingFlags)
.Where(m => m.HasAttribute<AssignsAttribute>())
.Select(m => new Assignment(m.ToManipulator(descriptorType), descriptionType));
}
}
}

View file

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

View file

@ -0,0 +1,19 @@
using System;
namespace Unity.VisualScripting
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class AssignsAttribute : Attribute
{
public AssignsAttribute() { }
public AssignsAttribute(string memberName)
{
this.memberName = memberName;
}
public string memberName { get; }
public bool cache { get; set; } = true;
}
}

View file

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

View file

@ -0,0 +1,7 @@
namespace Unity.VisualScripting
{
public interface IAssigner
{
void ValueChanged();
}
}

View file

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

View file

@ -0,0 +1,51 @@
using UnityEditor;
using UnityEngine;
using UnityEvent = UnityEngine.Event;
namespace Unity.VisualScripting
{
public static class BoltGUI
{
private static UnityEvent e => UnityEvent.current;
public static float GetVariableFieldHeight(GUIContent label, string value, ActionDirection direction)
{
return EditorGUIUtility.singleLineHeight;
}
public static string VariableField(Rect position, GUIContent label, string value, ActionDirection direction)
{
position = EditorGUI.PrefixLabel(position, label);
var style = direction != ActionDirection.Any ? BoltStyles.variableFieldWithDirectionIndicator : BoltStyles.variableFieldWithoutDirectionIndicator;
value = EditorGUI.TextField(position, GUIContent.none, value, style);
var iconPosition = new Rect
(
position.x + 3,
position.y + 2,
12,
12
);
GUI.DrawTexture(iconPosition, BoltCore.Icons.variable?[IconSize.Small]);
if (direction != ActionDirection.Any)
{
var arrowPosition = new Rect
(
iconPosition.xMax + (direction == ActionDirection.Get ? 12 : -2),
position.y + 2,
12 * (direction == ActionDirection.Get ? -1 : 1),
12
);
if (e.type == EventType.Repaint)
{
BoltStyles.variableFieldDirectionIndicator.Draw(arrowPosition, false, false, false, false);
}
}
return value;
}
}
}

View file

@ -0,0 +1,15 @@
fileFormatVersion: 2
<<<<<<< HEAD:Packages/com.unity.bolt/Editor/Bolt.Core/BoltGUI.cs.meta
guid: 0c9b7e151c1f64d48b39eca8d419c2b5
=======
guid: 9b13d76d6b80b4b1ab4d0fac8c174df4
>>>>>>> [1010] Visual Script Project Settings UI Change:Packages/com.unity.bolt/VSSettingsProvider/VSSettingsBackup.cs.meta
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnityEditor;
namespace Unity.VisualScripting
{
[Product(ID)]
public sealed class BoltProduct : Product
{
public BoltProduct() { }
public override void Initialize()
{
base.Initialize();
logo = BoltCore.Resources.LoadTexture("Logos/LogoBolt.png", CreateTextureOptions.Scalable)?.Single();
}
public override string configurationPanelLabel => "Bolt";
public override string name => "Bolt";
public override string description => "";
public override string authorLabel => "Designed & Developed by ";
public override string author => "";
public override string copyrightHolder => "Unity";
public override SemanticVersion version => "1.5.1";
public override string publisherUrl => "";
public override string websiteUrl => "";
public override string supportUrl => "";
public override string manualUrl => "https://docs.unity3d.com/Packages/com.unity.bolt@latest";
public override string assetStoreUrl => "http://u3d.as/1Md2";
public const string ID = "Bolt";
#if VISUAL_SCRIPT_INTERNAL
public const int ToolsMenuPriority = -990000;
public const int DeveloperToolsMenuPriority = ToolsMenuPriority + 1000;
#endif
public static BoltProduct instance => (BoltProduct)ProductContainer.GetProduct(ID);
[SettingsProvider]
private static SettingsProvider BoltSettingsProvider()
{
return new VSEditorSettingsProviderView();
}
private static bool PrepareForRelease()
{
if (!EditorUtility.DisplayDialog("Delete Generated Files", "This action will delete all generated files, including those containing user data.\n\nAre you sure you want to continue?", "Confirm", "Cancel"))
{
return false;
}
PluginConfiguration.DeleteAllProjectSettings();
foreach (var plugin in PluginContainer.plugins)
{
PathUtility.DeleteDirectoryIfExists(plugin.paths.persistentGenerated);
PathUtility.DeleteDirectoryIfExists(plugin.paths.transientGenerated);
}
return true;
}
#if VISUAL_SCRIPT_INTERNAL
[MenuItem("Tools/Bolt/Internal/Export Release Asset Package...", priority = DeveloperToolsMenuPriority + 102)]
#endif
private static void ExportReleasePackage()
{
if (!PrepareForRelease())
{
return;
}
var exportPath = EditorUtility.SaveFilePanel("Export Release Package",
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
"Bolt_" + instance.version.ToString().Replace(".", "_").Replace(" ", "_"),
"unitypackage");
if (exportPath == null)
{
return;
}
var packageDirectory = Path.GetDirectoryName(exportPath);
var paths = new List<string>()
{
PathUtility.GetPackageRootPath()
};
AssetDatabase.ExportPackage(paths.ToArray(), exportPath, ExportPackageOptions.Recurse);
if (EditorUtility.DisplayDialog("Export Release Package", "Release package export complete.\nOpen containing folder?", "Open Folder", "Close"))
{
Process.Start(packageDirectory);
}
}
}
}

View file

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

View file

@ -0,0 +1,24 @@
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
public static class BoltStyles
{
static BoltStyles()
{
// Variables
variableFieldDirectionIndicator = "AC LeftArrow";
variableFieldWithoutDirectionIndicator = new GUIStyle(EditorStyles.textField);
variableFieldWithoutDirectionIndicator.padding.left = IconSize.Small;
variableFieldWithDirectionIndicator = new GUIStyle(variableFieldWithoutDirectionIndicator);
variableFieldWithDirectionIndicator.padding.left = 24;
}
// Variables
public static readonly GUIStyle variableFieldDirectionIndicator;
public static readonly GUIStyle variableFieldWithDirectionIndicator;
public static readonly GUIStyle variableFieldWithoutDirectionIndicator;
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 31d3bc055420f4ee59008eb8996d7df2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,35 @@
namespace Unity.VisualScripting
{
public enum AlignOperation
{
/// <summary>
/// Align the left edges of the selected elements.
/// </summary>
AlignLeftEdges,
/// <summary>
/// Align the horizontal centers of the selected elements.
/// </summary>
AlignCenters,
/// <summary>
/// Align the right edges of the selected elements.
/// </summary>
AlignRightEdges,
/// <summary>
/// Align the top edges of the selected elements.
/// </summary>
AlignTopEdges,
/// <summary>
/// Align the vertical middles of the selected elements.
/// </summary>
AlignMiddles,
/// <summary>
/// Align the bottom edges of the selected elements.
/// </summary>
AlignBottomEdges
}
}

View file

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

View file

@ -0,0 +1,15 @@
using System;
namespace Unity.VisualScripting
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public sealed class CanvasAttribute : Attribute, IDecoratorAttribute
{
public CanvasAttribute(Type type)
{
this.type = type;
}
public Type type { get; private set; }
}
}

View file

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

View file

@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
public enum CanvasControlScheme
{
Unity,
Unreal
}
}

View file

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

View file

@ -0,0 +1,52 @@
namespace Unity.VisualScripting
{
public class CanvasProvider : SingleDecoratorProvider<IGraph, ICanvas, CanvasAttribute>
{
static CanvasProvider()
{
instance = new CanvasProvider();
}
public static CanvasProvider instance { get; }
protected override bool cache => true;
public override bool IsValid(IGraph graph)
{
return true;
}
}
public static class XCanvasProvider
{
public static ICanvas Canvas(this IGraph graph)
{
return CanvasProvider.instance.GetDecorator(graph);
}
public static TCanvas Canvas<TCanvas>(this IGraph graph) where TCanvas : ICanvas
{
return CanvasProvider.instance.GetDecorator<TCanvas>(graph);
}
public static IWidget Widget(this ICanvas context, IGraphItem item)
{
return context.widgetProvider.GetDecorator(item);
}
public static TWidget Widget<TWidget>(this ICanvas context, IGraphItem item) where TWidget : IWidget
{
return context.widgetProvider.GetDecorator<TWidget>(item);
}
public static IGraphElementWidget Widget(this ICanvas context, IGraphElement element)
{
return (IGraphElementWidget)context.widgetProvider.GetDecorator(element);
}
public static TWidget Widget<TWidget>(this ICanvas context, IGraphElement element) where TWidget : IGraphElementWidget
{
return context.widgetProvider.GetDecorator<TWidget>(element);
}
}
}

View file

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

View file

@ -0,0 +1,53 @@
namespace Unity.VisualScripting
{
public enum DistributeOperation
{
/// <summary>
/// Distribute the selected elements so that the left edges
/// are at equal distance of one another.
/// </summary>
DistributeLeftEdges,
/// <summary>
/// Distribute the selected elements so that the horizontal centers
/// are at equal distance of one another.
/// </summary>
DistributeCenters,
/// <summary>
/// Distribute the selected elements so that the right edges
/// are at equal distance of one another.
/// </summary>
DistributeRightEdges,
/// <summary>
/// Distribute the selected elements so that the horizontal gaps
/// are all of equal size.
/// </summary>
DistributeHorizontalGaps,
/// <summary>
/// Distribute the selected elements so that the top edges
/// are at equal distance of one another.
/// </summary>
DistributeTopEdges,
/// <summary>
/// Distribute the selected elements so that the vertical middles
/// are at equal distance of one another.
/// </summary>
DistributeMiddles,
/// <summary>
/// Distribute the selected elements so that the bottom edges
/// are at equal distance of one another.
/// </summary>
DistributeBottomEdges,
/// <summary>
/// Distribute the selected elements so that the vertical gaps
/// are all of equal size.
/// </summary>
DistributeVerticalGaps
}
}

View file

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

View file

@ -0,0 +1,173 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Unity.VisualScripting
{
public interface ICanvas : IDisposable, IDragAndDropHandler
{
void Cache();
#region Model
ICanvasWindow window { get; set; }
IGraph graph { get; }
WidgetProvider widgetProvider { get; }
GraphSelection selection { get; }
#endregion
#region Widgets
IEnumerable<IWidget> widgets { get; }
void Recollect();
void CacheWidgetCollections();
#endregion
#region Hovering
IWidget hoveredWidget { get; }
#endregion
#region Deleting
void DeleteSelection();
#endregion
#region Clipboard
void ShrinkCopyGroup(HashSet<IGraphElement> copyGroup);
#endregion
#region Lifecycle
void RegisterControls();
void Open();
void Close();
void Update();
void BeforeFrame();
void OnGUI();
#endregion
#region Viewing
float zoom { get; }
Vector2 pan { get; }
void UpdateViewport();
Rect viewport { get; set; }
Vector2 mousePosition { get; }
bool isMouseOver { get; }
bool isMouseOverBackground { get; }
void ViewElements(IEnumerable<IGraphElement> elements);
bool IsVisible(IWidget widget);
#endregion
#region Positioning
void CacheWidgetPositions();
#endregion
#region Lassoing
bool isLassoing { get; }
Rect lassoArea { get; }
#endregion
#region Selecting
bool isSelecting { get; }
Rect selectionArea { get; }
#endregion
#region Grouping
bool isGrouping { get; }
Rect groupArea { get; }
#endregion
#region Dragging
bool isDragging { get; }
void BeginDrag(EventWrapper e);
void Drag(EventWrapper e);
void EndDrag(EventWrapper e);
#endregion
#region Layout
void Align(AlignOperation operation);
void Distribute(DistributeOperation operation);
#endregion
#region Timing
float frameDeltaTime { get; }
float eventDeltaTime { get; }
float repaintDeltaTime { get; }
#endregion
#region Window
void OnToolbarGUI();
event Action delayCall;
Queue<Action> delayedCalls { get; }
#endregion
}
}

View file

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

View file

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public interface IGraphContextExtension : IDragAndDropHandler
{
IEnumerable<GraphContextMenuItem> contextMenuItems { get; }
}
}

View file

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

View file

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

View file

@ -0,0 +1,134 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace Unity.VisualScripting
{
/// <summary>
/// A list of widgets that can be safely iterated over even if the collection changes during iteration.
/// </summary>
public class WidgetList<TWidget> : Collection<TWidget>, IEnumerable<TWidget> where TWidget : class, IWidget
{
private uint version;
private readonly ICanvas canvas;
public WidgetList(ICanvas canvas)
{
Ensure.That(nameof(canvas)).IsNotNull(canvas);
this.canvas = canvas;
}
protected override void InsertItem(int index, TWidget item)
{
base.InsertItem(index, item);
version++;
}
protected override void RemoveItem(int index)
{
base.RemoveItem(index);
version++;
}
protected override void ClearItems()
{
base.ClearItems();
version++;
}
public new Enumerator GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator<TWidget> IEnumerable<TWidget>.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public struct Enumerator : IEnumerator<TWidget>
{
private readonly WidgetList<TWidget> list;
private int index;
private TWidget current;
private bool invalid;
private readonly uint version;
private IGraph graph;
public Enumerator(WidgetList<TWidget> list) : this()
{
this.list = list;
version = list.version;
// Micro optim
graph = list.canvas.graph;
}
public void Dispose() { }
public bool MoveNext()
{
// Stop if the list changed
if (version != list.version)
{
current = null;
invalid = true;
return false;
}
// Micro optim
var count = list.Count;
// Find the next element that is within the graph
while (index < count)
{
current = list[index];
index++;
if (current.item.graph == graph)
{
return true;
}
}
// Expleted the list
current = null;
invalid = true;
return false;
}
public TWidget Current => current;
object IEnumerator.Current
{
get
{
if (invalid)
{
throw new InvalidOperationException();
}
return Current;
}
}
void IEnumerator.Reset()
{
throw new InvalidOperationException();
}
}
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d95a4548a35ec4b78ad08d0210b776ec
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,321 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Unity.VisualScripting
{
[InitializeAfterPlugins]
public static class GraphClipboard
{
static GraphClipboard()
{
singleClipboard = new Clipboard();
groupClipboard = new Clipboard();
GraphWindow.activeContextChanged += OnContextChange;
}
private static Event e => Event.current;
private static void OnContextChange(IGraphContext context)
{
GraphClipboard.context = context;
}
private static IGraphContext context;
#region Context Shortcuts
private static GraphReference reference => context.reference;
private static IGraph graph => context.graph;
private static ICanvas canvas => context.canvas;
private static GraphSelection selection => context.selection;
#endregion
public static Clipboard singleClipboard { get; }
public static Clipboard groupClipboard { get; }
public static bool canCopySelection => selection.Count > 0;
public static bool canPaste
{
get
{
if (selection.Count == 1 && CanPasteInside(selection.Single()))
{
return true;
}
else
{
return canPasteOutside;
}
}
}
public static bool canPasteOutside => groupClipboard.containsData && GetPasteGroup().Any();
public static bool canDuplicateSelection => GetCopyGroup(selection).Count > 0;
private static HashSet<IGraphElement> GetCopyGroup(IEnumerable<IGraphElement> elements)
{
var copyGroup = new HashSet<IGraphElement>();
foreach (var element in elements)
{
copyGroup.Add(element);
canvas.Widget(element).ExpandCopyGroup(copyGroup);
}
canvas.ShrinkCopyGroup(copyGroup);
return copyGroup;
}
private static List<IGraphElement> GetPasteGroup()
{
return groupClipboard.Paste<HashSet<IGraphElement>>()
.Where(e => graph.elements.Includes(e.GetType()))
.OrderBy(e => e.dependencyOrder)
.ToList();
}
public static void CopyElement(IGraphElement element)
{
Ensure.That(nameof(element)).IsNotNull(element);
singleClipboard.Copy(element);
groupClipboard.Copy(GetCopyGroup(element.Yield()));
}
public static void CopySelection()
{
if (!canCopySelection)
{
throw new InvalidOperationException();
}
if (selection.Count == 1)
{
CopyElement(selection.Single());
}
else
{
singleClipboard.Clear();
groupClipboard.Copy(GetCopyGroup(selection));
}
e?.TryUse();
}
public static void Paste(Vector2? position = null)
{
if (!canPaste)
{
throw new InvalidOperationException();
}
if (selection.Count == 1 && CanPasteInside(selection.Single()))
{
PasteInside(selection.Single());
}
else
{
PasteOutside(true, position);
}
}
public static bool CanPasteInside(IGraphElement element)
{
Ensure.That(nameof(element)).IsNotNull(element);
// TODO: A solid PasteInside implementation would work like ReplaceUnit:
// Implement an IPreservable interface, preserve, remove, recreate, apply.
// This would make entirely sure that all OnAdd/OnRemove handlers get called,
// and wouldn't require any per-element implementation. Plus, it would
// allow pasting across element types while preserving connections/transitions!
return false;
}
public static void PasteInside(IGraphElement element)
{
Ensure.That(nameof(element)).IsNotNull(element);
if (!CanPasteInside(element))
{
throw new InvalidOperationException();
}
UndoUtility.RecordEditedObject("Paste Graph Element");
throw new NotImplementedException();
//GUI.changed = true;
//e?.TryUse();
}
public static void PasteOutside(bool reposition, Vector2? position = null)
{
if (!canPasteOutside)
{
throw new InvalidOperationException();
}
UndoUtility.RecordEditedObject("Paste Graph Elements");
var pastedElements = GetPasteGroup();
// Assign new GUIDs
foreach (var pastedElement in pastedElements)
{
pastedElement.guid = Guid.NewGuid();
}
// Add elements to graph and selection
selection.Clear();
foreach (var pastedElement in pastedElements)
{
if (!pastedElement.HandleDependencies())
{
continue;
}
graph.elements.Add(pastedElement);
selection.Add(pastedElement);
}
canvas.Cache();
foreach (var pastedElement in pastedElements)
{
var pastedWidget = canvas.Widget(pastedElement);
pastedWidget.BringToFront();
}
var pastedWidgets = pastedElements.Select(e => canvas.Widget(e)).ToList();
// Recenter elements in graph view
if (reposition)
{
var area = GraphGUI.CalculateArea(pastedWidgets.Where(widget => widget.canDrag));
Vector2 delta;
if (position.HasValue)
{
delta = position.Value - area.position;
}
else
{
delta = graph.pan - area.center;
}
foreach (var pastedWidget in pastedWidgets)
{
if (pastedWidget.canDrag)
{
pastedWidget.position = new Rect(pastedWidget.position.position + delta, pastedWidget.position.size).PixelPerfect();
pastedWidget.Reposition();
pastedWidget.CachePositionFirstPass();
pastedWidget.CachePosition();
}
}
}
// Space out overlapping elements
foreach (var pastedWidget in pastedWidgets)
{
if (pastedWidget.canDrag)
{
var distanciation = 20;
var timeout = 100;
var timeoutIndex = 0;
while (GraphGUI.PositionOverlaps(canvas, pastedWidget, 5))
{
// Space the widget out
pastedWidget.position = new Rect(pastedWidget.position.position + new Vector2(distanciation, distanciation), pastedWidget.position.size).PixelPerfect();
// Calculate the resulting position immediately
pastedWidget.CachePositionFirstPass();
pastedWidget.CachePosition();
// Mark it as invalid still so dependencies like ports will be recached
pastedWidget.Reposition();
// Failsafe to keep the editor from freezing
if (++timeoutIndex > timeout)
{
Debug.LogWarning($"Failed to space out pasted element: {pastedWidget.element}");
break;
}
}
}
}
canvas.Cache();
GUI.changed = true;
e?.TryUse();
}
public static void CutSelection()
{
UndoUtility.RecordEditedObject("Cut Graph Element Selection");
CopySelection();
canvas.DeleteSelection();
}
public static void DuplicateSelection()
{
object singleClipboardRestore = null;
object groupClipboardRestore = null;
if (singleClipboard.containsData)
{
singleClipboardRestore = singleClipboard.Paste();
}
if (groupClipboard.containsData)
{
groupClipboardRestore = groupClipboard.Paste();
}
UndoUtility.RecordEditedObject("Duplicate Graph Element Selection");
CopySelection();
PasteOutside(false);
if (singleClipboardRestore != null)
{
singleClipboard.Copy(singleClipboardRestore);
}
else
{
singleClipboard.Clear();
}
if (groupClipboardRestore != null)
{
groupClipboard.Copy(groupClipboardRestore);
}
else
{
groupClipboard.Clear();
}
}
}
}

View file

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

View file

@ -0,0 +1,114 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using UnityEditor;
using UnityObject = UnityEngine.Object;
namespace Unity.VisualScripting
{
public abstract class GraphContext<TGraph, TCanvas> : IGraphContext
where TGraph : class, IGraph
where TCanvas : class, ICanvas
{
protected GraphContext(GraphReference reference)
{
Ensure.That(nameof(reference)).IsNotNull(reference);
Ensure.That(nameof(reference.graph)).IsOfType<TGraph>(reference.graph);
this.reference = reference;
analyserProvider = new AnalyserProvider(reference);
graphMetadata = Metadata.Root().StaticObject(reference.graph);
extensions = this.Extensions().ToList().AsReadOnly();
sidebarPanels = SidebarPanels().ToList().AsReadOnly();
}
public GraphReference reference { get; }
public AnalyserProvider analyserProvider { get; }
public TCanvas canvas => (TCanvas)graph.Canvas();
ICanvas IGraphContext.canvas => canvas;
public GraphSelection selection => canvas.selection;
public TGraph graph => (TGraph)reference.graph;
IGraph IGraphContext.graph => graph;
public Metadata graphMetadata { get; }
public Metadata selectionMetadata => selection.Count == 1 ? ElementMetadata(selection.Single()) : null;
public Metadata ElementMetadata(IGraphElement element)
{
// Static object is faster than indexer
// return graphMetadata[nameof(IGraph.elements)].Indexer(element.guid).Cast(element.GetType());
return graphMetadata[nameof(IGraph.elements)].StaticObject(element);
}
public ReadOnlyCollection<IGraphContextExtension> extensions { get; }
IEnumerable<IGraphContextExtension> IGraphContext.extensions => extensions;
public virtual string windowTitle => "Graph";
protected virtual IEnumerable<ISidebarPanelContent> SidebarPanels() => Enumerable.Empty<ISidebarPanelContent>();
public ReadOnlyCollection<ISidebarPanelContent> sidebarPanels { get; }
IEnumerable<ISidebarPanelContent> IGraphContext.sidebarPanels => sidebarPanels;
public bool isPrefabInstance => reference.serializedObject?.IsConnectedPrefabInstance() ?? false;
#region Lifecycle
public virtual void Dispose()
{
// Manually free the providers so that the
// disposable decorators free their event handlers
analyserProvider?.FreeAll();
}
public void BeginEdit(bool disablePrefabInstance = true)
{
LudiqEditorUtility.editedObject.BeginOverride(reference.serializedObject);
LudiqGraphsEditorUtility.editedContext.BeginOverride(this);
EditorGUI.BeginDisabledGroup(disablePrefabInstance && isPrefabInstance);
EditorGUI.BeginChangeCheck();
}
public void EndEdit()
{
if (EditorGUI.EndChangeCheck())
{
DescribeAndAnalyze();
}
EditorGUI.EndDisabledGroup();
LudiqGraphsEditorUtility.editedContext.EndOverride();
LudiqEditorUtility.editedObject.EndOverride();
}
public void DescribeAndAnalyze()
{
foreach (var element in graph.elements)
{
if (element.HasDescriptor())
{
element.Describe();
}
}
graph.Describe();
analyserProvider.AnalyzeAll();
reference.parent.Describe();
}
#endregion
}
}

View file

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

View file

@ -0,0 +1,15 @@
using System;
namespace Unity.VisualScripting
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public sealed class GraphContextAttribute : Attribute, IDecoratorAttribute
{
public GraphContextAttribute(Type type)
{
this.type = type;
}
public Type type { get; private set; }
}
}

View file

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

View file

@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
public abstract class GraphContextExtension<TGraphContext> : IGraphContextExtension
where TGraphContext : IGraphContext
{
protected GraphContextExtension(TGraphContext context)
{
this.context = context;
}
public TGraphContext context { get; }
#region Context Shortcuts
protected GraphReference reference => context.reference;
protected IGraph graph => context.graph;
protected ICanvas canvas => context.canvas;
protected GraphSelection selection => context.selection;
#endregion
public virtual IEnumerable<GraphContextMenuItem> contextMenuItems => Enumerable.Empty<GraphContextMenuItem>();
public virtual DragAndDropVisualMode dragAndDropVisualMode => DragAndDropVisualMode.Generic;
public virtual bool AcceptsDragAndDrop() => false;
public virtual void PerformDragAndDrop() { }
public virtual void UpdateDragAndDrop() { }
public virtual void DrawDragAndDropPreview() { }
public virtual void ExitDragAndDrop() { }
protected static Event e => Event.current;
}
}

View file

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

View file

@ -0,0 +1,18 @@
using System;
namespace Unity.VisualScripting
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class GraphContextExtensionAttribute : Attribute, IDecoratorAttribute
{
public GraphContextExtensionAttribute(Type type)
{
Ensure.That(nameof(type)).IsNotNull(type);
Ensure.That(nameof(type)).IsOfType(type, typeof(IGraphContext));
this.type = type;
}
public Type type { get; }
}
}

View file

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

View file

@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public class GraphContextExtensionProvider : MultiDecoratorProvider<IGraphContext, IGraphContextExtension, GraphContextExtensionAttribute>
{
static GraphContextExtensionProvider()
{
instance = new GraphContextExtensionProvider();
}
public static GraphContextExtensionProvider instance { get; }
}
public static class XCanvasExtensionProvider
{
public static IEnumerable<IGraphContextExtension> Extensions(this IGraphContext context)
{
return GraphContextExtensionProvider.instance.GetDecorators(context);
}
}
}

View file

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

View file

@ -0,0 +1,17 @@
using System;
using UnityEngine;
namespace Unity.VisualScripting
{
public struct GraphContextMenuItem
{
public Action<Vector2> action { get; }
public string label { get; }
public GraphContextMenuItem(Action<Vector2> action, string label)
{
this.action = action;
this.label = label;
}
}
}

View file

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

View file

@ -0,0 +1,39 @@
using System;
namespace Unity.VisualScripting
{
public class GraphContextProvider : SingleDecoratorProvider<GraphReference, IGraphContext, GraphContextAttribute>
{
static GraphContextProvider()
{
instance = new GraphContextProvider();
}
public static GraphContextProvider instance { get; }
protected override bool cache => true;
protected override Type GetDecoratedType(GraphReference reference)
{
return reference.graph.GetType();
}
public override bool IsValid(GraphReference reference)
{
return reference.isValid;
}
}
public static class XGraphContextProvider
{
public static IGraphContext Context(this GraphReference reference)
{
return GraphContextProvider.instance.GetDecorator(reference);
}
public static T Context<T>(this GraphReference reference) where T : IGraphContext
{
return GraphContextProvider.instance.GetDecorator<T>(reference);
}
}
}

View file

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

View file

@ -0,0 +1,227 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public sealed class GraphSelection : ISet<IGraphElement>
{
public GraphSelection() : base()
{
set = new HashSet<IGraphElement>();
}
public event Action changed;
private readonly HashSet<IGraphElement> set;
public int Count => set.Count;
public bool IsReadOnly => false;
private void OnChange()
{
changed?.Invoke();
}
IEnumerator<IGraphElement> IEnumerable<IGraphElement>.GetEnumerator()
{
return GetEnumerator();
}
public HashSet<IGraphElement>.Enumerator GetEnumerator()
{
return set.GetEnumerator();
}
public void Select(IGraphElement item)
{
Clear();
Add(item);
}
public void Select(IEnumerable<IGraphElement> items)
{
Clear();
UnionWith(items);
}
public bool Contains(IGraphElement item)
{
Ensure.That(nameof(item)).IsNotNull(item);
return set.Contains(item);
}
public bool Add(IGraphElement item)
{
Ensure.That(nameof(item)).IsNotNull(item);
if (set.Add(item))
{
OnChange();
return true;
}
else
{
return false;
}
}
public bool Remove(IGraphElement item)
{
Ensure.That(nameof(item)).IsNotNull(item);
if (set.Remove(item))
{
OnChange();
return true;
}
else
{
return false;
}
}
public void Clear()
{
if (set.Count == 0)
{
return;
}
set.Clear();
OnChange();
}
#region Set Logic
public void ExceptWith(IEnumerable<IGraphElement> other)
{
var countBefore = set.Count;
set.ExceptWith(other);
if (countBefore != set.Count)
{
OnChange();
}
}
public void IntersectWith(IEnumerable<IGraphElement> other)
{
var countBefore = set.Count;
set.IntersectWith(other);
if (countBefore != set.Count)
{
OnChange();
}
}
public void SymmetricExceptWith(IEnumerable<IGraphElement> other)
{
var countBefore = set.Count;
set.SymmetricExceptWith(other);
if (countBefore != set.Count)
{
OnChange();
}
}
public void UnionWith(IEnumerable<IGraphElement> other)
{
var countBefore = set.Count;
set.UnionWith(other);
if (countBefore != set.Count)
{
OnChange();
}
}
public bool IsProperSubsetOf(IEnumerable<IGraphElement> other)
{
return set.IsProperSubsetOf(other);
}
public bool IsProperSupersetOf(IEnumerable<IGraphElement> other)
{
return set.IsProperSupersetOf(other);
}
public bool IsSubsetOf(IEnumerable<IGraphElement> other)
{
return set.IsSubsetOf(other);
}
public bool IsSupersetOf(IEnumerable<IGraphElement> other)
{
return set.IsSupersetOf(other);
}
public bool Overlaps(IEnumerable<IGraphElement> other)
{
return set.Overlaps(other);
}
public bool SetEquals(IEnumerable<IGraphElement> other)
{
return set.SetEquals(other);
}
public int RemoveWhere(Predicate<IGraphElement> match)
{
return set.RemoveWhere(match);
}
#endregion
#region ICollection
void ICollection<IGraphElement>.Add(IGraphElement item)
{
if (set.Add(item))
{
OnChange();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void CopyTo(IGraphElement[] array, int arrayIndex)
{
if (array == null)
{
throw new ArgumentNullException(nameof(array));
}
if (arrayIndex < 0)
{
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
}
if (array.Length - arrayIndex < Count)
{
throw new ArgumentException();
}
var i = 0;
foreach (var item in this)
{
array[i + arrayIndex] = item;
i++;
}
}
#endregion
}
}

View file

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

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public interface IGraphContext : IDisposable
{
GraphReference reference { get; }
IEnumerable<IGraphContextExtension> extensions { get; }
IGraph graph { get; }
ICanvas canvas { get; }
GraphSelection selection { get; }
Metadata graphMetadata { get; }
Metadata selectionMetadata { get; }
Metadata ElementMetadata(IGraphElement element);
AnalyserProvider analyserProvider { get; }
string windowTitle { get; }
IEnumerable<ISidebarPanelContent> sidebarPanels { get; }
bool isPrefabInstance { get; }
void BeginEdit(bool disablePrefabInstance = true);
void EndEdit();
void DescribeAndAnalyze();
}
}

View file

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

Some files were not shown because too many files have changed in this diff Show more