Added Unity project files
This commit is contained in:
8
Packages/com.vrchat.worlds/Editor.meta
Normal file
8
Packages/com.vrchat.worlds/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e9fbaa99aaf04a47a57992270bfe6eb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.vrchat.worlds/Editor/Udon.meta
Normal file
8
Packages/com.vrchat.worlds/Editor/Udon.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4043032f88a8ca14ab0daa7f59d4dc56
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.vrchat.worlds/Editor/Udon/Editor.meta
Normal file
8
Packages/com.vrchat.worlds/Editor/Udon/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 806c8d92e89f54e41871cdd22440042d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using VRC.Udon.Serialization.OdinSerializer;
|
||||
using VRC.Udon.Serialization.OdinSerializer.Utilities;
|
||||
using Object = System.Object;
|
||||
|
||||
namespace VRC.SDK3.Data.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(DataToken))]
|
||||
[CustomPropertyDrawer(typeof(DataList))]
|
||||
[CustomPropertyDrawer(typeof(DataDictionary))]
|
||||
public class DataPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return 30 * EditorGUIUtility.pixelsPerPoint;
|
||||
}
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.LabelField(position, $"{property.name} no defined editor for type of {property.type}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb263072af774326bec32396a5bef7ba
|
||||
timeCreated: 1675741121
|
||||
8
Packages/com.vrchat.worlds/Editor/Udon/External.meta
Normal file
8
Packages/com.vrchat.worlds/Editor/Udon/External.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 805b570a07431b24c9ced8636baf4e67
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.Compiler.dll
vendored
Normal file
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.Compiler.dll
vendored
Normal file
Binary file not shown.
102
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.Compiler.dll.meta
vendored
Normal file
102
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.Compiler.dll.meta
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b6535096cfa29340897276abbdd015f
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 0
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: LinuxUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.EditorBindings.dll
vendored
Normal file
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.EditorBindings.dll
vendored
Normal file
Binary file not shown.
46
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.EditorBindings.dll.meta
vendored
Normal file
46
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.EditorBindings.dll.meta
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 585dd63e377866248b16bdba915820ed
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 0
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.Graph.dll
vendored
Normal file
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.Graph.dll
vendored
Normal file
Binary file not shown.
46
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.Graph.dll.meta
vendored
Normal file
46
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.Graph.dll.meta
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b335798a4f28bec40ba9b3d4a15acee7
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 0
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.UAssembly.dll
vendored
Normal file
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.UAssembly.dll
vendored
Normal file
Binary file not shown.
46
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.UAssembly.dll.meta
vendored
Normal file
46
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.UAssembly.dll.meta
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21dcba1a47cc8c84381629950b692129
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 0
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.VRCGraphModules.dll
vendored
Normal file
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.VRCGraphModules.dll
vendored
Normal file
Binary file not shown.
33
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.VRCGraphModules.dll.meta
vendored
Normal file
33
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.VRCGraphModules.dll.meta
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 161140ecae894b84ba7bdd6e44ff4371
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.VRCTypeResolverModules.dll
vendored
Normal file
BIN
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.VRCTypeResolverModules.dll
vendored
Normal file
Binary file not shown.
33
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.VRCTypeResolverModules.dll.meta
vendored
Normal file
33
Packages/com.vrchat.worlds/Editor/Udon/External/VRC.Udon.VRCTypeResolverModules.dll.meta
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19cff77330d183441a69ff6c69e07629
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.vrchat.worlds/Editor/Udon/GraphModules.meta
Normal file
8
Packages/com.vrchat.worlds/Editor/Udon/GraphModules.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 678490760db5c0e48ae774b14b75699b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using VRC.Udon.Graph.Interfaces;
|
||||
using VRC.Udon.Graph.Attributes;
|
||||
using VRC.Udon.Graph.NodeRegistries;
|
||||
|
||||
[assembly: UdonGraphNodeRegistry(typeof(VRCInstantiateNodeRegistry), "VRCInstantiateNodeRegistry")]
|
||||
namespace VRC.Udon.Graph.NodeRegistries
|
||||
{
|
||||
public class VRCInstantiateNodeRegistry : BaseNodeRegistry
|
||||
{
|
||||
protected override Dictionary<string, INodeRegistry> NextRegistries => _nextRegistries;
|
||||
private static readonly Dictionary<string, INodeRegistry> _nextRegistries = new Dictionary<string, INodeRegistry>();
|
||||
|
||||
protected override Dictionary<string, UdonNodeDefinition> NodeDefinitions => _nodeDefinitions;
|
||||
|
||||
private static readonly Dictionary<string, UdonNodeDefinition> _nodeDefinitions = new Dictionary<string, UdonNodeDefinition>
|
||||
{
|
||||
{
|
||||
"VRCInstantiate.__Instantiate__UnityEngineGameObject__UnityEngineGameObject",
|
||||
new UdonNodeDefinition(
|
||||
"VRChat Instantiate",
|
||||
"VRCInstantiate.__Instantiate__UnityEngineGameObject__UnityEngineGameObject",
|
||||
typeof(UnityEngine.Object),
|
||||
new []
|
||||
{
|
||||
new UdonNodeParameter
|
||||
{
|
||||
name = "original",
|
||||
type = typeof(UnityEngine.GameObject),
|
||||
parameterType = UdonNodeParameter.ParameterType.IN
|
||||
},
|
||||
new UdonNodeParameter
|
||||
{
|
||||
name = "clone",
|
||||
type = typeof(UnityEngine.GameObject),
|
||||
parameterType = UdonNodeParameter.ParameterType.OUT
|
||||
}
|
||||
},
|
||||
new string[] { },
|
||||
new string[] { },
|
||||
new object[] { },
|
||||
true
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cac80b40f57c41d4b941dc5059271583
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 793c2f185ce686b4a952dc038f986c79
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e809894c9789ed4488974b1f99d92640
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public class UdonProgramSourceNewMenuAttribute : Attribute
|
||||
{
|
||||
public Type Type { get; }
|
||||
public string DisplayName { get; }
|
||||
|
||||
public UdonProgramSourceNewMenuAttribute(Type type, string displayName)
|
||||
{
|
||||
Type = type;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e5ced9511d591140b191bbd9e948e61
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEditor;
|
||||
using VRC.Udon.Common.Interfaces;
|
||||
using VRC.Udon.ProgramSources;
|
||||
using VRC.Udon.Serialization.OdinSerializer;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources
|
||||
{
|
||||
[CustomEditor(typeof(SerializedUdonProgramAsset))]
|
||||
public class SerializedUdonProgramAssetEditor : UnityEditor.Editor
|
||||
{
|
||||
private SerializedProperty _serializedProgramBytesStringSerializedProperty;
|
||||
private SerializedProperty _serializationDataFormatSerializedProperty;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_serializedProgramBytesStringSerializedProperty = serializedObject.FindProperty("serializedProgramBytesString");
|
||||
_serializationDataFormatSerializedProperty = serializedObject.FindProperty("serializationDataFormat");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
DrawSerializationDebug();
|
||||
}
|
||||
|
||||
[Conditional("UDON_DEBUG")]
|
||||
private void DrawSerializationDebug()
|
||||
{
|
||||
EditorGUILayout.LabelField($"DataFormat: {(DataFormat)_serializationDataFormatSerializedProperty.enumValueIndex}");
|
||||
|
||||
if(string.IsNullOrEmpty(_serializedProgramBytesStringSerializedProperty.stringValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(_serializationDataFormatSerializedProperty.enumValueIndex == (int)DataFormat.JSON)
|
||||
{
|
||||
using(new EditorGUI.DisabledScope(true))
|
||||
{
|
||||
EditorGUILayout.TextArea(System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(_serializedProgramBytesStringSerializedProperty.stringValue)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using(new EditorGUI.DisabledScope(true))
|
||||
{
|
||||
SerializedUdonProgramAsset serializedUdonProgramAsset = (SerializedUdonProgramAsset)target;
|
||||
IUdonProgram udonProgram = serializedUdonProgramAsset.RetrieveProgram();
|
||||
byte[] serializedBytes = Serialization.OdinSerializer.SerializationUtility.SerializeValue(udonProgram, DataFormat.JSON, out List<UnityEngine.Object> _);
|
||||
EditorGUILayout.TextArea(System.Text.Encoding.UTF8.GetString(serializedBytes));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1b5b45f24b268b42826fc5c5497dc15
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89cae0352490adc49b4d12ff7701437a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using VRC.Udon.Editor.ProgramSources;
|
||||
using VRC.Udon.Editor.ProgramSources.Attributes;
|
||||
|
||||
[assembly: UdonProgramSourceNewMenu(typeof(UdonAssemblyProgramAsset), "Udon Assembly Program Asset")]
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources
|
||||
{
|
||||
[CreateAssetMenu(menuName = "VRChat/Udon/Udon Assembly Program Asset", fileName = "New Udon Assembly Program Asset")]
|
||||
public class UdonAssemblyProgramAsset : UdonProgramAsset
|
||||
{
|
||||
[SerializeField]
|
||||
protected string udonAssembly = "";
|
||||
|
||||
[SerializeField]
|
||||
protected string assemblyError = null;
|
||||
|
||||
public string AssemblyError => assemblyError;
|
||||
|
||||
public delegate void AssembleDelegate(bool success, string assembly);
|
||||
public event AssembleDelegate OnAssemble;
|
||||
|
||||
protected override void DrawProgramSourceGUI(UdonBehaviour udonBehaviour, ref bool dirty)
|
||||
{
|
||||
DrawAssemblyErrorTextArea();
|
||||
|
||||
DrawPublicVariables(udonBehaviour, ref dirty);
|
||||
|
||||
DrawAssemblyTextArea(!Application.isPlaying, ref dirty);
|
||||
DrawProgramDisassembly();
|
||||
}
|
||||
|
||||
protected override void RefreshProgramImpl()
|
||||
{
|
||||
AssembleProgram();
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
protected virtual void DrawAssemblyTextArea(bool allowEditing, ref bool dirty)
|
||||
{
|
||||
EditorGUILayout.LabelField("Assembly Code", EditorStyles.boldLabel);
|
||||
if(GUILayout.Button("Copy Assembly To Clipboard"))
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = udonAssembly;
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
using(new EditorGUI.DisabledScope(!allowEditing))
|
||||
{
|
||||
string newAssembly = EditorGUILayout.TextArea(udonAssembly);
|
||||
if(EditorGUI.EndChangeCheck())
|
||||
{
|
||||
dirty = true;
|
||||
Undo.RecordObject(this, "Edit Assembly Program Code");
|
||||
udonAssembly = newAssembly;
|
||||
UdonEditorManager.Instance.QueueAndRefreshProgram(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
protected void DrawAssemblyErrorTextArea()
|
||||
{
|
||||
if(string.IsNullOrEmpty(assemblyError))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField("Assembly Error", EditorStyles.boldLabel);
|
||||
using(new EditorGUI.DisabledScope(true))
|
||||
{
|
||||
EditorGUILayout.TextArea(assemblyError);
|
||||
}
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
protected void AssembleProgram()
|
||||
{
|
||||
try
|
||||
{
|
||||
program = UdonEditorManager.Instance.Assemble(udonAssembly);
|
||||
assemblyError = null;
|
||||
OnAssemble?.Invoke(true, udonAssembly);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
program = null;
|
||||
assemblyError = e.Message;
|
||||
Debug.LogException(e);
|
||||
OnAssemble?.Invoke(false, assemblyError);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22203902d63dec94194fefc3e155c43b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources
|
||||
{
|
||||
[CustomEditor(typeof(UdonAssemblyProgramAsset))]
|
||||
public class UdonAssemblyProgramAssetEditor : UdonProgramAssetEditor
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3df823f3ab561fc43bcb81286e14b91d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,27 @@
|
||||
using System.IO;
|
||||
using JetBrains.Annotations;
|
||||
using UnityEditor;
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources
|
||||
{
|
||||
[UnityEditor.AssetImporters.ScriptedImporter(1, "uasm")]
|
||||
[UsedImplicitly]
|
||||
public class UdonAssemblyProgramAssetImporter : UnityEditor.AssetImporters.ScriptedImporter
|
||||
{
|
||||
public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
|
||||
{
|
||||
UdonAssemblyProgramAsset udonAssemblyProgramAsset = ScriptableObject.CreateInstance<UdonAssemblyProgramAsset>();
|
||||
SerializedObject serializedUdonAssemblyProgramAsset = new SerializedObject(udonAssemblyProgramAsset);
|
||||
SerializedProperty udonAssemblyProperty = serializedUdonAssemblyProgramAsset.FindProperty("udonAssembly");
|
||||
udonAssemblyProperty.stringValue = File.ReadAllText(ctx.assetPath);
|
||||
serializedUdonAssemblyProgramAsset.ApplyModifiedProperties();
|
||||
|
||||
udonAssemblyProgramAsset.RefreshProgram();
|
||||
|
||||
ctx.AddObjectToAsset("Imported Udon Assembly Program", udonAssemblyProgramAsset);
|
||||
ctx.SetMainObject(udonAssemblyProgramAsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c0638314c289c24193b47d1c53c9fca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e9bedaf686c5e448b06e64cdfe95728
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f2c773c057bbd749ad8fd66c018541a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0261d54fb1cc86b46a074b8d6e477cf0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bea6600b38aa0249b02e3d3ee8a7d44
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class ByteField : BaseField<byte>
|
||||
{
|
||||
public ByteField():base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Char Editor and listen for changes
|
||||
IntegerField field = new IntegerField();
|
||||
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = Convert.ToByte(e.newValue));
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c66f97d5a5a38cb478fd4df11ece7be7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,24 @@
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class CharField : BaseField<char>
|
||||
{
|
||||
public CharField():base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Char Editor and listen for changes
|
||||
TextField field = new TextField
|
||||
{
|
||||
maxLength = 1
|
||||
};
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = e.newValue.ToCharArray()[0]);
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 602ffcf431b3e4f41a18bd868751439a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class DecimalField : BaseField<decimal>
|
||||
{
|
||||
public DecimalField():base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Char Editor and listen for changes
|
||||
DoubleField field = new DoubleField();
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = Convert.ToDecimal(e.newValue));
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e79144dad56140a7bcd0d9f945153784
|
||||
timeCreated: 1632419615
|
||||
@ -0,0 +1,24 @@
|
||||
using UnityEngine.UIElements;
|
||||
using UIElements = UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class LayerMaskField : BaseField<LayerMask>
|
||||
{
|
||||
public LayerMaskField() : base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create LayerMask Editor and listen for changes
|
||||
UIElements.LayerMaskField field = new UIElements.LayerMaskField();
|
||||
field.RegisterValueChangedCallback(e =>
|
||||
{
|
||||
this.value = e.newValue;
|
||||
});
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42d9183d7c7ce67448d1e010456e36f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,25 @@
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using VRC.SDK3.Components;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class MirrorReflectionClearFlagsField : BaseField<MirrorClearFlags>
|
||||
{
|
||||
public MirrorReflectionClearFlagsField() : base(null, null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create LayerMask Editor and listen for changes
|
||||
EnumField field = new EnumField();
|
||||
field.Init(MirrorClearFlags.FromReferenceCamera);
|
||||
field.RegisterValueChangedCallback(e =>
|
||||
{
|
||||
this.value = (MirrorClearFlags)e.newValue;
|
||||
});
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a6b99e05a39452082bd89b0feec45ca
|
||||
timeCreated: 1660169942
|
||||
@ -0,0 +1,24 @@
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class QuaternionField : BaseField<Quaternion>
|
||||
{
|
||||
public QuaternionField() :base(null, null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Vector4 Editor and listen for changes
|
||||
Vector4Field field = new Vector4Field();
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = new Quaternion(e.newValue.x, e.newValue.y, e.newValue.z, e.newValue.w)
|
||||
);
|
||||
Add(field);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c96407d2b7698c4c8a0476efa2c765d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class SByteField : BaseField<sbyte>
|
||||
{
|
||||
public SByteField():base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Char Editor and listen for changes
|
||||
IntegerField field = new IntegerField();
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = Convert.ToSByte(e.newValue));
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42747856e1884be6b1112c8838963662
|
||||
timeCreated: 1632419007
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class ShortField : BaseField<short>
|
||||
{
|
||||
public ShortField():base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Char Editor and listen for changes
|
||||
IntegerField field = new IntegerField();
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = Convert.ToInt16(e.newValue));
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcda1561abdb40c69f9eeb9211bd3e3d
|
||||
timeCreated: 1632419462
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class UnsignedIntegerField : BaseField<uint>
|
||||
{
|
||||
public UnsignedIntegerField():base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Char Editor and listen for changes
|
||||
IntegerField field = new IntegerField();
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = Convert.ToUInt32(e.newValue));
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b91b14ff1e24276863f173d0e9c760c
|
||||
timeCreated: 1632419145
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class UnsignedLongField : BaseField<ulong>
|
||||
{
|
||||
public UnsignedLongField():base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Char Editor and listen for changes
|
||||
IntegerField field = new IntegerField();
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = Convert.ToUInt64(e.newValue));
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d1c8af690a94ef0a670e5d321733414
|
||||
timeCreated: 1632419341
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class UnsignedShortField : BaseField<ushort>
|
||||
{
|
||||
public UnsignedShortField():base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Char Editor and listen for changes
|
||||
IntegerField field = new IntegerField();
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = Convert.ToUInt16(e.newValue));
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1387a4616a8f4c87bd0d55d2ffc021c8
|
||||
timeCreated: 1632419528
|
||||
@ -0,0 +1,23 @@
|
||||
using UnityEngine.UIElements;
|
||||
using System;
|
||||
using VRC.SDKBase;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class VRCUrlField : BaseField<VRCUrl>
|
||||
{
|
||||
public VRCUrlField():base(null,null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create Text Editor and listen for changes
|
||||
TextField field = new TextField(50, false, false, Char.MinValue);
|
||||
field.RegisterValueChangedCallback(
|
||||
e =>
|
||||
value = new VRCUrl(e.newValue)
|
||||
);
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eeb751ae1c234a04291c5039626f3470
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,25 @@
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using VRC.SDK3.Components.Video;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public class VideoErrorField : BaseField<VideoError>
|
||||
{
|
||||
public VideoErrorField() : base(null, null)
|
||||
{
|
||||
// Set up styling
|
||||
AddToClassList("UdonValueField");
|
||||
|
||||
// Create LayerMask Editor and listen for changes
|
||||
EnumField field = new EnumField();
|
||||
field.Init(VideoError.Unknown);
|
||||
field.RegisterValueChangedCallback(e =>
|
||||
{
|
||||
this.value = (VideoError)e.newValue;
|
||||
});
|
||||
|
||||
Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22a713ed81ae4c7e9ad58760232ce573
|
||||
timeCreated: 1660170466
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b029e079cc40515438800823a9649f5b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,81 @@
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
using UnityEngine.UIElements;
|
||||
#else
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
#endif
|
||||
using System;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView;
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
namespace UnityEditor.Experimental.GraphView
|
||||
#else
|
||||
namespace UnityEditor.Experimental.UIElements.GraphView
|
||||
#endif
|
||||
{
|
||||
public static class GraphElementExtension
|
||||
{
|
||||
|
||||
public static void Reload(this GraphElement element)
|
||||
{
|
||||
var evt = new Event()
|
||||
{
|
||||
type = EventType.ExecuteCommand,
|
||||
commandName = UdonGraphCommands.Reload
|
||||
};
|
||||
using (var e = ExecuteCommandEvent.GetPooled(evt))
|
||||
{
|
||||
element.SendEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Compile(this GraphElement element)
|
||||
{
|
||||
var evt = new Event()
|
||||
{
|
||||
type = EventType.ExecuteCommand,
|
||||
commandName = UdonGraphCommands.Compile
|
||||
};
|
||||
using (var e = ExecuteCommandEvent.GetPooled(evt))
|
||||
{
|
||||
element.SendEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetUid(this GraphElement element)
|
||||
{
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
return element.viewDataKey;
|
||||
#else
|
||||
return element.persistenceKey;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void MarkDirty()
|
||||
{
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector2 GetSnappedPosition(Vector2 position)
|
||||
{
|
||||
// don't snap at 0 size
|
||||
var snap = Settings.GridSnapSize;
|
||||
if (snap == 0) return position;
|
||||
|
||||
position.x = (float)Math.Round(position.x / snap) * snap;
|
||||
position.y = (float)Math.Round(position.y / snap) * snap;
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
public static Rect GetSnappedRect(Rect rect)
|
||||
{
|
||||
rect.position = GetSnappedPosition(rect.position);
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 469db50616185d04e8a46dcd75db12d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,86 @@
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
using UnityEngine.UIElements;
|
||||
#else
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
#endif
|
||||
using System;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
public class UdonArrayEditor : VisualElement
|
||||
{
|
||||
private IArrayProvider _inspector;
|
||||
private Button _editArrayButton;
|
||||
private Action<object> _setValueCallback;
|
||||
private Type _type;
|
||||
private object _value;
|
||||
private bool _inspectorOpen = false;
|
||||
|
||||
public UdonArrayEditor(Type t, Action<object> valueChangedAction, object value)
|
||||
{
|
||||
_setValueCallback = valueChangedAction;
|
||||
_value = value;
|
||||
_type = t.GetElementType();
|
||||
|
||||
_editArrayButton = new Button(EditArray)
|
||||
{
|
||||
text = "Edit",
|
||||
name = "array-editor",
|
||||
};
|
||||
|
||||
Add(_editArrayButton);
|
||||
}
|
||||
|
||||
private void EditArray()
|
||||
{
|
||||
if (_inspector == null)
|
||||
{
|
||||
// Create it new
|
||||
Type typedArrayInspector = (typeof(UdonArrayInspector<>)).MakeGenericType(_type);
|
||||
_inspector = (Activator.CreateInstance(typedArrayInspector, null, _value) as IArrayProvider);
|
||||
|
||||
AddInspector();
|
||||
_inspectorOpen = true;
|
||||
_editArrayButton.text = "Save";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update Values when 'Save' is clicked
|
||||
if(_inspectorOpen)
|
||||
{
|
||||
// Update Values
|
||||
var values = _inspector.GetValues();
|
||||
_setValueCallback(values);
|
||||
|
||||
// Remove Inspector
|
||||
_inspector.RemoveFromHierarchy();
|
||||
|
||||
// Update Button Text
|
||||
_editArrayButton.text = "Edit";
|
||||
_inspectorOpen = false;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inspector exists, it's just removed
|
||||
_inspectorOpen = true;
|
||||
AddInspector();
|
||||
_editArrayButton.text = "Save";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddInspector()
|
||||
{
|
||||
if (parent.GetType() == typeof(UdonPort))
|
||||
{
|
||||
parent.parent.Add(_inspector as VisualElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
Add(_inspector as VisualElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f257a6eeae213a4db991d486cace003
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,156 @@
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
#else
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
using UnityEditor.Experimental.UIElements;
|
||||
#endif
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
public class UdonArrayInspector<T> : VisualElement, IArrayProvider
|
||||
{
|
||||
private ScrollView _scroller;
|
||||
private List<VisualElement> _fields = new List<VisualElement>();
|
||||
private IntegerField _sizeField;
|
||||
private Action<object> _setValueCallback;
|
||||
|
||||
public UdonArrayInspector(Action<object> valueChangedAction, object value)
|
||||
{
|
||||
_setValueCallback = valueChangedAction;
|
||||
|
||||
AddToClassList("input-inspector");
|
||||
var resizeContainer = new VisualElement()
|
||||
{
|
||||
name = "resize-container",
|
||||
};
|
||||
resizeContainer.Add(new Label("size"));
|
||||
|
||||
_sizeField = new IntegerField();
|
||||
_sizeField.isDelayed = true;
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
_sizeField.RegisterValueChangedCallback((evt) =>
|
||||
#else
|
||||
_sizeField.OnValueChanged((evt) =>
|
||||
#endif
|
||||
{
|
||||
ResizeTo(evt.newValue);
|
||||
});
|
||||
resizeContainer.Add(_sizeField);
|
||||
Add(resizeContainer);
|
||||
|
||||
_scroller = new ScrollView()
|
||||
{
|
||||
name = "array-scroll",
|
||||
};
|
||||
Add(_scroller);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
// Can't show if array is empty
|
||||
_sizeField.value = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
IEnumerable<T> values = (value as IEnumerable<T>);
|
||||
if (values == null)
|
||||
{
|
||||
Debug.LogError($"Couldn't convert {value} to {typeof(T).ToString()} Array");
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate fields and their values from passed-in array
|
||||
_fields = new List<VisualElement>();
|
||||
foreach (var item in values)
|
||||
{
|
||||
var field = GetValueField(item);
|
||||
_fields.Add(field);
|
||||
|
||||
_scroller.contentContainer.Add(field);
|
||||
}
|
||||
|
||||
_sizeField.value = values.Count();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ResizeTo(int newValue)
|
||||
{
|
||||
_sizeField.value = newValue;
|
||||
|
||||
// Create from scratch if currentFields are null
|
||||
if(_fields == null)
|
||||
{
|
||||
Debug.Log($"Creating from Scratch");
|
||||
_fields = new List<VisualElement>();
|
||||
for (int i = 0; i < newValue; i++)
|
||||
{
|
||||
var field = GetValueField(null);
|
||||
_fields.Add(field);
|
||||
_scroller.contentContainer.Add(field as VisualElement);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Shrink list if new value is less than old one
|
||||
if(newValue < _fields.Count)
|
||||
{
|
||||
for (int i = _fields.Count - 1; i >= newValue; i--)
|
||||
{
|
||||
(_fields[i] as VisualElement).RemoveFromHierarchy();
|
||||
_fields.RemoveAt(i);
|
||||
}
|
||||
MarkDirtyRepaint();
|
||||
return;
|
||||
}
|
||||
|
||||
// Expand list if new value is more than old one.
|
||||
if(newValue > _fields.Count)
|
||||
{
|
||||
int numberToAdd = newValue - _fields.Count;
|
||||
for (int i = 0; i < numberToAdd; i++)
|
||||
{
|
||||
var field = GetValueField(null);
|
||||
if (field == null)
|
||||
{
|
||||
Debug.LogWarning($"Sorry, can't edit object of type {typeof(T).ToString()} yet.");
|
||||
return;
|
||||
}
|
||||
_fields.Add(field);
|
||||
|
||||
_scroller.contentContainer.Add(field as VisualElement);
|
||||
}
|
||||
MarkDirtyRepaint();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private VisualElement GetValueField(object value)
|
||||
{
|
||||
return UdonFieldFactory.CreateField(typeof(T), value, _setValueCallback);
|
||||
}
|
||||
|
||||
public object GetValues()
|
||||
{
|
||||
var result = new List<T>();
|
||||
for (int i = 0; i < _fields.Count; i++)
|
||||
{
|
||||
var f = (_fields[i] as INotifyValueChanged<T>);
|
||||
result.Add(f.value);
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface IArrayProvider
|
||||
{
|
||||
object GetValues();
|
||||
void RemoveFromHierarchy(); // in VisualElement
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4f0ade55ae13b6468a765826f1f2540
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,212 @@
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine.UIElements;
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
public sealed class UdonComment : UdonGraphElement, IUdonGraphElementDataProvider
|
||||
{
|
||||
private readonly VisualElement _mainContainer;
|
||||
private readonly Label _label;
|
||||
private readonly TextField _textField;
|
||||
private readonly CustomData _customData = new CustomData();
|
||||
private readonly UdonGraph _graph;
|
||||
public UdonGroup group;
|
||||
|
||||
// Called from Context menu and Reload
|
||||
public static UdonComment Create(string value, Rect position, UdonGraph graph)
|
||||
{
|
||||
var comment = new UdonComment("", graph);
|
||||
|
||||
// make sure rect size is not 0
|
||||
position.width = position.width > 0 ? position.width : 128;
|
||||
position.height = position.height > 0 ? position.height : 40;
|
||||
|
||||
comment._customData.layout = position;
|
||||
comment._customData.title = value;
|
||||
|
||||
comment.UpdateFromData();
|
||||
UdonGraph.MarkSceneDirty();
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
public static UdonComment Create(UdonGraphElementData elementData, UdonGraph graph)
|
||||
{
|
||||
var comment = new UdonComment(elementData.jsonData, graph);
|
||||
|
||||
comment.UpdateFromData();
|
||||
UdonGraph.MarkSceneDirty();
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
private UdonComment(string jsonData, UdonGraph graph)
|
||||
{
|
||||
name = "comment";
|
||||
_graph = graph;
|
||||
|
||||
capabilities |= Capabilities.Selectable | Capabilities.Movable | Capabilities.Deletable |
|
||||
Capabilities.Resizable;
|
||||
pickingMode = PickingMode.Ignore;
|
||||
|
||||
type = UdonGraphElementType.UdonComment;
|
||||
|
||||
if(!string.IsNullOrEmpty(jsonData))
|
||||
{
|
||||
EditorJsonUtility.FromJsonOverwrite(jsonData, _customData);
|
||||
}
|
||||
|
||||
_mainContainer = new VisualElement();
|
||||
_mainContainer.StretchToParentSize();
|
||||
_mainContainer.AddToClassList("mainContainer");
|
||||
Add(_mainContainer);
|
||||
|
||||
_label = new Label();
|
||||
_label.RegisterCallback<MouseDownEvent>(OnLabelClick);
|
||||
_mainContainer.Add(_label);
|
||||
|
||||
_textField = new TextField(1000, true, false, '*')
|
||||
{
|
||||
isDelayed = true
|
||||
};
|
||||
|
||||
// Support IME
|
||||
_textField.RegisterCallback<FocusInEvent>(evt =>{ Input.imeCompositionMode = IMECompositionMode.On;});
|
||||
_textField.RegisterCallback<FocusOutEvent>(evt =>
|
||||
{
|
||||
SetText(_textField.text);
|
||||
Input.imeCompositionMode = IMECompositionMode.Auto;
|
||||
SwitchToEditMode(false);
|
||||
});
|
||||
|
||||
_textField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
SetText(evt.newValue);
|
||||
SwitchToEditMode(false);
|
||||
});
|
||||
}
|
||||
|
||||
private void SaveNewData()
|
||||
{
|
||||
_graph.SaveGraphElementData(this);
|
||||
}
|
||||
|
||||
private void UpdateFromData()
|
||||
{
|
||||
if(_customData != null)
|
||||
{
|
||||
layer = _customData.layer;
|
||||
if(string.IsNullOrEmpty(_customData.uid))
|
||||
{
|
||||
_customData.uid = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
uid = _customData.uid;
|
||||
|
||||
SetPosition(_customData.layout);
|
||||
SetText(_customData.title);
|
||||
}
|
||||
}
|
||||
protected override void OnCustomStyleResolved(ICustomStyle istyle)
|
||||
{
|
||||
base.OnCustomStyleResolved(istyle);
|
||||
// Something is forcing style! Resetting a few things here.
|
||||
|
||||
style.borderBottomWidth = 1;
|
||||
|
||||
var resizer = this.Q(null, "resizer");
|
||||
if (resizer == null) return;
|
||||
resizer.style.paddingTop = 0;
|
||||
resizer.style.paddingLeft = 0;
|
||||
}
|
||||
|
||||
public override void SetPosition(Rect newPos)
|
||||
{
|
||||
newPos = GraphElementExtension.GetSnappedRect(newPos);
|
||||
base.SetPosition(newPos);
|
||||
}
|
||||
|
||||
public override void UpdatePresenterPosition()
|
||||
{
|
||||
base.UpdatePresenterPosition();
|
||||
_customData.layout = GraphElementExtension.GetSnappedRect(GetPosition());
|
||||
SaveNewData();
|
||||
group?.SaveNewData();
|
||||
}
|
||||
|
||||
private double lastClickTime;
|
||||
private const double DOUBLE_CLICK_SPEED = 0.5;
|
||||
|
||||
private void OnLabelClick(MouseDownEvent evt)
|
||||
{
|
||||
var newTime = EditorApplication.timeSinceStartup;
|
||||
if(newTime - lastClickTime < DOUBLE_CLICK_SPEED)
|
||||
{
|
||||
SwitchToEditMode(true);
|
||||
}
|
||||
|
||||
lastClickTime = newTime;
|
||||
}
|
||||
|
||||
private void SwitchToEditMode(bool switchingToEdit)
|
||||
{
|
||||
if (switchingToEdit)
|
||||
{
|
||||
_mainContainer.Remove(_label);
|
||||
_textField.value = _label.text;
|
||||
_mainContainer.Add(_textField);
|
||||
_textField.delegatesFocus = true;
|
||||
_textField.Focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
_mainContainer.Remove(_textField);
|
||||
_mainContainer.Add(_label);
|
||||
}
|
||||
|
||||
MarkDirtyRepaint();
|
||||
}
|
||||
|
||||
private void SetText(string value)
|
||||
{
|
||||
Undo.RecordObject(_graph.graphProgramAsset, "Rename Comment");
|
||||
value = value.TrimEnd();
|
||||
_customData.title = value;
|
||||
_label.text = value;
|
||||
SaveNewData();
|
||||
MarkDirtyRepaint();
|
||||
}
|
||||
|
||||
public UdonGraphElementData GetData()
|
||||
{
|
||||
return new UdonGraphElementData(UdonGraphElementType.UdonComment, uid,
|
||||
EditorJsonUtility.ToJson(_customData));
|
||||
}
|
||||
|
||||
// CustomData is serialized in user assets, so we can't rename/modify/remove any of these variables
|
||||
// ReSharper disable InconsistentNaming
|
||||
// ReSharper disable NotAccessedField.Local
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Local
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable UnassignedField.Global
|
||||
#pragma warning disable CS0649
|
||||
private class CustomData
|
||||
{
|
||||
public string uid;
|
||||
public Rect layout;
|
||||
public string title = "Comment";
|
||||
public int layer;
|
||||
public Color elementTypeColor;
|
||||
|
||||
}
|
||||
#pragma warning restore CS0649
|
||||
// ReSharper enable UnassignedField.Global
|
||||
// ReSharper enable UnusedMember.Global
|
||||
// ReSharper enable InconsistentNaming
|
||||
// ReSharper enable NotAccessedField.Local
|
||||
// ReSharper enable FieldCanBeMadeReadOnly.Local
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e5916b8dd19e4445a9156a457b82ee4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,48 @@
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
#else
|
||||
using UnityEditor.Experimental.UIElements.GraphView;
|
||||
#endif
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
public class UdonGraphElement : GraphElement
|
||||
{
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
public string uid { get => viewDataKey; set => viewDataKey = value; }
|
||||
#else
|
||||
public string uid { get => persistenceKey; set => persistenceKey = value; }
|
||||
#endif
|
||||
internal UdonGraphElementType type = UdonGraphElementType.GraphElement;
|
||||
|
||||
internal UdonGraphElement()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public interface IUdonGraphElementDataProvider
|
||||
{
|
||||
UdonGraphElementData GetData();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class GraphRect
|
||||
{
|
||||
public float x;
|
||||
public float y;
|
||||
public float width;
|
||||
public float height;
|
||||
|
||||
public GraphRect(Rect input)
|
||||
{
|
||||
this.x = Mathf.Round(input.x);
|
||||
this.y = Mathf.Round(input.y);
|
||||
this.width = Mathf.Round(input.width);
|
||||
this.height = Mathf.Round(input.height);
|
||||
}
|
||||
|
||||
public Rect rect => new Rect(this.x, this.y, this.width, this.height);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba3ecc4c46929404d8c2ec920743b823
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,134 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using VRC.Udon.Graph;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
public class UdonGraphEvents : VisualElement
|
||||
{
|
||||
private readonly UdonGraph _graph;
|
||||
private UdonNodeData[] _events;
|
||||
private readonly VisualElement _list;
|
||||
private readonly Label _placeholder;
|
||||
|
||||
public UdonGraphEvents(UdonGraph graph, UdonSearchManager searchManager)
|
||||
{
|
||||
_graph = graph;
|
||||
name = "UdonGraphEvents";
|
||||
|
||||
AddToClassList("baseBlock");
|
||||
|
||||
var header = new VisualElement();
|
||||
header.AddToClassList("header");
|
||||
header.RegisterCallback((MouseUpEvent e) =>
|
||||
{
|
||||
ToggleInClassList("collapsed");
|
||||
});
|
||||
Add(header);
|
||||
|
||||
var leftSide = new VisualElement();
|
||||
header.Add(leftSide);
|
||||
|
||||
var collapseIcon = new VisualElement();
|
||||
collapseIcon.AddToClassList("collapseIcon");
|
||||
leftSide.Add(collapseIcon);
|
||||
|
||||
var headerText = new Label("Events");
|
||||
leftSide.Add(headerText);
|
||||
var eventAddBtn = new Button(() =>
|
||||
{
|
||||
var screenPosition = GUIUtility.GUIToScreenPoint(_graph.lastMousePosition);
|
||||
searchManager.OpenEventSearch(screenPosition);
|
||||
})
|
||||
{
|
||||
text = "+"
|
||||
};
|
||||
eventAddBtn.AddToClassList("addEventBtn");
|
||||
header.Add(eventAddBtn);
|
||||
_list = new VisualElement();
|
||||
_list.AddToClassList("list");
|
||||
Add(_list);
|
||||
|
||||
_placeholder = new Label("No Events Added");
|
||||
_placeholder.AddToClassList("placeholder");
|
||||
_list.Add(_placeholder);
|
||||
}
|
||||
|
||||
public UdonNodeData[] Events
|
||||
{
|
||||
set
|
||||
{
|
||||
_events = value;
|
||||
var oldEvents = this.Query<Button>(null, "udonEvent").ToList();
|
||||
foreach (var e in oldEvents)
|
||||
{
|
||||
_list.Remove(e);
|
||||
}
|
||||
|
||||
if (_events.Length == 0)
|
||||
{
|
||||
if (!_list.Contains(_placeholder))
|
||||
{
|
||||
_list.Add(_placeholder);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_list.Contains(_placeholder))
|
||||
{
|
||||
_placeholder.RemoveFromHierarchy();
|
||||
}
|
||||
}
|
||||
foreach (var e in _events)
|
||||
{
|
||||
var eventButton = new Button(() =>
|
||||
{
|
||||
_graph.ClearSelection();
|
||||
_graph.AddToSelection(_graph.GetNodeByGuid(e.uid));
|
||||
_graph.FrameSelection();
|
||||
})
|
||||
{
|
||||
name = $"jumpTo_{e.fullName}"
|
||||
};
|
||||
eventButton.AddToClassList("udonEvent");
|
||||
var eventName = e.fullName.Replace("Event_", "");
|
||||
if (eventName.StartsWithCached("Custom"))
|
||||
{
|
||||
var customName = e.nodeValues[0].Deserialize() as string;
|
||||
if (!string.IsNullOrEmpty(customName))
|
||||
{
|
||||
eventButton.text = e.nodeValues[0].Deserialize() as string;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventButton.text = "Custom Event";
|
||||
}
|
||||
|
||||
// append arity
|
||||
var parameters = e.nodeValues.Length - 2;
|
||||
if (parameters > 0)
|
||||
{
|
||||
eventButton.text += $" ({parameters})";
|
||||
}
|
||||
|
||||
eventButton.AddToClassList("customEvent");
|
||||
_list.Insert(0, eventButton);
|
||||
continue;
|
||||
}
|
||||
switch (eventName)
|
||||
{
|
||||
case "OnVariableChange":
|
||||
eventButton.text = $"{_graph.GetVariableName(e.nodeValues[0].Deserialize() as string)} Change";
|
||||
eventButton.AddToClassList("variableChange");
|
||||
_list.Add(eventButton);
|
||||
break;
|
||||
default:
|
||||
eventButton.text = eventName;
|
||||
_list.Add(eventButton);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75df7c5698fa41118a907e0f229bb537
|
||||
timeCreated: 1641352883
|
||||
@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
public class UdonGraphGroups : VisualElement
|
||||
{
|
||||
private readonly VisualElement _list;
|
||||
private readonly Label _placeholder;
|
||||
private UdonGroup[] _groups;
|
||||
|
||||
public UdonGraphGroups(UdonGraph graph)
|
||||
{
|
||||
UdonGraph graph1 = graph;
|
||||
name = "UdonGraphGroups";
|
||||
|
||||
AddToClassList("baseBlock");
|
||||
|
||||
var header = new VisualElement();
|
||||
header.AddToClassList("header");
|
||||
header.RegisterCallback((MouseUpEvent e) =>
|
||||
{
|
||||
ToggleInClassList("collapsed");
|
||||
});
|
||||
Add(header);
|
||||
|
||||
var leftSide = new VisualElement();
|
||||
header.Add(leftSide);
|
||||
|
||||
var collapseIcon = new VisualElement();
|
||||
collapseIcon.AddToClassList("collapseIcon");
|
||||
leftSide.Add(collapseIcon);
|
||||
|
||||
var headerText = new Label("Groups");
|
||||
leftSide.Add(headerText);
|
||||
var eventAddBtn = new Button(() =>
|
||||
{
|
||||
var groupRect = graph1.GetRectFromMouse();
|
||||
groupRect.x += 200;
|
||||
UdonGroup group = UdonGroup.Create("Group", groupRect, graph1);
|
||||
Undo.RecordObject(graph1.graphProgramAsset, "Add Group");
|
||||
graph1.AddElement(group);
|
||||
group.UpdateDataId();
|
||||
|
||||
foreach (ISelectable item in graph1.selection)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case UdonNode node:
|
||||
group.AddElement(node);
|
||||
break;
|
||||
case UdonComment comment:
|
||||
group.AddElement(comment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
group.Initialize();
|
||||
graph1.SaveGraphElementData(group);
|
||||
AddGroup(group);
|
||||
})
|
||||
{
|
||||
text = "+"
|
||||
};
|
||||
eventAddBtn.AddToClassList("addEventBtn");
|
||||
header.Add(eventAddBtn);
|
||||
_list = new VisualElement();
|
||||
_list.AddToClassList("list");
|
||||
Add(_list);
|
||||
|
||||
_placeholder = new Label("No Groups Added");
|
||||
_placeholder.AddToClassList("placeholder");
|
||||
_list.Add(_placeholder);
|
||||
}
|
||||
|
||||
public void AddGroup(UdonGroup group)
|
||||
{
|
||||
if (Groups != null)
|
||||
{
|
||||
var newGroups = Groups.ToList();
|
||||
newGroups.Add(group);
|
||||
Groups = newGroups.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
Groups = new[] { group };
|
||||
}
|
||||
}
|
||||
|
||||
public new void Clear()
|
||||
{
|
||||
Groups = Array.Empty<UdonGroup>();
|
||||
}
|
||||
|
||||
private UdonGroup[] Groups
|
||||
{
|
||||
get => _groups;
|
||||
set
|
||||
{
|
||||
_groups = value;
|
||||
UpdateGroups(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGroups(UdonGroup[] value)
|
||||
{
|
||||
var oldGroups = this.Query(null, "udonGroup").ToList();
|
||||
foreach (var group in oldGroups)
|
||||
{
|
||||
_list.Remove(group);
|
||||
}
|
||||
|
||||
if (value.Length == 0)
|
||||
{
|
||||
if (!_list.Contains(_placeholder))
|
||||
{
|
||||
_list.Add(_placeholder);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_list.Contains(_placeholder))
|
||||
{
|
||||
_placeholder.RemoveFromHierarchy();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var group in value)
|
||||
{
|
||||
group.UpdateGraphGroups = UpdateGroupsDelegate;
|
||||
var groupBtn = new Button(() => { group.SelectGroup(); })
|
||||
{
|
||||
name = $"jumpTo_{group.name}",
|
||||
text = group.title
|
||||
};
|
||||
groupBtn.AddToClassList("udonGroup");
|
||||
_list.Add(groupBtn);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGroupsDelegate()
|
||||
{
|
||||
UpdateGroups(_groups);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2adbf86181214870b117bdc6c99946d8
|
||||
timeCreated: 1641420287
|
||||
@ -0,0 +1,116 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
public class UdonGraphToolbar: VisualElement
|
||||
{
|
||||
private readonly IntegerField _updateOrderIntField;
|
||||
private readonly Button _graphHighlightFlow;
|
||||
private readonly UdonGraphStatus _graphStatus;
|
||||
private float _sidebarOffset = 238f;
|
||||
private VisualElement _sidebarSpacer;
|
||||
|
||||
private readonly StyleSheet styles = (StyleSheet)Resources.Load("UdonToolbarStyle");
|
||||
|
||||
public UdonGraphToolbar(UdonGraph graphView)
|
||||
{
|
||||
name = "UdonGraphToolbar";
|
||||
|
||||
graphView.OnSidebarResize += OnSidebarResize;
|
||||
|
||||
if (!graphView.styleSheets.Contains(styles))
|
||||
{
|
||||
graphView.styleSheets.Add(styles);
|
||||
}
|
||||
|
||||
bool hasValue = graphView.graphProgramAsset != null && graphView.graphProgramAsset.graphData != null;
|
||||
_updateOrderIntField = new IntegerField
|
||||
{
|
||||
name = "UpdateOrderIntegerField",
|
||||
label = "Update Order",
|
||||
value = hasValue ? graphView.graphProgramAsset.graphData.updateOrder : 0
|
||||
};
|
||||
_updateOrderIntField.AddToClassList("updateOrderField");
|
||||
|
||||
_updateOrderIntField.RegisterValueChangedCallback(e =>
|
||||
{
|
||||
Undo.RecordObject(graphView.graphProgramAsset, "Changed UpdateOrder");
|
||||
graphView.graphProgramAsset.graphData.updateOrder = e.newValue;
|
||||
graphView.SaveGraphToDisk();
|
||||
AssetDatabase.SaveAssets();
|
||||
});
|
||||
_updateOrderIntField.isDelayed = true;
|
||||
var leftSide = new VisualElement();
|
||||
|
||||
_sidebarSpacer = new VisualElement();
|
||||
_sidebarSpacer.AddToClassList("toolbarSpacer");
|
||||
Add(_sidebarSpacer);
|
||||
|
||||
Add(leftSide);
|
||||
leftSide.Add(_updateOrderIntField);
|
||||
|
||||
var rightSide = new VisualElement();
|
||||
rightSide.AddToClassList("toolbarRightSide");
|
||||
|
||||
_graphHighlightFlow = new Button(() =>
|
||||
{
|
||||
Settings.HighlightFlow = !Settings.HighlightFlow;
|
||||
_graphHighlightFlow?.EnableInClassList("selected", Settings.HighlightFlow);
|
||||
graphView.OnHighlightFlowChanged();
|
||||
})
|
||||
{
|
||||
text = "Highlight Flow",
|
||||
tooltip = "Highlights the flow-connected nodes on click"
|
||||
};
|
||||
rightSide.Add(_graphHighlightFlow);
|
||||
|
||||
Button graphCompile = new Button(() =>
|
||||
{
|
||||
if (graphView.graphProgramAsset != null &&
|
||||
graphView.graphProgramAsset is AbstractUdonProgramSource udonProgramSource)
|
||||
{
|
||||
UdonEditorManager.Instance.QueueAndRefreshProgram(udonProgramSource);
|
||||
}
|
||||
})
|
||||
{ text = "Compile" };
|
||||
rightSide.Add(graphCompile);
|
||||
|
||||
Button graphReload = new Button(graphView.Reload)
|
||||
{ text = "Reload" };
|
||||
rightSide.Add(graphReload);
|
||||
|
||||
_graphStatus = new UdonGraphStatus(graphView);
|
||||
rightSide.Add(_graphStatus);
|
||||
Add(rightSide);
|
||||
|
||||
UpdateStatusAsset(graphView.graphProgramAsset);
|
||||
|
||||
// block dragging/moving
|
||||
RegisterCallback((EventCallback<DragUpdatedEvent>) (e => e.StopPropagation()));
|
||||
RegisterCallback((EventCallback<WheelEvent>) (e => e.StopPropagation()));
|
||||
RegisterCallback((EventCallback<MouseDownEvent>) (e => e.StopPropagation()));
|
||||
}
|
||||
|
||||
private void UpdateStatusAsset(UdonGraphProgramAsset graph)
|
||||
{
|
||||
if (graph == null) return;
|
||||
_graphStatus.LoadAsset(graph);
|
||||
}
|
||||
|
||||
public void RefreshAsset(UdonGraphProgramAsset asset)
|
||||
{
|
||||
if (asset == null) return;
|
||||
_updateOrderIntField.value = asset.graphData.updateOrder;
|
||||
UpdateStatusAsset(asset);
|
||||
}
|
||||
|
||||
private void OnSidebarResize(object sender, MouseMoveEvent evt)
|
||||
{
|
||||
_sidebarOffset = evt.mousePosition.x + 8f;
|
||||
_sidebarSpacer.style.width = new StyleLength(_sidebarOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1889c18ccf7e41c7af45075ff3ad65b6
|
||||
timeCreated: 1641509003
|
||||
@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using VRC.Udon.Graph;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
public class UdonGraphVariables : VisualElement, IUdonGraphElementDataProvider
|
||||
{
|
||||
private readonly CustomData _customData = new CustomData();
|
||||
private readonly UdonGraph _graph;
|
||||
private readonly VisualElement _list;
|
||||
private readonly Label _placeholder;
|
||||
private Button _addButton;
|
||||
private readonly string _guid;
|
||||
private Dictionary<string, UdonVariableRow> _idToRow;
|
||||
private Action<VisualElement, string> EditTextRequested { get; set; }
|
||||
|
||||
public UdonGraphVariables(UdonGraph graph, UdonSearchManager searchManager, Action<VisualElement, string> editTextRequested)
|
||||
{
|
||||
EditTextRequested = editTextRequested;
|
||||
_guid = GUID.Generate().ToString();
|
||||
_graph = graph;
|
||||
|
||||
AddToClassList("baseBlock");
|
||||
|
||||
var header = new VisualElement();
|
||||
header.AddToClassList("header");
|
||||
Add(header);
|
||||
|
||||
header.RegisterCallback((MouseUpEvent e) =>
|
||||
{
|
||||
ToggleInClassList("collapsed");
|
||||
});
|
||||
|
||||
var leftSide = new VisualElement();
|
||||
header.Add(leftSide);
|
||||
|
||||
var collapseIcon = new VisualElement();
|
||||
collapseIcon.AddToClassList("collapseIcon");
|
||||
leftSide.Add(collapseIcon);
|
||||
|
||||
var headerText = new Label("Variables");
|
||||
leftSide.Add(headerText);
|
||||
var eventAddBtn = new Button(() =>
|
||||
{
|
||||
var screenPosition = GUIUtility.GUIToScreenPoint(_graph.lastMousePosition);
|
||||
searchManager.OpenVariableSearch(screenPosition);
|
||||
})
|
||||
{
|
||||
text = "+"
|
||||
};
|
||||
eventAddBtn.AddToClassList("addEventBtn");
|
||||
header.Add(eventAddBtn);
|
||||
_list = new VisualElement();
|
||||
_list.AddToClassList("list");
|
||||
Add(_list);
|
||||
_placeholder = new Label("No Variables Added");
|
||||
_placeholder.AddToClassList("placeholder");
|
||||
_list.Add(_placeholder);
|
||||
_idToRow = new Dictionary<string, UdonVariableRow>();
|
||||
|
||||
_list.RegisterCallback<KeyDownEvent>(_graph.OnKeyDown);
|
||||
}
|
||||
|
||||
public void AddFromData(UdonNodeData nodeData)
|
||||
{
|
||||
// don't add internal variables, which start with __
|
||||
// Todo: handle all "__" variables instead, need to tell community first and let the word spread
|
||||
string newVariableName = (string)nodeData.nodeValues[(int)UdonParameterProperty.ValueIndices.Name].Deserialize();
|
||||
if (newVariableName.StartsWithCached("__returnValue"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UdonNodeDefinition definition = UdonEditorManager.Instance.GetNodeDefinition(nodeData.fullName);
|
||||
if (definition != null)
|
||||
{
|
||||
var row = new UdonVariableRow(new UdonParameterField(_graph, nodeData, EditTextRequested),
|
||||
new UdonParameterProperty(definition, nodeData));
|
||||
row.AddToClassList("udonVariable");
|
||||
_list.Add(row);
|
||||
_idToRow.Add(nodeData.uid, row);
|
||||
}
|
||||
|
||||
if (_list.Contains(_placeholder))
|
||||
{
|
||||
_placeholder.RemoveFromHierarchy();
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadData(UdonGraphElementData data)
|
||||
{
|
||||
JsonUtility.FromJsonOverwrite(data.jsonData, _customData);
|
||||
visible = _customData.visible;
|
||||
}
|
||||
|
||||
private void SaveData()
|
||||
{
|
||||
_graph.SaveGraphElementData(this);
|
||||
}
|
||||
|
||||
public UdonGraphElementData GetData()
|
||||
{
|
||||
return new UdonGraphElementData(UdonGraphElementType.VariablesWindow, _guid, JsonUtility.ToJson(_customData));
|
||||
}
|
||||
|
||||
public void RemoveByID(string id)
|
||||
{
|
||||
if (!_idToRow.TryGetValue(id, out UdonVariableRow row)) return;
|
||||
_list.Remove(row);
|
||||
_idToRow.Remove(id);
|
||||
}
|
||||
|
||||
public new void Clear()
|
||||
{
|
||||
_idToRow?.Clear();
|
||||
_list.Add(_placeholder);
|
||||
var oldVars = this.Query<UdonVariableRow>(null, "udonVariable").ToList();
|
||||
foreach (var oldVar in oldVars)
|
||||
{
|
||||
_list.Remove(oldVar);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private class CustomData {
|
||||
public bool visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 346f4d7e451c44daaaacbf470d40c254
|
||||
timeCreated: 1641412295
|
||||
@ -0,0 +1,245 @@
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine.UIElements;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
public class UdonGroup : Group, IUdonGraphElementDataProvider
|
||||
{
|
||||
public Action UpdateGraphGroups;
|
||||
private string Uid { get; set; }
|
||||
|
||||
private readonly CustomData _customData = new CustomData();
|
||||
private readonly UdonGraph _graph;
|
||||
private const int GROUP_LAYER = -1;
|
||||
|
||||
public static UdonGroup Create(string value, Rect position, UdonGraph graph)
|
||||
{
|
||||
var group = new UdonGroup("", graph)
|
||||
{
|
||||
Uid = Guid.NewGuid().ToString()
|
||||
};
|
||||
|
||||
// make sure rect size is not 0
|
||||
position.width = position.width > 0 ? position.width : 128;
|
||||
position.height = position.height > 0 ? position.height : 128;
|
||||
|
||||
group._customData.uid = group.Uid;
|
||||
group._customData.layout = position;
|
||||
group._customData.title = value;
|
||||
group._customData.layer = GROUP_LAYER;
|
||||
group._customData.elementTypeColor = Color.black;
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
// Called in Reload > RestoreElementFromData
|
||||
public static UdonGroup Create(UdonGraphElementData elementData, UdonGraph graph)
|
||||
{
|
||||
return new UdonGroup(elementData.jsonData, graph);
|
||||
}
|
||||
|
||||
// current order of operations issue when creating a group from the context menu means this isn't set until first save. This allows us to force it.
|
||||
public void UpdateDataId()
|
||||
{
|
||||
_customData.uid = Uid;
|
||||
}
|
||||
|
||||
// Build a Group from jsonData, save to userData
|
||||
private UdonGroup(string jsonData, UdonGraph graph)
|
||||
{
|
||||
title = "Group";
|
||||
_graph = graph;
|
||||
layer = GROUP_LAYER;
|
||||
|
||||
if (!string.IsNullOrEmpty(jsonData))
|
||||
{
|
||||
EditorJsonUtility.FromJsonOverwrite(jsonData, _customData);
|
||||
}
|
||||
|
||||
// listen for changes on child elements
|
||||
RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
}
|
||||
|
||||
public sealed override string title
|
||||
{
|
||||
get => base.title;
|
||||
set
|
||||
{
|
||||
base.title = value;
|
||||
UpdateGraphGroups?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGeometryChanged(GeometryChangedEvent evt)
|
||||
{
|
||||
_customData.layout = GraphElementExtension.GetSnappedRect(GetPosition());
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (_customData != null)
|
||||
{
|
||||
// Propagate data to useful places
|
||||
title = _customData.title;
|
||||
layer = _customData.layer;
|
||||
if (string.IsNullOrEmpty(_customData.uid))
|
||||
{
|
||||
_customData.uid = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
Uid = _customData.uid;
|
||||
|
||||
// Add all elements from graph to self
|
||||
var childUIDs = _customData.containedElements;
|
||||
if (childUIDs.Count > 0)
|
||||
{
|
||||
foreach (var item in childUIDs)
|
||||
{
|
||||
GraphElement element = _graph.GetElementByGuid(item);
|
||||
if (element != null)
|
||||
{
|
||||
if (ContainsElement(element)) continue;
|
||||
AddElement(element);
|
||||
if (element is UdonComment c)
|
||||
{
|
||||
c.group = this;
|
||||
}
|
||||
else if (element is UdonNode n)
|
||||
{
|
||||
n.group = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No children, so restore the saved position
|
||||
SetPosition(_customData.layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetPosition(Rect newPos)
|
||||
{
|
||||
newPos = GraphElementExtension.GetSnappedRect(newPos);
|
||||
base.SetPosition(newPos);
|
||||
}
|
||||
|
||||
public void SaveNewData()
|
||||
{
|
||||
_graph.SaveGraphElementData(this);
|
||||
}
|
||||
|
||||
// Save data to asset after new position set
|
||||
public override void UpdatePresenterPosition()
|
||||
{
|
||||
base.UpdatePresenterPosition();
|
||||
Rect snappedRect = GraphElementExtension.GetSnappedRect(GetPosition());
|
||||
base.SetPosition(snappedRect);
|
||||
SaveNewData();
|
||||
}
|
||||
|
||||
public void SelectGroup()
|
||||
{
|
||||
_graph.ClearSelection();
|
||||
// groups exist on a separate layer and fairly opaque from an actual graph view, so it doesn't report them in the `GetElementByGuid`
|
||||
// so we force-select them via UI Elements ways
|
||||
_graph.AddToSelection(_graph.contentViewContainer.Query<UdonGroup>().Where(g => g.Equals(this)).First());
|
||||
var childUIDs = _customData.containedElements;
|
||||
if (childUIDs.Count > 0)
|
||||
{
|
||||
foreach (var item in childUIDs)
|
||||
{
|
||||
_graph.AddToSelection( _graph.GetElementByGuid(item));
|
||||
}
|
||||
}
|
||||
_graph.FrameSelection();
|
||||
}
|
||||
|
||||
// Save data to asset after rename
|
||||
protected override void OnGroupRenamed(string oldName, string newName)
|
||||
{
|
||||
// limit name to 100 characters
|
||||
title = newName.Substring(0, Mathf.Min(newName.Length, 100));
|
||||
_customData.title = title;
|
||||
SaveNewData();
|
||||
}
|
||||
|
||||
protected override void OnElementsAdded(IEnumerable<GraphElement> elements)
|
||||
{
|
||||
//Enumerate first to prevent multiple-enumeration
|
||||
IEnumerable<GraphElement> graphElements = elements as GraphElement[] ?? elements.ToArray();
|
||||
base.OnElementsAdded(graphElements);
|
||||
foreach (var element in graphElements)
|
||||
{
|
||||
if (!_customData.containedElements.Contains(element.GetUid()))
|
||||
{
|
||||
_customData.containedElements.Add(element.GetUid());
|
||||
}
|
||||
|
||||
switch (element)
|
||||
{
|
||||
// Set group variable on UdonNodes
|
||||
case UdonNode node:
|
||||
node.group = this;
|
||||
node.BringToFront();
|
||||
break;
|
||||
case UdonComment comment:
|
||||
comment.group = this;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SaveNewData();
|
||||
}
|
||||
|
||||
protected override void OnElementsRemoved(IEnumerable<GraphElement> elements)
|
||||
{
|
||||
//Enumerate first to prevent multiple-enumeration
|
||||
IEnumerable<GraphElement> graphElements = elements as GraphElement[] ?? elements.ToArray();
|
||||
base.OnElementsRemoved(graphElements);
|
||||
foreach (var element in graphElements)
|
||||
{
|
||||
if (!_customData.containedElements.Contains(element.GetUid())) continue;
|
||||
_customData.containedElements.Remove(element.GetUid());
|
||||
switch (element)
|
||||
{
|
||||
case UdonNode node:
|
||||
node.group = null;
|
||||
break;
|
||||
case UdonComment comment:
|
||||
comment.group = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SaveNewData();
|
||||
}
|
||||
|
||||
public UdonGraphElementData GetData()
|
||||
{
|
||||
return new UdonGraphElementData(UdonGraphElementType.UdonGroup, Uid, EditorJsonUtility.ToJson(_customData));
|
||||
}
|
||||
|
||||
// CustomData is serialized in user assets, so we can't rename/modify/remove any of these variables
|
||||
// ReSharper disable InconsistentNaming
|
||||
// ReSharper disable NotAccessedField.Local
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Local
|
||||
private class CustomData
|
||||
{
|
||||
public string uid;
|
||||
public Rect layout;
|
||||
public List<string> containedElements = new List<string>();
|
||||
public string title;
|
||||
public int layer;
|
||||
public Color elementTypeColor;
|
||||
}
|
||||
// ReSharper enable InconsistentNaming
|
||||
// ReSharper enable NotAccessedField.Local
|
||||
// ReSharper enable FieldCanBeMadeReadOnly.Local
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b8045222a10ce04b815642b9cd5ca17
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcd657bc1dcf357448d27bcfa8c5dc36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bca285c1c0c4a5cb2f03599b086abe4
|
||||
timeCreated: 1623890899
|
||||
@ -0,0 +1,24 @@
|
||||
using EngineUI = UnityEngine.UIElements;
|
||||
using EditorUI = UnityEngine.UIElements;
|
||||
|
||||
using VRC.Udon.Graph;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView.UdonNodes
|
||||
{
|
||||
public class GetOrSetProgramVariableNode : UdonNode
|
||||
{
|
||||
private EditorUI.PopupField<string> _programVariablePopup;
|
||||
|
||||
public GetOrSetProgramVariableNode(UdonNodeDefinition nodeDefinition, UdonGraph view, UdonNodeData nodeData = null) :
|
||||
base(nodeDefinition, view, nodeData)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_programVariablePopup =
|
||||
this.GetProgramPopup(UdonNodeExtensions.ProgramPopupType.Variables, _programVariablePopup, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbfa6b1c2cf44feca09853837fc740bb
|
||||
timeCreated: 1623890922
|
||||
@ -0,0 +1,22 @@
|
||||
using EditorGV = UnityEditor.Experimental.GraphView;
|
||||
using EngineUI = UnityEngine.UIElements;
|
||||
using EditorUI = UnityEngine.UIElements;
|
||||
using VRC.Udon.Graph;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView.UdonNodes
|
||||
{
|
||||
public class SendCustomEventNode : UdonNode
|
||||
{
|
||||
private EditorUI.PopupField<string> _eventNamePopup;
|
||||
|
||||
public SendCustomEventNode(UdonNodeDefinition nodeDefinition, UdonGraph view, UdonNodeData nodeData = null) : base(nodeDefinition, view, nodeData)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_eventNamePopup = this.GetProgramPopup(UdonNodeExtensions.ProgramPopupType.Events, _eventNamePopup, allowEventsWithParameters: definition.fullName.Contains("__SendCustomNetworkEvent__"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8164fc2c5c5b43428503cf064e8b53f0
|
||||
timeCreated: 1624411228
|
||||
@ -0,0 +1,30 @@
|
||||
using EditorGV = UnityEditor.Experimental.GraphView;
|
||||
using EngineUI = UnityEngine.UIElements;
|
||||
using EditorUI = UnityEditor.UIElements;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using VRC.Udon.Graph;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView.UdonNodes
|
||||
{
|
||||
public class SetReturnValueNode : UdonNode
|
||||
{
|
||||
public SetReturnValueNode(UdonNodeDefinition nodeDefinition, UdonGraph view, UdonNodeData nodeData = null) : base(nodeDefinition, view, nodeData)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
const string returnVariable = UdonBehaviour.ReturnVariableName;
|
||||
string uuid = !Graph.VariableNames.Contains(returnVariable) ? Graph.AddNewVariable("Variable_SystemObject", returnVariable) :
|
||||
Graph.VariableNodes.FirstOrDefault(n => (string)n.nodeValues[1].Deserialize() == returnVariable)?.uid;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(uuid))
|
||||
SetNewValue(uuid, 0);
|
||||
else
|
||||
Debug.LogError("Could not find return value name!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e65118bfe2d43f1ad2412dba47c21ee
|
||||
timeCreated: 1623892831
|
||||
@ -0,0 +1,24 @@
|
||||
using UnityEngine.UIElements;
|
||||
using VRC.Udon.Graph;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView.UdonNodes
|
||||
{
|
||||
public class SetVariableNode : UdonNode
|
||||
{
|
||||
public SetVariableNode(UdonNodeDefinition nodeDefinition, UdonGraph view, UdonNodeData nodeData = null) : base(nodeDefinition, view, nodeData)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
UdonPort sendChangePort = portsIn[2];
|
||||
var toggle = sendChangePort.Q<Toggle>();
|
||||
if (toggle != null)
|
||||
{
|
||||
sendChangePort.Insert(0, toggle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd9209fd8a363ee42a49a2afaeb35805
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,187 @@
|
||||
using System;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using EditorGV = UnityEditor.Experimental.GraphView;
|
||||
using EngineUI = UnityEngine.UIElements;
|
||||
using EditorUI = UnityEngine.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using VRC.Udon.Common;
|
||||
using VRC.Udon.Compiler.Compilers;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView.UdonNodes
|
||||
{
|
||||
public static class UdonNodeExtensions
|
||||
{
|
||||
|
||||
#region Methods for creating popup selectors from Program variables / event
|
||||
|
||||
private static readonly HashSet<string> InternalEventNames = new HashSet<string>()
|
||||
{
|
||||
"_start", "_update", "_lateUpdate", "_fixedUpdate", "onAnimatorIk", "_onAnimatorMove", "_onAvatarChanged", "_onAvatarEyeHeightChanged", "_onBecameInvisible", "_onBecameVisible",
|
||||
"_onPlayerCollisionEnter", "_onCollisionEnter", "_onCollisionEnter2D", "_onPlayerCollisionExit", "_onCollisionExit", "_onCollisionExit2D", "_onPlayerCollisionStay", "_onCollisionStay", "_onCollisionStay2D",
|
||||
"_onPlayerTriggerEnter", "_onTriggerEnter", "_onTriggerEnter2D", "_onPlayerTriggerExit", "_onTriggerExit", "_onTriggerExit2D", "_onPlayerTriggerStay", "_onTriggerStay", "_onTriggerStay2D",
|
||||
"_onDestroy", "_onDisable", "_onDrawGizmos", "_onDrawGizmosSelected", "_onEnable", "_onJointBreak", "_onJointBreak2D", "_onMouseDown", "_onMouseDrag", "_onMouseEnter", "_onMouseExit", "_onMouseOver", "_onMouseUp", "_onMouseUpAsButton",
|
||||
"_onPlayerParticleCollision", "_onParticleCollision", "_onParticleTrigger", "_onPostRender", "_onPreCull", "_onPreRender", "_onRenderImage", "_onRenderObject", "_onTransformChildrenChanged", "_onTransformParentChanged", "_onValidate", "_onWillRenderObject",
|
||||
"_interact", "_onDrop", "_onPickup", "_onPickupUseDown", "_onPickupUseUp", "_onPreSerialization", "_onPostSerialization", "_onDeserialization", "_onVideoEnd", "_onVideoPause", "_onVideoPlay", "_onVideoStart", "_midiNoteOn", "_midiNoteOff", "_midiControlChange",
|
||||
"_onOwnershipRequest", "_onNetworkReady", "_onOwnershipTransferred", "_onPlayerJoined", "_onPlayerLeft", "_onSpawn", "_onStationEntered", "_onStationExited", "_onPlayerRespawn", "_onPlayerDataUpdated", "_onPlayerRestored", "_onInstanceRestored",
|
||||
"_onMasterTransferred", "_onDroneTriggerEnter", "_onDroneTriggerStay", "_onDroneTriggerExit", "_onVRCCameraSettingsChanged", "_onVRCQualitySettingsChanged",
|
||||
#if VRC_ENABLE_PLAYER_PERSISTENCE || VRC_ENABLE_INSTANCE_PERSISTENCE
|
||||
"_onPersistenceUsageUpdated",
|
||||
#endif
|
||||
#if VRC_ENABLE_PLAYER_PERSISTENCE
|
||||
"_onPlayerDataStorageExceeded", "_onPlayerDataStorageWarning", "_onPlayerObjectStorageExceeded", "_onPlayerObjectStorageWarning",
|
||||
#endif
|
||||
};
|
||||
|
||||
public enum ProgramPopupType
|
||||
{
|
||||
Variables, Events
|
||||
}
|
||||
|
||||
private static List<string> GetCustomEventsFromAsset(AbstractSerializedUdonProgramAsset asset, bool allowEventsWithParameters)
|
||||
{
|
||||
// don't return internal event names or VariableChange events
|
||||
var events = asset.RetrieveProgram().EntryPoints.GetExportedSymbols().Where(e =>
|
||||
!InternalEventNames.Contains(e) && !e.StartsWithCached(VariableChangedEvent.EVENT_PREFIX)).ToList();
|
||||
|
||||
if (!allowEventsWithParameters)
|
||||
{
|
||||
for (int i = events.Count - 1; i >= 0 ; i--)
|
||||
{
|
||||
var eventName = events[i];
|
||||
var metadata = asset.GetNetworkCallingMetadata(eventName);
|
||||
if (metadata != null && metadata.Parameters.Length > 0)
|
||||
{
|
||||
// event has parameters, remove
|
||||
events.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
public static EditorUI.PopupField<string> GetProgramPopup(this UdonNode node, ProgramPopupType popupType, EditorUI.PopupField<string> eventNamePopup, bool allowEventsWithParameters)
|
||||
{
|
||||
const string placeholder = "----";
|
||||
const string missing = "MISSING! Was";
|
||||
|
||||
List<string> options = new List<string>{placeholder};
|
||||
var data = node.data;
|
||||
|
||||
bool unavailable = true;
|
||||
if(data.nodeUIDs.Length < 1 || string.IsNullOrEmpty(data.nodeUIDs[0]))
|
||||
{
|
||||
switch (popupType)
|
||||
{
|
||||
case ProgramPopupType.Events:
|
||||
options = GetCustomEventsFromAsset(node.Graph.graphProgramAsset.SerializedProgramAsset, allowEventsWithParameters);
|
||||
break;
|
||||
case ProgramPopupType.Variables:
|
||||
node.Graph.RefreshVariables(false);
|
||||
options = new List<string>(node.Graph.VariableNames).Where(x=>!x.StartsWithCached(VariableChangedEvent.OLD_VALUE_PREFIX)).ToList();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(popupType), popupType, null);
|
||||
}
|
||||
unavailable = options.Count == 0;
|
||||
options.Insert(0, placeholder);
|
||||
}
|
||||
else if(data.InputNodeAtIndex(0)?.fullName == "Get_Variable")
|
||||
{
|
||||
// So much work to get the underlying node referenced by a variable. Would be nice to have a method for this.
|
||||
var parts = data.nodeUIDs[0].Split('|');
|
||||
if (parts.Length < 1) return null;
|
||||
|
||||
string targetId = parts[0];
|
||||
|
||||
var variableGetterNode = node.Graph.graphData.FindNode(targetId);
|
||||
if (variableGetterNode == null || variableGetterNode.nodeValues.Length < 1) return null;
|
||||
|
||||
string variableId = variableGetterNode.nodeValues[0].Deserialize() as string;
|
||||
if (string.IsNullOrWhiteSpace(variableId)) return null;
|
||||
|
||||
string variableName = node.Graph.GetVariableName(variableId);
|
||||
if (string.IsNullOrWhiteSpace(variableName)) return null;
|
||||
|
||||
if (node.Graph.udonBehaviour != null && node.Graph.udonBehaviour.publicVariables.TryGetVariableValue(variableName, out UdonBehaviour ub))
|
||||
{
|
||||
if (ub != null)
|
||||
{
|
||||
switch (popupType)
|
||||
{
|
||||
case ProgramPopupType.Events:
|
||||
options = GetCustomEventsFromAsset(ub.programSource.SerializedProgramAsset, allowEventsWithParameters);
|
||||
break;
|
||||
case ProgramPopupType.Variables:
|
||||
{
|
||||
if(ub.programSource == null){break;}
|
||||
if(ub.programSource.SerializedProgramAsset == null){break;}
|
||||
options = ub.programSource.SerializedProgramAsset.RetrieveProgram()?.SymbolTable
|
||||
.GetSymbols().Where(s =>
|
||||
!s.StartsWithCached(UdonGraphCompiler.INTERNAL_VARIABLE_PREFIX) &&
|
||||
!s.StartsWithCached(VariableChangedEvent.OLD_VALUE_PREFIX)).ToList();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
options?.Insert(0, placeholder);
|
||||
unavailable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int currentIndex = 0;
|
||||
int targetNodeValueIndex = node.data.fullName.Contains("SendCustomNetworkEvent") ? 2 : 1;
|
||||
string targetVarName = data.nodeValues[targetNodeValueIndex].Deserialize() as string;
|
||||
if (targetVarName != null && targetVarName.StartsWithCached(missing)) targetVarName = null;
|
||||
|
||||
// If we have a target variable name:
|
||||
if (!string.IsNullOrWhiteSpace(targetVarName) && options != null)
|
||||
{
|
||||
if (options.Contains(targetVarName))
|
||||
{
|
||||
currentIndex = options.IndexOf(targetVarName);
|
||||
}
|
||||
else
|
||||
{
|
||||
options[0] = unavailable ? targetVarName : $"{missing} {targetVarName}";
|
||||
}
|
||||
}
|
||||
|
||||
if (eventNamePopup == null)
|
||||
{
|
||||
eventNamePopup = new EditorUI.PopupField<string>(options, currentIndex)
|
||||
{
|
||||
name = popupType == ProgramPopupType.Events ? "EventNamePopup" : "VariablePopup"
|
||||
};
|
||||
var eventNamePort = node.inputContainer.Q(null, popupType == ProgramPopupType.Events ? "eventName" : "symbolName");
|
||||
eventNamePort?.Add(eventNamePopup);
|
||||
if (unavailable)
|
||||
{
|
||||
eventNamePopup.SetEnabled(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remaking it - remove the old one, at the new one at its previous location
|
||||
int index = node.inputContainer.IndexOf(eventNamePopup);
|
||||
eventNamePopup.RemoveFromHierarchy();
|
||||
eventNamePopup = new EditorUI.PopupField<string>(options, currentIndex);
|
||||
node.inputContainer.Insert(index, eventNamePopup);
|
||||
}
|
||||
eventNamePopup.RegisterValueChangedCallback(
|
||||
e =>
|
||||
{
|
||||
node.SetNewValue(string.Compare(e.newValue, placeholder, StringComparison.Ordinal) == 0 ? "" : e.newValue.ToString(), targetNodeValueIndex);
|
||||
// Todo: update text field directly and save instead of calling Reload
|
||||
node.Reload();
|
||||
});
|
||||
|
||||
return eventNamePopup;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00b770580aae40ffb9f6a1d898b52269
|
||||
timeCreated: 1625678192
|
||||
@ -0,0 +1,512 @@
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine.UIElements;
|
||||
using EditorUI = UnityEditor.UIElements;
|
||||
using EngineUI = UnityEngine.UIElements;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using VRC.Udon.Graph;
|
||||
using VRC.Udon.Serialization;
|
||||
using VRC.SDK3.Network;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
|
||||
{
|
||||
[Serializable]
|
||||
public class UdonPort : Port
|
||||
{
|
||||
private UdonNodeData _udonNodeData;
|
||||
private int _nodeValueIndex;
|
||||
|
||||
private VisualElement _inputField;
|
||||
private VisualElement _inputFieldTypeLabel;
|
||||
|
||||
private IArrayProvider _inspector;
|
||||
|
||||
protected UdonPort(Orientation portOrientation, Direction portDirection, Capacity portCapacity, Type type) :
|
||||
base(portOrientation, portDirection, portCapacity, type)
|
||||
{
|
||||
}
|
||||
|
||||
public static Port Create(string portName, Direction portDirection, IEdgeConnectorListener connectorListener,
|
||||
Type type, UdonNodeData data, int index, Orientation orientation = Orientation.Horizontal)
|
||||
{
|
||||
|
||||
Capacity capacity = Capacity.Single;
|
||||
if (portDirection == Direction.Input && type == null || portDirection == Direction.Output && type != null)
|
||||
{
|
||||
capacity = Capacity.Multi;
|
||||
}
|
||||
|
||||
UdonPort port = new UdonPort(orientation, portDirection, capacity, type)
|
||||
{
|
||||
m_EdgeConnector = new EdgeConnector<Edge>(connectorListener),
|
||||
portName = portName,
|
||||
_udonNodeData = data,
|
||||
_nodeValueIndex = index
|
||||
};
|
||||
|
||||
port.SetupPort();
|
||||
return port;
|
||||
}
|
||||
|
||||
public int GetIndex()
|
||||
{
|
||||
return _nodeValueIndex;
|
||||
}
|
||||
|
||||
private bool _isSendChangePort;
|
||||
|
||||
private void SetupPort()
|
||||
{
|
||||
_isSendChangePort = portName == "sendChange";
|
||||
if (_isSendChangePort)
|
||||
{
|
||||
m_EdgeConnector = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.AddManipulator(m_EdgeConnector);
|
||||
}
|
||||
|
||||
tooltip = UdonGraphExtensions.FriendlyTypeName(portType);
|
||||
|
||||
// apply friendly name for custom event output parameters
|
||||
if (direction == Direction.Output && _udonNodeData.fullName.StartsWithCached("Event_Custom"))
|
||||
{
|
||||
if (portType != null)
|
||||
{
|
||||
string typeLabel = UdonGraphExtensions.FriendlyTypeName(portType).FriendlyNameify();
|
||||
SetLabelText($"Param {_nodeValueIndex + 1} ({typeLabel})");
|
||||
}
|
||||
}
|
||||
|
||||
if (portType == null || direction == Direction.Output)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_udonNodeData.fullName.StartsWithCached("Event_Custom"))
|
||||
{
|
||||
HandleFieldForCustomEvent();
|
||||
}
|
||||
else if (TryGetValueObject(out object result, portType))
|
||||
{
|
||||
MakeField(result);
|
||||
}
|
||||
|
||||
if (_udonNodeData.fullName.StartsWithCached("Const"))
|
||||
{
|
||||
RemoveConnectorAndLabel();
|
||||
}
|
||||
else if (_udonNodeData.fullName.StartsWithCached("Set_Variable") && _nodeValueIndex == 2)
|
||||
{
|
||||
_isSendChangePort = true;
|
||||
RemoveConnector();
|
||||
AddToClassList("send-change");
|
||||
}
|
||||
|
||||
AddToClassList(portName);
|
||||
|
||||
UpdateLabel(connected);
|
||||
}
|
||||
|
||||
private VisualElement MakeField(object value)
|
||||
{
|
||||
var field = UdonFieldFactory.CreateField(
|
||||
portType,
|
||||
value,
|
||||
SetNewValue
|
||||
);
|
||||
|
||||
if (field != null)
|
||||
{
|
||||
SetupField(field);
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
private void HandleFieldForCustomEvent()
|
||||
{
|
||||
// custom events get some extra fields
|
||||
if (portName == "EventName")
|
||||
{
|
||||
TryGetValueObject(out object result, portType);
|
||||
var field = MakeField(result);
|
||||
SetupFieldForCustomEventName(field);
|
||||
}
|
||||
else if (portName == "MaxEventsPerSecond")
|
||||
{
|
||||
var hasParameters = _udonNodeData.fullName.StartsWithCached("Event_Custom_"); // note the trailing underscore!
|
||||
if (!TryGetValueObject(out object result, portType) || result is not int storedMax)
|
||||
{
|
||||
storedMax = hasParameters ? 5 : 0; // allow 0 for non-parameter events to migrate legacy data
|
||||
}
|
||||
if (hasParameters && storedMax == 0)
|
||||
{
|
||||
storedMax = 5; // default to 5 for parameter events
|
||||
}
|
||||
|
||||
// write back immediately to ensure default is set
|
||||
SetNewValue(storedMax);
|
||||
|
||||
var field = UdonFieldFactory.CreateField(
|
||||
typeof(int),
|
||||
storedMax,
|
||||
(newValue) =>
|
||||
{
|
||||
if (newValue is not int newValueInt)
|
||||
{
|
||||
newValueInt = hasParameters ? 5 : 0;
|
||||
}
|
||||
if (newValueInt < (hasParameters ? 1 : 0))
|
||||
{
|
||||
Debug.LogWarning($"Found invalid MaxEventsPerSecond value of {newValueInt}, applying default.");
|
||||
newValueInt = hasParameters ? 5 : 0;
|
||||
}
|
||||
else if (newValueInt > 100)
|
||||
{
|
||||
Debug.LogWarning($"Found large MaxEventsPerSecond value of {newValueInt}, clamping to 100.");
|
||||
newValueInt = 100;
|
||||
}
|
||||
SetNewValue(newValueInt);
|
||||
}
|
||||
);
|
||||
|
||||
SetupField(field);
|
||||
RemoveConnector();
|
||||
}
|
||||
else if (portName.EndsWith("_type"))
|
||||
{
|
||||
TryGetValueObject(out object result, portType);
|
||||
result ??= typeof(string);
|
||||
var udonType = VRCUdonSyncTypeConverter.TypeToUdonType(result as Type);
|
||||
if (udonType == VRCUdonSyncType.NONE)
|
||||
udonType = VRCUdonSyncType.UdonString;
|
||||
|
||||
// write back immediately to ensure default is set
|
||||
SetNewValue(VRCUdonSyncTypeConverter.UdonTypeToType(udonType));
|
||||
|
||||
var field = UdonFieldFactory.CreateField(
|
||||
typeof(VRCUdonSyncType),
|
||||
udonType,
|
||||
(newValue) =>
|
||||
{
|
||||
// Convert back to type
|
||||
var udonType = (VRCUdonSyncType)newValue;
|
||||
if (udonType == VRCUdonSyncType.NONE)
|
||||
{
|
||||
Debug.LogWarning($"Event parameter cannot have type None, defaulting to String.");
|
||||
udonType = VRCUdonSyncType.UdonString;
|
||||
}
|
||||
var type = VRCUdonSyncTypeConverter.UdonTypeToType(udonType);
|
||||
SetNewValue(type);
|
||||
|
||||
// Disconnect anything from the corresponding output port, since the type changed
|
||||
var eventNode = (UdonNode)node;
|
||||
eventNode.DisconnectUdonPort(eventNode.portsOut[_nodeValueIndex - 2]);
|
||||
|
||||
// Update the port to show the new type
|
||||
this.Reload();
|
||||
}
|
||||
);
|
||||
|
||||
SetupField(field);
|
||||
RemoveConnector();
|
||||
SetLabelText($"Param {_nodeValueIndex - 1} Type");
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupField(VisualElement field)
|
||||
{
|
||||
// Add label, shown when input is connected. Not shown by default
|
||||
var friendlyName = UdonGraphExtensions.FriendlyTypeName(portType).FriendlyNameify();
|
||||
var label = new Label(friendlyName);
|
||||
_inputFieldTypeLabel = label;
|
||||
field.AddToClassList("portField");
|
||||
|
||||
_inputField = field;
|
||||
Add(_inputField);
|
||||
}
|
||||
|
||||
private void SetupFieldForCustomEventName(VisualElement field)
|
||||
{
|
||||
// Custom Event fields need their event names sanitized after input and their connectors removed
|
||||
var tField = (TextField) field;
|
||||
tField.RegisterValueChangedCallback(
|
||||
(e) =>
|
||||
{
|
||||
string newValue = e.newValue.SanitizeVariableName();
|
||||
tField.value = newValue;
|
||||
SetNewValue(newValue);
|
||||
});
|
||||
RemoveConnectorAndLabel();
|
||||
field.AddToClassList("portFieldCustomEvent"); // slightly different spacing
|
||||
}
|
||||
|
||||
private void RemoveConnectorAndLabel()
|
||||
{
|
||||
RemoveConnector();
|
||||
this.Q(null, "connectorText")?.RemoveFromHierarchy();
|
||||
}
|
||||
|
||||
private void RemoveConnector()
|
||||
{
|
||||
this.Q("connector")?.RemoveFromHierarchy();
|
||||
}
|
||||
|
||||
private void SetLabelText(string text)
|
||||
{
|
||||
if (this.Q(null, "connectorText") is Label label)
|
||||
{
|
||||
label.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable 0649 // variable never assigned
|
||||
// ReSharper disable once UnassignedField.Local
|
||||
private Button _editArrayButton;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private void EditArray(Type elementType)
|
||||
{
|
||||
// Update Values when 'Save' is clicked
|
||||
if (_inspector != null)
|
||||
{
|
||||
// Update Values
|
||||
SetNewValue(_inspector.GetValues());
|
||||
|
||||
// Remove Inspector
|
||||
_inspector.RemoveFromHierarchy();
|
||||
_inspector = null;
|
||||
|
||||
// Update Button Text
|
||||
_editArrayButton.text = "Edit";
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise set up the inspector
|
||||
_editArrayButton.text = "Save";
|
||||
|
||||
// Get value object, null is ok
|
||||
TryGetValueObject(out object value);
|
||||
|
||||
// Create it new
|
||||
Type typedArrayInspector = (typeof(UdonArrayInspector<>)).MakeGenericType(elementType);
|
||||
_inspector = (Activator.CreateInstance(typedArrayInspector, value) as IArrayProvider);
|
||||
|
||||
parent.Add(_inspector as VisualElement);
|
||||
}
|
||||
|
||||
// Update elements on connect
|
||||
public override void Connect(Edge edge)
|
||||
{
|
||||
AddToClassList("connected");
|
||||
base.Connect(edge);
|
||||
|
||||
Undo.RecordObject(((UdonNode)node).Graph.graphProgramAsset, "Connect Edge");
|
||||
|
||||
// The below logic is just for Output ports
|
||||
if (edge.input.Equals(this)) return;
|
||||
|
||||
// hide field, show label
|
||||
var input = ((UdonPort) edge.input);
|
||||
input.UpdateLabel(true);
|
||||
|
||||
if (IsReloading())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// update data
|
||||
if (portType == null)
|
||||
{
|
||||
// We are a flow port
|
||||
SetFlowUid(((UdonNode) input.node).uid);
|
||||
this.Compile();
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are a value port, we need to send our info over to the OTHER node
|
||||
string myNodeUid = ((UdonNode) node).uid;
|
||||
input.SetDataFromNewConnection($"{myNodeUid}|{_nodeValueIndex}", input.GetIndex());
|
||||
}
|
||||
|
||||
if (_isSendChangePort)
|
||||
{
|
||||
DisconnectAll();
|
||||
this.Reload();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnStopEdgeDragging()
|
||||
{
|
||||
base.OnStopEdgeDragging();
|
||||
|
||||
if (edgeConnector?.edgeDragHelper?.draggedPort == this)
|
||||
{
|
||||
if (capacity == Capacity.Single && connections.Any())
|
||||
{
|
||||
// This port could only have one connection. Fixed in Reserialize, need to reload to show the change
|
||||
this.Reload();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Reload();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetFlowUid(string newValue)
|
||||
{
|
||||
if (_udonNodeData.flowUIDs.Length <= _nodeValueIndex)
|
||||
{
|
||||
// If we don't have space for this flow value, create a new array
|
||||
// TODO: handle this elsewhere?
|
||||
var newFlowArray = new string[_nodeValueIndex + 1];
|
||||
for (int i = 0; i < _udonNodeData.flowUIDs.Length; i++)
|
||||
{
|
||||
newFlowArray[i] = _udonNodeData.flowUIDs[i];
|
||||
}
|
||||
|
||||
_udonNodeData.flowUIDs = newFlowArray;
|
||||
|
||||
_udonNodeData.flowUIDs.SetValue(newValue, _nodeValueIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
_udonNodeData.flowUIDs.SetValue(newValue, _nodeValueIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReloading()
|
||||
{
|
||||
return node is UdonNode && ((UdonNode) node).Graph.IsReloading;
|
||||
}
|
||||
|
||||
public void SetDataFromNewConnection(string uidAndPort, int index)
|
||||
{
|
||||
// can't do this for Reg stack nodes yet so skipping for demo
|
||||
if (_udonNodeData == null) return;
|
||||
|
||||
if (_udonNodeData.nodeUIDs.Length <= _nodeValueIndex)
|
||||
{
|
||||
Debug.Log("Couldn't set it");
|
||||
}
|
||||
else
|
||||
{
|
||||
_udonNodeData.nodeUIDs.SetValue(uidAndPort, index);
|
||||
}
|
||||
}
|
||||
|
||||
// Update elements on disconnect
|
||||
public override void Disconnect(Edge edge)
|
||||
{
|
||||
RemoveFromClassList("connected");
|
||||
if (node == null) return;
|
||||
Undo.RecordObject(((UdonNode)node).Graph.graphProgramAsset, "Connect Edge");
|
||||
base.Disconnect(edge);
|
||||
|
||||
// hide label, show field
|
||||
if (direction == Direction.Input)
|
||||
{
|
||||
UpdateLabel(false);
|
||||
}
|
||||
|
||||
if (IsReloading())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// update data
|
||||
if (direction == Direction.Output && portType == null)
|
||||
{
|
||||
// We are a flow port
|
||||
SetFlowUid("");
|
||||
this.Compile();
|
||||
}
|
||||
else if (direction == Direction.Input && portType != null)
|
||||
{
|
||||
// Direction is input
|
||||
// We are a value port
|
||||
SetDataFromNewConnection("", GetIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateLabel(bool isConnected)
|
||||
{
|
||||
// Port has a 'connected' bool but it doesn't seem to update, so passing 'isConnected' for now
|
||||
|
||||
if (isConnected)
|
||||
{
|
||||
if (_inputField != null && Contains(_inputField))
|
||||
{
|
||||
_inputField.RemoveFromHierarchy();
|
||||
}
|
||||
|
||||
if (_inputFieldTypeLabel != null && !Contains(_inputFieldTypeLabel))
|
||||
{
|
||||
Add(_inputFieldTypeLabel);
|
||||
}
|
||||
|
||||
if (_editArrayButton != null && Contains(_editArrayButton))
|
||||
{
|
||||
_editArrayButton.RemoveFromHierarchy();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_inputField != null && !Contains(_inputField))
|
||||
{
|
||||
Add(_inputField);
|
||||
}
|
||||
|
||||
if (_inputFieldTypeLabel != null && Contains(_inputFieldTypeLabel))
|
||||
{
|
||||
_inputFieldTypeLabel.RemoveFromHierarchy();
|
||||
}
|
||||
|
||||
if (_editArrayButton != null && !Contains(_editArrayButton))
|
||||
{
|
||||
Add(_editArrayButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetValueObject(out object result, Type type = null)
|
||||
{
|
||||
// Initialize out object
|
||||
result = null;
|
||||
|
||||
// get container from node values
|
||||
SerializableObjectContainer container = _udonNodeData.nodeValues[_nodeValueIndex];
|
||||
|
||||
// Null check, failure
|
||||
if (container == null)
|
||||
return false;
|
||||
|
||||
// Deserialize into result, return failure on null
|
||||
result = container.Deserialize();
|
||||
|
||||
// Strings will deserialize as null, that's ok
|
||||
if (type == null || type == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// any other type is not ok to be null
|
||||
else if (result == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success - return true
|
||||
return type.IsInstanceOfType(result);
|
||||
}
|
||||
|
||||
private void SetNewValue(object newValue)
|
||||
{
|
||||
_udonNodeData.nodeValues[_nodeValueIndex] = SerializableObjectContainer.Serialize(newValue, portType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f83d1d3578dd28498c71a980bca86dd
|
||||
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
Reference in New Issue
Block a user