Initial Commit
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using Meta.WitAi.Data.Configuration;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
public abstract class BaseWitWindow : EditorWindow
|
||||
{
|
||||
// Scroll offset
|
||||
private Vector2 ScrollOffset;
|
||||
|
||||
// Override values
|
||||
protected abstract GUIContent Title { get; }
|
||||
protected virtual Texture2D HeaderIcon => WitTexts.HeaderIcon;
|
||||
protected virtual string HeaderUrl => WitTexts.WitUrl;
|
||||
protected virtual string DocsUrl => WitTexts.Texts.WitDocsUrl;
|
||||
|
||||
// Window open
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
titleContent = Title;
|
||||
WitConfigurationUtility.ReloadConfigurationData();
|
||||
}
|
||||
// Window close
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
ScrollOffset = Vector2.zero;
|
||||
}
|
||||
// Handle Layout
|
||||
protected virtual void OnGUI()
|
||||
{
|
||||
Vector2 size;
|
||||
WitEditorUI.LayoutWindow(Title.text, HeaderIcon, HeaderUrl, DocsUrl, LayoutContent, ref ScrollOffset, out size);
|
||||
}
|
||||
// Draw content of window
|
||||
protected abstract void LayoutContent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb1fb949657a24a43bce2710d35ef1df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_ViewDataDictionary: {instanceID: 0}
|
||||
- witIcon: {fileID: 2800000, guid: d3b5ac4c8b01ef14a8a66d7e2a4991cc, type: 3}
|
||||
- mainHeader: {fileID: 2800000, guid: 6a61dbb599169b64ca5584c8eebeb69e, type: 3}
|
||||
- continueButton: {fileID: 2800000, guid: 2ed0be21c4a8bce4fadffab71d5b6e85, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26754a049aa53d445a323de4dcb955e3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using UnityEditor;
|
||||
|
||||
namespace Meta.WitAi.CallbackHandlers
|
||||
{
|
||||
[CustomEditor(typeof(SimpleIntentHandler))]
|
||||
public class SimpleIntentHandlerEditor : WitIntentMatcherEditor
|
||||
{
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
_fieldGUI.onAdditionalGuiLayout = OnInspectorAdditionalGUI;
|
||||
}
|
||||
private void OnInspectorAdditionalGUI()
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Output", EditorStyles.boldLabel);
|
||||
var eventProperty = serializedObject.FindProperty("onIntentTriggered");
|
||||
EditorGUILayout.PropertyField(eventProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10996c842bbaede43a73adef9cddba5a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Meta.WitAi.Data.Info;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.CallbackHandlers
|
||||
{
|
||||
[CustomEditor(typeof(SimpleStringEntityHandler))]
|
||||
public class SimpleStringEntityHandlerEditor : WitIntentMatcherEditor
|
||||
{
|
||||
// Entity values
|
||||
private string[] _entityNames;
|
||||
private int _entityIndex;
|
||||
|
||||
// Set app info
|
||||
protected override void SetAppInfo(WitAppInfo appInfo)
|
||||
{
|
||||
base.SetAppInfo(appInfo);
|
||||
if (appInfo.entities != null)
|
||||
{
|
||||
_entityNames = appInfo.entities.Select(i => i.name).ToArray();
|
||||
_entityIndex = Array.IndexOf(_entityNames, ((SimpleStringEntityHandler)_matcher).entity);
|
||||
}
|
||||
}
|
||||
// Custom GUI
|
||||
protected override bool OnInspectorCustomGUI(FieldInfo fieldInfo)
|
||||
{
|
||||
base.OnInspectorCustomGUI(fieldInfo);
|
||||
// Custom layout
|
||||
if (string.Equals(fieldInfo.Name, "entity"))
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Entity", EditorStyles.boldLabel);
|
||||
WitEditorUI.LayoutSerializedObjectPopup(serializedObject, "entity",
|
||||
_entityNames, ref _entityIndex);
|
||||
return true;
|
||||
}
|
||||
// Layout intent triggered
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a303e99a01d07d54e9659f3b46adbe25
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Meta.WitAi.Data;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.CallbackHandlers
|
||||
{
|
||||
public class ValuePathMatcherPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
private string currentEditPath;
|
||||
|
||||
class Properties
|
||||
{
|
||||
public const string witValueRef = "witValueReference";
|
||||
public const string path = "path";
|
||||
public const string contentRequired = "contentRequired";
|
||||
public const string matchMethod = "matchMethod";
|
||||
public const string comparisonMethod = "comparisonMethod";
|
||||
public const string matchValue = "matchValue";
|
||||
|
||||
public const string floatingPointComparisonTolerance =
|
||||
"floatingPointComparisonTolerance";
|
||||
}
|
||||
|
||||
private Dictionary<string, bool> foldouts =
|
||||
new Dictionary<string, bool>();
|
||||
|
||||
private string GetPropertyPath(SerializedProperty property)
|
||||
{
|
||||
var valueRefProp = property.FindPropertyRelative(Properties.witValueRef);
|
||||
if (valueRefProp.objectReferenceValue)
|
||||
{
|
||||
return ((WitValue) valueRefProp.objectReferenceValue).path;
|
||||
}
|
||||
return property.FindPropertyRelative(Properties.path).stringValue;
|
||||
}
|
||||
|
||||
private bool IsEditingProperty(SerializedProperty property)
|
||||
{
|
||||
var path = GetPropertyPath(property);
|
||||
return path == currentEditPath || string.IsNullOrEmpty(path);
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
|
||||
float height = 0;
|
||||
|
||||
// Path
|
||||
height += EditorGUIUtility.singleLineHeight;
|
||||
|
||||
if (IsExpanded(property))
|
||||
{
|
||||
// Content Required
|
||||
height += EditorGUIUtility.singleLineHeight;
|
||||
// Match Method
|
||||
height += EditorGUIUtility.singleLineHeight;
|
||||
|
||||
if (ComparisonMethodsVisible(property))
|
||||
{
|
||||
// Comparison Method
|
||||
height += EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
if (ComparisonValueVisible(property))
|
||||
{
|
||||
// Comparison Value
|
||||
height += EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
if (FloatingToleranceVisible(property))
|
||||
{
|
||||
// Floating Point Tolerance
|
||||
height += EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
height += 4;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
private bool IsExpanded(SerializedProperty property)
|
||||
{
|
||||
return foldouts.TryGetValue(GetPropertyPath(property), out bool value) && value;
|
||||
}
|
||||
|
||||
private bool Foldout(Rect rect, SerializedProperty property)
|
||||
{
|
||||
var path = GetPropertyPath(property);
|
||||
if (!foldouts.TryGetValue(path, out var value))
|
||||
{
|
||||
foldouts[path] = false;
|
||||
}
|
||||
|
||||
foldouts[path] = EditorGUI.Foldout(rect, value, "");
|
||||
return foldouts[path];
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var rect = new Rect(position)
|
||||
{
|
||||
height = EditorGUIUtility.singleLineHeight
|
||||
};
|
||||
var path = property.FindPropertyRelative(Properties.path);
|
||||
|
||||
var valueRefProp = property.FindPropertyRelative(Properties.witValueRef);
|
||||
var editIconWidth = 24;
|
||||
var pathRect = new Rect(rect);
|
||||
pathRect.width -= editIconWidth;
|
||||
var pathValue = GetPropertyPath(property);
|
||||
if (IsEditingProperty(property))
|
||||
{
|
||||
if (!valueRefProp.objectReferenceValue)
|
||||
{
|
||||
pathRect.width -= WitStyles.IconButtonSize;
|
||||
var value = EditorGUI.TextField(pathRect, path.stringValue);
|
||||
if (value != path.stringValue)
|
||||
{
|
||||
path.stringValue = value;
|
||||
}
|
||||
|
||||
pathRect.width += WitStyles.IconButtonSize;
|
||||
|
||||
var pickerRect = new Rect(pathRect)
|
||||
{
|
||||
x = pathRect.x + pathRect.width - 20,
|
||||
width = 20
|
||||
};
|
||||
if (GUI.Button(pickerRect, WitStyles.ObjectPickerIcon, "Label"))
|
||||
{
|
||||
var id = EditorGUIUtility.GetControlID(FocusType.Passive) + 100;
|
||||
EditorGUIUtility.ShowObjectPicker<WitValue>(
|
||||
(WitValue) valueRefProp.objectReferenceValue, false, "", id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.PropertyField(pathRect, valueRefProp, new GUIContent());
|
||||
}
|
||||
|
||||
if (Event.current.commandName == "ObjectSelectorClosed")
|
||||
{
|
||||
valueRefProp.objectReferenceValue = EditorGUIUtility.GetObjectPickerObject();
|
||||
}
|
||||
|
||||
pathValue = GetPropertyPath(property);
|
||||
if (pathValue != currentEditPath && null != currentEditPath)
|
||||
{
|
||||
foldouts[currentEditPath] = false;
|
||||
currentEditPath = GetPropertyPath(property);
|
||||
foldouts[currentEditPath] = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (valueRefProp.objectReferenceValue)
|
||||
{
|
||||
EditorGUI.LabelField(pathRect, valueRefProp.objectReferenceValue.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.LabelField(pathRect, path.stringValue);
|
||||
}
|
||||
}
|
||||
|
||||
var editRect = new Rect(rect)
|
||||
{
|
||||
x = pathRect.x + pathRect.width + 8
|
||||
};
|
||||
|
||||
if (Foldout(rect, property))
|
||||
{
|
||||
if (GUI.Button(editRect, WitStyles.EditIcon, "Label"))
|
||||
{
|
||||
if (currentEditPath == pathValue)
|
||||
{
|
||||
currentEditPath = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentEditPath = pathValue;
|
||||
}
|
||||
}
|
||||
|
||||
rect.x += WitStyles.IconButtonSize;
|
||||
rect.width -= WitStyles.IconButtonSize;
|
||||
rect.y += rect.height;
|
||||
EditorGUI.PropertyField(rect, property.FindPropertyRelative(Properties.contentRequired));
|
||||
rect.y += rect.height;
|
||||
EditorGUI.PropertyField(rect, property.FindPropertyRelative(Properties.matchMethod));
|
||||
|
||||
if (ComparisonMethodsVisible(property))
|
||||
{
|
||||
rect.y += rect.height;
|
||||
EditorGUI.PropertyField(rect,
|
||||
property.FindPropertyRelative(Properties.comparisonMethod));
|
||||
}
|
||||
|
||||
if (ComparisonValueVisible(property))
|
||||
{
|
||||
rect.y += rect.height;
|
||||
EditorGUI.PropertyField(rect,
|
||||
property.FindPropertyRelative(Properties.matchValue));
|
||||
}
|
||||
|
||||
if (FloatingToleranceVisible(property))
|
||||
{
|
||||
rect.y += rect.height;
|
||||
EditorGUI.PropertyField(rect,
|
||||
property.FindPropertyRelative(Properties.floatingPointComparisonTolerance));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ComparisonMethodsVisible(SerializedProperty property)
|
||||
{
|
||||
var matchedMethodProperty = property.FindPropertyRelative(Properties.matchMethod);
|
||||
return matchedMethodProperty.enumValueIndex > (int) MatchMethod.RegularExpression;
|
||||
}
|
||||
|
||||
private bool ComparisonValueVisible(SerializedProperty property)
|
||||
{
|
||||
var matchedMethodProperty = property.FindPropertyRelative(Properties.matchMethod);
|
||||
return matchedMethodProperty.enumValueIndex > 0;
|
||||
}
|
||||
|
||||
private bool FloatingToleranceVisible(SerializedProperty property)
|
||||
{
|
||||
var matchedMethodProperty = property.FindPropertyRelative(Properties.matchMethod);
|
||||
var comparisonMethodProperty =
|
||||
property.FindPropertyRelative(Properties.comparisonMethod);
|
||||
|
||||
var comparisonMethod = comparisonMethodProperty.enumValueIndex;
|
||||
return matchedMethodProperty.enumValueIndex >= (int) MatchMethod.FloatComparison &&
|
||||
(comparisonMethod == (int) ComparisonMethod.Equals || comparisonMethod == (int) ComparisonMethod.NotEquals);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70c91e08d884bfe4a99b40d2706b15d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Meta.WitAi.Data.Info;
|
||||
using Meta.WitAi.Windows;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.CallbackHandlers
|
||||
{
|
||||
public class WitIntentMatcherEditor : Editor
|
||||
{
|
||||
// The matcher
|
||||
protected WitIntentMatcher _matcher;
|
||||
// Custom field gui
|
||||
protected FieldGUI _fieldGUI;
|
||||
|
||||
// Intents & current intent
|
||||
private string[] _intentNames;
|
||||
private int _intentIndex;
|
||||
|
||||
// On enable, setup gui
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
_matcher = target as WitIntentMatcher;
|
||||
|
||||
// Setup field gui
|
||||
if (_fieldGUI == null)
|
||||
{
|
||||
_fieldGUI = new FieldGUI();
|
||||
_fieldGUI.onCustomGuiLayout = OnInspectorCustomGUI;
|
||||
}
|
||||
}
|
||||
// Inspector gui
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (!_matcher.Voice)
|
||||
{
|
||||
GUILayout.Label("VoiceService component is not present in the scene. Add voice service to scene to get intent suggestions.",
|
||||
EditorStyles.helpBox);
|
||||
}
|
||||
|
||||
// Intent suggestions
|
||||
if (_matcher && _matcher.Voice && null == _intentNames)
|
||||
{
|
||||
if (_matcher.Voice is IWitRuntimeConfigProvider provider
|
||||
&& null != provider.RuntimeConfiguration
|
||||
&& provider.RuntimeConfiguration.witConfiguration)
|
||||
{
|
||||
SetAppInfo(provider.RuntimeConfiguration.witConfiguration.GetApplicationInfo());
|
||||
}
|
||||
}
|
||||
|
||||
// Layout fields
|
||||
_fieldGUI.OnGuiLayout(serializedObject);
|
||||
}
|
||||
// Set app info
|
||||
protected virtual void SetAppInfo(WitAppInfo appInfo)
|
||||
{
|
||||
if (appInfo.intents != null)
|
||||
{
|
||||
_intentNames = appInfo.intents.Select(i => i.name).ToArray();
|
||||
_intentIndex = Array.IndexOf(_intentNames, _matcher.intent);
|
||||
}
|
||||
}
|
||||
// Custom GUI
|
||||
protected virtual bool OnInspectorCustomGUI(FieldInfo fieldInfo)
|
||||
{
|
||||
// Custom layout
|
||||
if (string.Equals(fieldInfo.Name, "intent"))
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Validation Settings", EditorStyles.boldLabel);
|
||||
WitEditorUI.LayoutSerializedObjectPopup(serializedObject, "intent",
|
||||
_intentNames, ref _intentIndex);
|
||||
return true;
|
||||
}
|
||||
// Layout intent triggered
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ef9650649f4f6740a0b7d5b6b4e5dd2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 817d0e10131c4339849a5c99f8fb082b
|
||||
timeCreated: 1624319154
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d192dfd6dc3ff0240b7171d81525428b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
namespace Meta.WitAi.Data.Configuration
|
||||
{
|
||||
public interface IApplicationDetailProvider
|
||||
{
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ed426c1b615d4b44a3c55c12850ce15
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b74ce5059d44106941f1fcb6419a0e6
|
||||
timeCreated: 1677872564
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Meta.WitAi;
|
||||
using Meta.WitAi.Data.Info;
|
||||
namespace Meta.WitAi.Data.Configuration.Tabs
|
||||
{
|
||||
public class WitConfigurationApplicationTab : WitConfigurationEditorTab
|
||||
{
|
||||
public override Type DataType => null;
|
||||
public override string TabID { get; } = "application";
|
||||
public override int TabOrder { get; } = 0;
|
||||
public override string TabLabel { get; } = WitTexts.Texts.ConfigurationApplicationTabLabel;
|
||||
public override string MissingLabel { get; } = WitTexts.Texts.ConfigurationApplicationMissingLabel;
|
||||
public override bool ShouldTabShow(WitAppInfo appInfo)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public override string GetPropertyName(string tabID)
|
||||
{
|
||||
return "_appInfo";
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bebd7edc23f2449f86d2b4c28582465c
|
||||
timeCreated: 1677872642
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using Meta.WitAi.Data.Info;
|
||||
using UnityEditor;
|
||||
namespace Meta.WitAi.Data.Configuration.Tabs
|
||||
{
|
||||
public abstract class WitConfigurationEditorTab
|
||||
{
|
||||
// the WitConfigurationData type relevant to this tab
|
||||
public abstract Type DataType { get; }
|
||||
|
||||
public abstract string TabID { get; }
|
||||
public abstract int TabOrder { get; }
|
||||
public abstract string TabLabel { get; }
|
||||
public abstract string MissingLabel { get; }
|
||||
public abstract bool ShouldTabShow(WitAppInfo appInfo);
|
||||
public virtual bool ShouldTabShow(WitConfiguration configuration) { return false; }
|
||||
|
||||
public virtual string GetPropertyName(string tabID)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("_appInfo");
|
||||
sb.Append($".{TabID}");
|
||||
return sb.ToString();
|
||||
}
|
||||
public virtual string GetTabText(bool titleLabel)
|
||||
{
|
||||
return titleLabel ? TabLabel : MissingLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6dedb23257484140becc3ef2e04f3bc1
|
||||
timeCreated: 1677855364
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Meta.WitAi;
|
||||
using Meta.WitAi.Data.Info;
|
||||
namespace Meta.WitAi.Data.Configuration.Tabs
|
||||
{
|
||||
public class WitConfigurationEntitiesTab: WitConfigurationEditorTab
|
||||
{
|
||||
public override int TabOrder { get; } = 2;
|
||||
public override Type DataType => null;
|
||||
public override string TabID { get; } = "entities";
|
||||
public override string TabLabel { get; } = WitTexts.Texts.ConfigurationEntitiesTabLabel;
|
||||
public override string MissingLabel { get; } = WitTexts.Texts.ConfigurationEntitiesMissingLabel;
|
||||
public override bool ShouldTabShow(WitAppInfo appInfo)
|
||||
{
|
||||
return null != appInfo.entities;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bd06d8523c94460b26f1228c2efd3e8
|
||||
timeCreated: 1677872927
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Meta.WitAi;
|
||||
using Meta.WitAi.Data.Info;
|
||||
namespace Meta.WitAi.Data.Configuration.Tabs
|
||||
{
|
||||
public class WitConfigurationIntentsTab : WitConfigurationEditorTab
|
||||
{
|
||||
public override Type DataType => null;
|
||||
public override int TabOrder { get; } = 1;
|
||||
public override string TabID { get; } = "intents";
|
||||
public override string TabLabel { get; } = WitTexts.Texts.ConfigurationIntentsTabLabel;
|
||||
public override string MissingLabel { get; } = WitTexts.Texts.ConfigurationIntentsMissingLabel;
|
||||
public override bool ShouldTabShow(WitAppInfo appInfo)
|
||||
{
|
||||
return null != appInfo.intents;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c693b199fe184d9fb432dd65a4b47bee
|
||||
timeCreated: 1677872672
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Meta.WitAi;
|
||||
using Meta.WitAi.Data.Info;
|
||||
namespace Meta.WitAi.Data.Configuration.Tabs
|
||||
{
|
||||
public class WitConfigurationTraitsTab : WitConfigurationEditorTab
|
||||
{
|
||||
public override Type DataType => null;
|
||||
public override int TabOrder { get; } = 3;
|
||||
public override string TabID { get; } = "traits";
|
||||
public override string TabLabel { get; } = WitTexts.Texts.ConfigurationTraitsTabLabel;
|
||||
public override string MissingLabel { get; } = WitTexts.Texts.ConfigurationTraitsMissingLabel;
|
||||
public override bool ShouldTabShow(WitAppInfo appInfo)
|
||||
{
|
||||
return null != appInfo.traits;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e918e26b57b74f01af337608e8d9a531
|
||||
timeCreated: 1677872967
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Meta.WitAi;
|
||||
using Meta.WitAi.Data.Info;
|
||||
namespace Meta.WitAi.Data.Configuration.Tabs
|
||||
{
|
||||
public class WitConfigurationVoicesTab: WitConfigurationEditorTab
|
||||
{
|
||||
public override Type DataType => null;
|
||||
public override int TabOrder { get; } = 4;
|
||||
public override string TabID { get; } = "voices";
|
||||
public override string TabLabel { get; } = WitTexts.Texts.ConfigurationVoicesTabLabel;
|
||||
public override string MissingLabel { get; } = WitTexts.Texts.ConfigurationVoicesMissingLabel;
|
||||
public override bool ShouldTabShow(WitAppInfo appInfo)
|
||||
{
|
||||
return null != appInfo.voices;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d61288c0131e4c43bf0bce4d39f9d829
|
||||
timeCreated: 1677869703
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
namespace Meta.WitAi.Data.Configuration
|
||||
{
|
||||
public class WitApplicationDetailProvider : IApplicationDetailProvider
|
||||
{
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 394d4d63ba17f4ed5918eccdd3b7059f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+631
@@ -0,0 +1,631 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Meta.WitAi.Data.Configuration.Tabs;
|
||||
using Lib.Wit.Runtime.Requests;
|
||||
using Meta.Conduit.Editor;
|
||||
using Meta.WitAi.Configuration;
|
||||
using Meta.WitAi.Data.Configuration;
|
||||
using Meta.Conduit;
|
||||
using Meta.Voice.TelemetryUtilities;
|
||||
using Meta.WitAi.Lib;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Meta.WitAi.Windows.Components;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
[InitializeOnLoadAttribute]
|
||||
public class WitConfigurationEditor : Editor
|
||||
{
|
||||
private ConduitManifestGenerationManager _conduitManifestGenerationManager;
|
||||
|
||||
public WitConfiguration Configuration {
|
||||
get => _configuration;
|
||||
private set
|
||||
{
|
||||
if (_configuration == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_configuration = value;
|
||||
_conduitManifestGenerationManager = ConduitManifestGenerationManager.GetInstance(_configuration);
|
||||
}
|
||||
}
|
||||
private WitConfiguration _configuration;
|
||||
private string _serverToken;
|
||||
private string _appName;
|
||||
private string _appID;
|
||||
private bool _initialized = false;
|
||||
public bool drawHeader = true;
|
||||
private bool _foldout = true;
|
||||
private int _requestTab = 0;
|
||||
private bool _syncInProgress = false;
|
||||
private bool _didCheckAutoTrainAvailability = false;
|
||||
private bool _isAutoTrainAvailable = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not server specific functionality like sync
|
||||
/// should be disabled for this configuration
|
||||
/// </summary>
|
||||
protected virtual bool _disableServerPost => false;
|
||||
private static readonly ManifestLoader ManifestLoader = new ManifestLoader();
|
||||
private static readonly IWitVRequestFactory VRequestFactory = new WitVRequestFactory();
|
||||
|
||||
private EnumSynchronizer _enumSynchronizer;
|
||||
|
||||
private static Type[] _tabTypes;
|
||||
private WitConfigurationEditorTab[] _tabs;
|
||||
|
||||
private const string ENTITY_SYNC_CONSENT_KEY = "Conduit.EntitySync.Consent";
|
||||
|
||||
protected virtual Texture2D HeaderIcon => WitTexts.HeaderIcon;
|
||||
public virtual string HeaderUrl => WitTexts.GetAppURL(Configuration.GetApplicationId(), WitTexts.WitAppEndpointType.Settings);
|
||||
protected virtual string DocsUrl => WitTexts.Texts.WitDocsUrl;
|
||||
protected virtual string OpenButtonLabel => WitTexts.Texts.WitOpenButtonLabel;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// Shared between all WitConfigurationEditors
|
||||
if (_tabTypes == null)
|
||||
{
|
||||
_tabTypes = typeof(WitConfigurationEditorTab).GetSubclassTypes().ToArray();
|
||||
}
|
||||
// Generate tab instances
|
||||
if (_tabs == null)
|
||||
{
|
||||
_tabs = _tabTypes.Select(type => (WitConfigurationEditorTab)Activator.CreateInstance(type))
|
||||
.OrderBy(tab =>tab.TabOrder)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
// Refresh configuration & auth tokens
|
||||
Configuration = target as WitConfiguration;
|
||||
|
||||
// Get app server token
|
||||
_serverToken = WitAuthUtility.GetAppServerToken(Configuration);
|
||||
if (CanConfigurationRefresh(Configuration) && WitConfigurationUtility.IsServerTokenValid(_serverToken))
|
||||
{
|
||||
// Get client token if needed
|
||||
_appID = Configuration.GetApplicationId();
|
||||
if (string.IsNullOrEmpty(_appID))
|
||||
{
|
||||
Configuration.SetServerToken(_serverToken);
|
||||
}
|
||||
// Refresh additional data
|
||||
else
|
||||
{
|
||||
SafeRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
ConduitManifestGenerationManager.PersistStatistics();
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
// Init if needed
|
||||
if (!_initialized || Configuration != target)
|
||||
{
|
||||
Initialize();
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
// Draw header
|
||||
WitEditorUI.LayoutHeaderText(target.name, HeaderUrl, DocsUrl);
|
||||
|
||||
|
||||
// Layout content
|
||||
LayoutContent();
|
||||
}
|
||||
|
||||
private void LayoutConduitContent()
|
||||
{
|
||||
if (_conduitManifestGenerationManager == null)
|
||||
{
|
||||
_conduitManifestGenerationManager = ConduitManifestGenerationManager.GetInstance(Configuration);
|
||||
}
|
||||
|
||||
var isServerTokenValid = WitConfigurationUtility.IsServerTokenValid(_serverToken);
|
||||
if (!isServerTokenValid && !_disableServerPost)
|
||||
{
|
||||
GUILayout.TextArea(WitTexts.Texts.ConfigurationConduitMissingTokenLabel, WitStyles.LabelError);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
// Set conduit
|
||||
var updated = false;
|
||||
WitEditorUI.LayoutToggle(new GUIContent(WitTexts.Texts.ConfigurationConduitUseConduitLabel), ref Configuration.useConduit, ref updated);
|
||||
if (updated)
|
||||
{
|
||||
EditorUtility.SetDirty(Configuration);
|
||||
}
|
||||
|
||||
// Configuration buttons
|
||||
GUILayout.Space(EditorGUI.indentLevel * WitStyles.ButtonMargin);
|
||||
{
|
||||
GUI.enabled = Configuration.useConduit;
|
||||
updated = false;
|
||||
WitEditorUI.LayoutToggle(
|
||||
new GUIContent(WitTexts.Texts.ConfigurationConduitRelaxedResolutionsLabel,
|
||||
WitTexts.Texts.ConfigurationConduitRelaxedResolutionsTooltip),
|
||||
ref Configuration.relaxedResolution, ref updated);
|
||||
if (updated)
|
||||
{
|
||||
EditorUtility.SetDirty(Configuration);
|
||||
}
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
{
|
||||
if (_conduitManifestGenerationManager != null && WitEditorUI.LayoutTextButton(_conduitManifestGenerationManager.ManifestAvailable ? WitTexts.Texts.ConfigurationConduitUpdateManifestLabel : WitTexts.Texts.ConfigurationConduitGenerateManifestLabel))
|
||||
{
|
||||
_conduitManifestGenerationManager.GenerateManifest(Configuration, true);
|
||||
}
|
||||
|
||||
GUI.enabled = Configuration.useConduit && _conduitManifestGenerationManager.ManifestAvailable ;
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.ConfigurationConduitSelectManifestLabel) && _conduitManifestGenerationManager.ManifestAvailable )
|
||||
{
|
||||
Selection.activeObject =
|
||||
AssetDatabase.LoadAssetAtPath<TextAsset>(Configuration.GetManifestEditorPath());
|
||||
}
|
||||
|
||||
GUI.enabled = Configuration.useConduit;
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.ConfigurationConduitSpecifyAssembliesLabel))
|
||||
{
|
||||
PresentAssemblySelectionDialog();
|
||||
}
|
||||
|
||||
if (isServerTokenValid && !_disableServerPost)
|
||||
{
|
||||
GUI.enabled = Configuration.useConduit && _conduitManifestGenerationManager.ManifestAvailable && !_syncInProgress;
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.ConfigurationConduitSyncEntitiesLabel))
|
||||
{
|
||||
SyncEntities();
|
||||
GUIUtility.ExitGUI();
|
||||
return;
|
||||
}
|
||||
if (_isAutoTrainAvailable)
|
||||
{
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.ConfigurationConduitAutoTrainLabel) && _conduitManifestGenerationManager.ManifestAvailable )
|
||||
{
|
||||
SyncEntities(() => { AutoTrainOnWitAi(Configuration); });
|
||||
}
|
||||
}
|
||||
}
|
||||
GUI.enabled = true;
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
protected virtual void LayoutContent()
|
||||
{
|
||||
// Begin vertical box
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
|
||||
// Check for app name/id update
|
||||
ReloadAppData();
|
||||
|
||||
// Title Foldout
|
||||
GUILayout.BeginHorizontal();
|
||||
string foldoutText = WitTexts.Texts.ConfigurationHeaderLabel;
|
||||
if (!string.IsNullOrEmpty(_appName))
|
||||
{
|
||||
foldoutText = foldoutText + " - " + _appName;
|
||||
}
|
||||
|
||||
_foldout = WitEditorUI.LayoutFoldout(new GUIContent(foldoutText), _foldout);
|
||||
// Refresh button
|
||||
if (CanConfigurationRefresh(Configuration))
|
||||
{
|
||||
if (string.IsNullOrEmpty(_appName))
|
||||
{
|
||||
bool isValid = WitConfigurationUtility.IsServerTokenValid(_serverToken);
|
||||
GUI.enabled = isValid;
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.ConfigurationRefreshButtonLabel))
|
||||
{
|
||||
ApplyServerToken(_serverToken);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isRefreshing = Configuration.IsUpdatingData();
|
||||
GUI.enabled = !isRefreshing;
|
||||
if (WitEditorUI.LayoutTextButton(isRefreshing ? WitTexts.Texts.ConfigurationRefreshingButtonLabel : WitTexts.Texts.ConfigurationRefreshButtonLabel))
|
||||
{
|
||||
SafeRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
GUI.enabled = true;
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(WitStyles.ButtonMargin);
|
||||
|
||||
// Show configuration app data
|
||||
if (_foldout)
|
||||
{
|
||||
// Indent
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
// Server access token
|
||||
bool updated = false;
|
||||
WitEditorUI.LayoutPasswordField(WitTexts.ConfigurationServerTokenContent, ref _serverToken, ref updated);
|
||||
|
||||
if (updated && WitConfigurationUtility.IsServerTokenValid(_serverToken))
|
||||
{
|
||||
ApplyServerToken(_serverToken);
|
||||
}
|
||||
|
||||
// Additional data
|
||||
if (Configuration)
|
||||
{
|
||||
LayoutConfigurationData();
|
||||
}
|
||||
|
||||
// Undent
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
// End vertical box layout
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
LayoutConduitContent();
|
||||
GUILayout.EndVertical();
|
||||
|
||||
|
||||
// Layout configuration request tabs
|
||||
LayoutConfigurationRequestTabs();
|
||||
|
||||
// Additional open wit button
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button(OpenButtonLabel, WitStyles.TextButton))
|
||||
{
|
||||
Application.OpenURL(HeaderUrl);
|
||||
}
|
||||
}
|
||||
// Reload app data if needed
|
||||
private void ReloadAppData()
|
||||
{
|
||||
// Check for changes
|
||||
string checkID = "";
|
||||
string checkName = "";
|
||||
if (Configuration != null)
|
||||
{
|
||||
checkID = Configuration.GetApplicationId();
|
||||
if (!string.IsNullOrEmpty(checkID))
|
||||
{
|
||||
checkName = Configuration.GetApplicationInfo().name;
|
||||
}
|
||||
}
|
||||
// Reset
|
||||
if (!string.Equals(_appName, checkName) || !string.Equals(_appID, checkID))
|
||||
{
|
||||
// Refresh app data
|
||||
_appName = checkName;
|
||||
_appID = checkID;
|
||||
|
||||
// Do not clear token if failed to set
|
||||
string newToken = WitAuthUtility.GetAppServerToken(Configuration);
|
||||
if (!string.IsNullOrEmpty(newToken))
|
||||
{
|
||||
_serverToken = newToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Apply server token
|
||||
public void ApplyServerToken(string newToken)
|
||||
{
|
||||
if (newToken != _serverToken)
|
||||
{
|
||||
_serverToken = newToken;
|
||||
Configuration.ResetData();
|
||||
}
|
||||
|
||||
WitAuthUtility.ServerToken = _serverToken;
|
||||
Configuration.SetServerToken(_serverToken);
|
||||
|
||||
_conduitManifestGenerationManager.GenerateManifest(Configuration, false);
|
||||
}
|
||||
// Whether or not to allow a configuration to refresh
|
||||
protected virtual bool CanConfigurationRefresh(WitConfiguration configuration)
|
||||
{
|
||||
return configuration;
|
||||
}
|
||||
// Layout configuration data
|
||||
protected virtual void LayoutConfigurationData()
|
||||
{
|
||||
// Reset update
|
||||
bool updated = false;
|
||||
// Client access field
|
||||
string clientAccessToken = Configuration.GetClientAccessToken();
|
||||
WitEditorUI.LayoutPasswordField(WitTexts.ConfigurationClientTokenContent, ref clientAccessToken, ref updated);
|
||||
if (updated && string.IsNullOrEmpty(clientAccessToken))
|
||||
{
|
||||
VLog.E("Client access token is not defined. Cannot perform requests with '" + Configuration.name + "'.");
|
||||
}
|
||||
// Timeout field
|
||||
WitEditorUI.LayoutIntField(WitTexts.ConfigurationRequestTimeoutContent, ref Configuration.timeoutMS, ref updated);
|
||||
// Updated
|
||||
if (updated)
|
||||
{
|
||||
Configuration.SetClientAccessToken(clientAccessToken);
|
||||
}
|
||||
|
||||
// Show configuration app data
|
||||
LayoutConfigurationEndpoint();
|
||||
}
|
||||
// Layout endpoint data
|
||||
protected virtual void LayoutConfigurationEndpoint()
|
||||
{
|
||||
// Generate if needed
|
||||
if (Configuration.endpointConfiguration == null)
|
||||
{
|
||||
Configuration.endpointConfiguration = new WitEndpointConfig();
|
||||
EditorUtility.SetDirty(Configuration);
|
||||
}
|
||||
|
||||
// Handle via serialized object
|
||||
var serializedObj = new SerializedObject(Configuration);
|
||||
var serializedProp = serializedObj.FindProperty("endpointConfiguration");
|
||||
EditorGUILayout.PropertyField(serializedProp);
|
||||
serializedObj.ApplyModifiedProperties();
|
||||
}
|
||||
// Tabs
|
||||
protected virtual void LayoutConfigurationRequestTabs()
|
||||
{
|
||||
// Application info
|
||||
Data.Info.WitAppInfo appInfo = Configuration.GetApplicationInfo();
|
||||
// Indent
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
// Iterate tabs
|
||||
if (_tabs != null)
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
for (int i = 0; i < _tabs.Length; i++)
|
||||
{
|
||||
// Enable if not selected
|
||||
GUI.enabled = _requestTab != i;
|
||||
// If valid and clicked, begin selecting
|
||||
if (null != appInfo.id &&
|
||||
(_tabs[i].ShouldTabShow(appInfo) || _tabs[i].ShouldTabShow(Configuration)))
|
||||
{
|
||||
if (WitEditorUI.LayoutTabButton(_tabs[i].GetTabText(true)))
|
||||
{
|
||||
_requestTab = i;
|
||||
}
|
||||
}
|
||||
// If invalid, stop selecting
|
||||
else if (_requestTab == i)
|
||||
{
|
||||
_requestTab = -1;
|
||||
}
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
// Layout selected tab using property id
|
||||
string propertyID = _requestTab >= 0 && _requestTab < _tabs.Length
|
||||
? _tabs[_requestTab].TabID
|
||||
: string.Empty;
|
||||
if (!string.IsNullOrEmpty(propertyID) && Configuration != null)
|
||||
{
|
||||
var newConfigData = Array.Find(Configuration.GetConfigData(), d => d.GetType() == _tabs[_requestTab].DataType);
|
||||
|
||||
SerializedObject serializedObj;
|
||||
if (newConfigData == null)
|
||||
{
|
||||
serializedObj = new SerializedObject(Configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
serializedObj = new SerializedObject(newConfigData);
|
||||
}
|
||||
|
||||
SerializedProperty serializedProp = serializedObj.FindProperty(_tabs[_requestTab].GetPropertyName(propertyID));
|
||||
if (serializedProp == null)
|
||||
{
|
||||
WitEditorUI.LayoutErrorLabel(_tabs[_requestTab].GetTabText(false));
|
||||
}
|
||||
else if (!serializedProp.isArray)
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedProp);
|
||||
}
|
||||
else if (serializedProp.arraySize == 0)
|
||||
{
|
||||
WitEditorUI.LayoutErrorLabel(_tabs[_requestTab].GetTabText(false));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < serializedProp.arraySize; i++)
|
||||
{
|
||||
SerializedProperty serializedPropChild = serializedProp.GetArrayElementAtIndex(i);
|
||||
EditorGUILayout.PropertyField(serializedPropChild);
|
||||
}
|
||||
}
|
||||
serializedObj.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
// Undent
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
// Safe refresh
|
||||
protected virtual void SafeRefresh()
|
||||
{
|
||||
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
|
||||
|
||||
if (WitConfigurationUtility.IsServerTokenValid(_serverToken))
|
||||
{
|
||||
Configuration.SetServerToken(_serverToken);
|
||||
Configuration.UpdateDataAssets();
|
||||
}
|
||||
else if (WitConfigurationUtility.IsClientTokenValid(Configuration.GetClientAccessToken()))
|
||||
{
|
||||
Configuration.RefreshAppInfo();
|
||||
Configuration.UpdateDataAssets();
|
||||
}
|
||||
if (Configuration.useConduit)
|
||||
{
|
||||
CheckAutoTrainAvailabilityIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckAutoTrainAvailabilityIfNeeded()
|
||||
{
|
||||
if (_didCheckAutoTrainAvailability || !WitConfigurationUtility.IsServerTokenValid(_serverToken)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_didCheckAutoTrainAvailability = true;
|
||||
CheckAutoTrainIsAvailable(Configuration, (isAvailable) => {
|
||||
_isAutoTrainAvailable = isAvailable;
|
||||
Telemetry.LogInstantEvent(Telemetry.TelemetryEventId.CheckAutoTrain, new Dictionary<Telemetry.AnnotationKey, string>
|
||||
{
|
||||
{ Telemetry.AnnotationKey.IsAvailable, isAvailable.ToString() }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Show dialog to disable/enable assemblies
|
||||
private void PresentAssemblySelectionDialog()
|
||||
{
|
||||
var assemblyWalker = _conduitManifestGenerationManager.AssemblyWalker;
|
||||
var assemblyNames = assemblyWalker.GetAllAssemblies().Select(a => a.FullName).ToList();
|
||||
assemblyWalker.AssembliesToIgnore = new HashSet<string>(Configuration.excludedAssemblies);
|
||||
WitMultiSelectionPopup.Show(assemblyNames, assemblyWalker.AssembliesToIgnore, (disabledAssemblies) => {
|
||||
assemblyWalker.AssembliesToIgnore = new HashSet<string>(disabledAssemblies);
|
||||
Configuration.excludedAssemblies = new List<string>(assemblyWalker.AssembliesToIgnore);
|
||||
_conduitManifestGenerationManager.GenerateManifest(Configuration, false);
|
||||
});
|
||||
}
|
||||
|
||||
// Sync entities
|
||||
private void SyncEntities(Action successCallback = null)
|
||||
{
|
||||
var instanceKey = Telemetry.StartEvent(Telemetry.TelemetryEventId.SyncEntities);
|
||||
|
||||
if (!EditorUtility.DisplayDialog("Synchronizing with Wit.Ai entities", "This will synchronize local enums with Wit.Ai entities. Part of this process involves generating code locally and may result in overwriting existing code. Please make sure to backup your work before proceeding.", "Proceed", "Cancel", DialogOptOutDecisionType.ForThisSession, ENTITY_SYNC_CONSENT_KEY))
|
||||
{
|
||||
Telemetry.EndEvent(instanceKey, Telemetry.ResultType.Cancel);
|
||||
VLog.D("Entity Sync cancelled");
|
||||
return;
|
||||
}
|
||||
|
||||
// Fail without server token
|
||||
var validServerToken = WitConfigurationUtility.IsServerTokenValid(_serverToken);
|
||||
if (!validServerToken)
|
||||
{
|
||||
Telemetry.EndEventWithFailure(instanceKey, "Invalid server token");
|
||||
VLog.E($"Conduit Sync Failed\nError: Invalid server token");
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate
|
||||
if (_enumSynchronizer == null)
|
||||
{
|
||||
var assemblyWalker = _conduitManifestGenerationManager.AssemblyWalker;
|
||||
_enumSynchronizer = new EnumSynchronizer(Configuration, assemblyWalker, new FileIo(), VRequestFactory);
|
||||
}
|
||||
|
||||
// Sync
|
||||
_syncInProgress = true;
|
||||
EditorUtility.DisplayProgressBar("Conduit Entity Sync", "Generating Manifest.", 0f );
|
||||
_conduitManifestGenerationManager.GenerateManifest(Configuration, false);
|
||||
|
||||
var manifest = LoadManifest(Configuration.ManifestLocalPath);
|
||||
|
||||
const float initializationProgress = 0.1f;
|
||||
EditorUtility.DisplayProgressBar("Conduit Entity Sync", "Synchronizing entities. Please wait...", initializationProgress);
|
||||
VLog.D("Synchronizing enums with Wit.Ai entities");
|
||||
CoroutineUtility.StartCoroutine(_enumSynchronizer.SyncWitEntities(manifest, (success, data) =>
|
||||
{
|
||||
_syncInProgress = false;
|
||||
EditorUtility.ClearProgressBar();
|
||||
if (!success)
|
||||
{
|
||||
Telemetry.EndEventWithFailure(instanceKey, data);
|
||||
VLog.E($"Conduit failed to synchronize entities\nError: {data}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Telemetry.EndEvent(instanceKey, Telemetry.ResultType.Success);
|
||||
VLog.D("Conduit successfully synchronized entities");
|
||||
successCallback?.Invoke();
|
||||
}
|
||||
},
|
||||
(status, progress) =>
|
||||
{
|
||||
EditorUtility.DisplayProgressBar("Conduit Entity Sync", status,
|
||||
initializationProgress + (1f - initializationProgress) * progress);
|
||||
}));
|
||||
}
|
||||
|
||||
private void AutoTrainOnWitAi(WitConfiguration configuration)
|
||||
{
|
||||
var instanceKey = Telemetry.StartEvent(Telemetry.TelemetryEventId.AutoTrain);
|
||||
var manifest = LoadManifest(configuration.ManifestLocalPath);
|
||||
|
||||
var intents = _conduitManifestGenerationManager.ExtractManifestData();
|
||||
VLog.D($"Auto training on WIT.ai: {intents.Count} intents.");
|
||||
|
||||
configuration.ImportData(manifest, (isSuccess, error) =>
|
||||
{
|
||||
if (isSuccess)
|
||||
{
|
||||
Telemetry.EndEvent(instanceKey, Telemetry.ResultType.Success);
|
||||
EditorUtility.DisplayDialog("Auto Train", "Successfully started auto train process on WIT.ai.",
|
||||
"OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
var failureMessage =
|
||||
$"Failed to import generated manifest JSON into WIT.ai: {error}. Manifest:\n{manifest}";
|
||||
Telemetry.EndEventWithFailure(instanceKey, failureMessage);
|
||||
VLog.E(failureMessage);
|
||||
EditorUtility.DisplayDialog("Auto Train", "Failed to start auto train process on WIT.ai.", "OK");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void CheckAutoTrainIsAvailable(WitConfiguration configuration, Action<bool> onComplete)
|
||||
{
|
||||
var appInfo = configuration.GetApplicationInfo();
|
||||
var manifestText = _conduitManifestGenerationManager.GenerateEmptyManifest(appInfo.name, appInfo.id);
|
||||
var manifest = ManifestLoader.LoadManifestFromString(manifestText);
|
||||
configuration.ImportData(manifest, (result, error) => onComplete(result), true);
|
||||
}
|
||||
|
||||
private static Manifest LoadManifest(string manifestPath)
|
||||
{
|
||||
var instanceKey = Telemetry.StartEvent(Telemetry.TelemetryEventId.LoadManifest);
|
||||
|
||||
var manifest = ManifestLoader.LoadManifest(manifestPath);
|
||||
|
||||
if (manifest == null)
|
||||
{
|
||||
Telemetry.EndEventWithFailure(instanceKey);
|
||||
}
|
||||
Telemetry.EndEvent(instanceKey, Telemetry.ResultType.Success);
|
||||
|
||||
return manifest;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fda2e192978913c42af9533c9a0baa01
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using UnityEditor;
|
||||
|
||||
namespace Meta.WitAi.Data.Configuration
|
||||
{
|
||||
public class WitConfigurationPostprocessor : AssetPostprocessor
|
||||
{
|
||||
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets,
|
||||
string[] movedFromAssetPaths)
|
||||
{
|
||||
WitConfigurationUtility.NeedsConfigReload();
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16fe7d4f8f3e51a42ab214947550a298
|
||||
timeCreated: 1631316958
|
||||
+391
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if UNITY_EDITOR
|
||||
//#define VERBOSE_LOG
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Meta.Conduit;
|
||||
using Meta.Voice.TelemetryUtilities;
|
||||
using Meta.WitAi.Json;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Meta.WitAi.Lib;
|
||||
using Meta.WitAi.Requests;
|
||||
using Meta.WitAi.Windows;
|
||||
using Meta.WitAi.Interfaces;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Meta.WitAi.Data.Configuration
|
||||
{
|
||||
public static class WitConfigurationUtility
|
||||
{
|
||||
#region ACCESS
|
||||
// Return wit configs
|
||||
public static WitConfiguration[] WitConfigs
|
||||
{
|
||||
get
|
||||
{
|
||||
// Reload if not setup
|
||||
if (_witConfigs == null)
|
||||
{
|
||||
ReloadConfigurationData();
|
||||
}
|
||||
// Force reload
|
||||
if (_needsConfigReload)
|
||||
{
|
||||
ReloadConfigurationData();
|
||||
}
|
||||
// Return config data
|
||||
return _witConfigs;
|
||||
}
|
||||
}
|
||||
// Wit configuration assets
|
||||
private static WitConfiguration[] _witConfigs = null;
|
||||
|
||||
// Wit configuration asset names
|
||||
public static string[] WitConfigNames => _witConfigNames;
|
||||
private static string[] _witConfigNames = Array.Empty<string>();
|
||||
|
||||
// Config reload
|
||||
private static bool _needsConfigReload = false;
|
||||
|
||||
// Has configuration
|
||||
public static bool HasValidCustomConfig()
|
||||
{
|
||||
// Find a valid custom configuration
|
||||
return Array.Exists(WitConfigs, (c) => !c.isDemoOnly);
|
||||
}
|
||||
// Enable config reload on next access
|
||||
public static void NeedsConfigReload()
|
||||
{
|
||||
_needsConfigReload = true;
|
||||
}
|
||||
// Refresh configuration asset list
|
||||
public static void ReloadConfigurationData()
|
||||
{
|
||||
// Reloaded
|
||||
_needsConfigReload = false;
|
||||
|
||||
// Find all Wit Configurations
|
||||
List<WitConfiguration> loaded = GetLoadedConfigurations();
|
||||
List<WitConfiguration> found = new List<WitConfiguration>();
|
||||
string[] guids = AssetDatabase.FindAssets("t:WitConfiguration");
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
WitConfiguration config = AssetDatabase.LoadAssetAtPath<WitConfiguration>(path);
|
||||
if (!config.isDemoOnly || loaded.Contains(config))
|
||||
{
|
||||
found.Add(config);
|
||||
}
|
||||
}
|
||||
|
||||
// Store wit configuration data
|
||||
_witConfigs = found.ToArray();
|
||||
// Obtain all names
|
||||
_witConfigNames = new string[_witConfigs.Length];
|
||||
for (int i = 0; i < _witConfigs.Length; i++)
|
||||
{
|
||||
_witConfigNames[i] = _witConfigs[i].name;
|
||||
}
|
||||
}
|
||||
// Get configuration index
|
||||
public static int GetConfigurationIndex(WitConfiguration configuration)
|
||||
{
|
||||
// Search through configs
|
||||
return Array.FindIndex(WitConfigs, (checkConfig) => checkConfig == configuration );
|
||||
}
|
||||
// Get configuration index
|
||||
public static int GetConfigurationIndex(string configurationName)
|
||||
{
|
||||
// Search through configs
|
||||
return Array.FindIndex(WitConfigs, (checkConfig) => string.Equals(checkConfig.name, configurationName));
|
||||
}
|
||||
// Return all configurations referenced in loaded scenes
|
||||
public static List<WitConfiguration> GetLoadedConfigurations()
|
||||
{
|
||||
// Get results
|
||||
List<WitConfiguration> results = new List<WitConfiguration>();
|
||||
|
||||
// Iterate loaded scenes
|
||||
for (int sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++)
|
||||
{
|
||||
Scene scene = SceneManager.GetSceneAt(sceneIndex);
|
||||
if (!scene.IsValid() || !scene.isLoaded)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var rootGameObject in scene.GetRootGameObjects())
|
||||
{
|
||||
IWitConfigurationProvider[] providers = rootGameObject.GetComponentsInChildren<IWitConfigurationProvider>(true);
|
||||
if (providers != null)
|
||||
{
|
||||
foreach (var provider in providers)
|
||||
{
|
||||
WitConfiguration config = provider.Configuration;
|
||||
if (config != null && !results.Contains(config))
|
||||
{
|
||||
results.Add(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return results list
|
||||
return results;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MANAGEMENT
|
||||
// Create configuration for token with blank configuration
|
||||
public static int CreateConfiguration(string serverToken)
|
||||
{
|
||||
// Generate blank asset
|
||||
WitConfiguration configurationAsset = ScriptableObject.CreateInstance<WitConfiguration>();
|
||||
configurationAsset.name = WitTexts.Texts.ConfigurationFileNameLabel;
|
||||
configurationAsset.ResetData();
|
||||
// Create
|
||||
int index = SaveConfiguration(serverToken, configurationAsset);
|
||||
if (index == -1)
|
||||
{
|
||||
configurationAsset.DestroySafely();
|
||||
}
|
||||
// Return new index
|
||||
return index;
|
||||
}
|
||||
// Get asset save directory
|
||||
public static string GetFileSaveDirectory(string title, string fileName, string fileExt)
|
||||
{
|
||||
// Determine root directory with selection if possible
|
||||
string rootDirectory = Application.dataPath;
|
||||
if (Selection.activeObject)
|
||||
{
|
||||
// Get asset path
|
||||
string selectedPath = AssetDatabase.GetAssetPath(Selection.activeObject);
|
||||
// Only allow if in assets
|
||||
if (selectedPath.StartsWith("Assets"))
|
||||
{
|
||||
if (AssetDatabase.IsValidFolder(selectedPath))
|
||||
{
|
||||
rootDirectory = selectedPath;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(selectedPath))
|
||||
{
|
||||
rootDirectory = new System.IO.FileInfo(selectedPath).DirectoryName;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Save panel
|
||||
return EditorUtility.SaveFilePanel(title, rootDirectory, fileName, fileExt);
|
||||
}
|
||||
// Save configuration after determining path
|
||||
public static int SaveConfiguration(string serverToken, WitConfiguration configurationAsset)
|
||||
{
|
||||
string savePath = GetFileSaveDirectory(WitTexts.Texts.ConfigurationFileManagerLabel, WitTexts.Texts.ConfigurationFileNameLabel, "asset");
|
||||
return SaveConfiguration(savePath, serverToken, configurationAsset);
|
||||
}
|
||||
// Save configuration to selected location
|
||||
public static int SaveConfiguration(string savePath, string serverToken, WitConfiguration configurationAsset)
|
||||
{
|
||||
// Ensure valid save path
|
||||
if (string.IsNullOrEmpty(savePath))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// Must be in assets
|
||||
string unityPath = savePath.Replace("\\", "/");
|
||||
if (!unityPath.StartsWith(Application.dataPath))
|
||||
{
|
||||
VLog.E($"Configuration Utility - Cannot Create Configuration Outside of Assets Directory\nPath: {unityPath}");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Determine local unity path
|
||||
unityPath = unityPath.Replace(Application.dataPath, "Assets");
|
||||
AssetDatabase.CreateAsset(configurationAsset, unityPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
configurationAsset.UpdateDataAssets(); //must be done after SaveAssets
|
||||
|
||||
// Refresh configurations
|
||||
ReloadConfigurationData();
|
||||
|
||||
// Get new index following reload
|
||||
string name = System.IO.Path.GetFileNameWithoutExtension(unityPath);
|
||||
int index = GetConfigurationIndex(name);
|
||||
|
||||
// Set server token
|
||||
if (!string.IsNullOrEmpty(serverToken))
|
||||
{
|
||||
_witConfigs[index].SetServerToken(serverToken);
|
||||
}
|
||||
|
||||
// Return index
|
||||
return index;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TOKENS
|
||||
// Token valid check
|
||||
public static bool IsServerTokenValid(string serverToken)
|
||||
{
|
||||
return !string.IsNullOrEmpty(serverToken) && WitAuthUtility.IsServerTokenValid(serverToken);
|
||||
}
|
||||
// Token valid check
|
||||
public static bool IsClientTokenValid(string clientToken)
|
||||
{
|
||||
return !string.IsNullOrEmpty(clientToken) && clientToken.Length == 32;
|
||||
}
|
||||
// Sets server token for all configurations if possible
|
||||
public static void SetServerToken(string serverToken, Action<string> onSetComplete = null)
|
||||
{
|
||||
// Invalid token
|
||||
if (!IsServerTokenValid(serverToken))
|
||||
{
|
||||
SetServerTokenComplete(string.Empty, "", onSetComplete);
|
||||
return;
|
||||
}
|
||||
// Perform a list app request to get app for token
|
||||
WitAppInfoUtility.GetAppInfo(serverToken, (clientToken, info, error) =>
|
||||
{
|
||||
SetServerTokenComplete(serverToken, error, onSetComplete);
|
||||
});
|
||||
}
|
||||
// Set server token complete
|
||||
private static void SetServerTokenComplete(string serverToken, string error, Action<string> onSetComplete)
|
||||
{
|
||||
// Failed
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
{
|
||||
VLog.E($"Set Server Token Failed\n{error}");
|
||||
WitAuthUtility.ServerToken = "";
|
||||
}
|
||||
// Success
|
||||
else
|
||||
{
|
||||
// Log Success
|
||||
VLog.D("Set Server Token Success");
|
||||
// Apply token
|
||||
WitAuthUtility.ServerToken = serverToken;
|
||||
// Refresh configurations
|
||||
ReloadConfigurationData();
|
||||
}
|
||||
// On complete
|
||||
onSetComplete?.Invoke(error);
|
||||
}
|
||||
// Sets server token for specified configuration by updating it's application data
|
||||
public static void SetServerToken(this WitConfiguration configuration, string serverToken, Action<string> onSetComplete = null)
|
||||
{
|
||||
var instanceKey = Telemetry.StartEvent(Telemetry.TelemetryEventId.SupplyToken);
|
||||
|
||||
// Invalid
|
||||
if (!IsServerTokenValid(serverToken))
|
||||
{
|
||||
onSetComplete?.Invoke("Invalid Token");
|
||||
return;
|
||||
}
|
||||
// Perform a list app request to get app for token
|
||||
WitAppInfoUtility.GetAppInfo(serverToken, (clientToken, info, error) =>
|
||||
{
|
||||
// Set client access token
|
||||
configuration.SetClientAccessToken(clientToken);
|
||||
// Set application info
|
||||
configuration.SetApplicationInfo(info);
|
||||
// Set server token
|
||||
if (!string.IsNullOrEmpty(info.id))
|
||||
{
|
||||
WitAuthUtility.SetAppServerToken(info.id, serverToken);
|
||||
}
|
||||
|
||||
// Complete
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
{
|
||||
Telemetry.EndEventWithFailure(instanceKey, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
Telemetry.EndEvent(instanceKey, Telemetry.ResultType.Success);
|
||||
}
|
||||
|
||||
onSetComplete?.Invoke(error);
|
||||
});
|
||||
}
|
||||
// Determine if is a server token
|
||||
public static VRequest CheckServerToken(string serverToken, Action<bool> onComplete) => WitAppInfoUtility.CheckServerToken(serverToken, onComplete);
|
||||
#endregion
|
||||
|
||||
#region APP DATA IMPORT
|
||||
|
||||
/// <summary>
|
||||
/// Import supplied Manifest into WIT.ai.
|
||||
/// </summary>
|
||||
internal static void ImportData(this WitConfiguration configuration, Manifest manifest, VRequest.RequestCompleteDelegate<bool> onComplete = null, bool suppressLogs = false)
|
||||
{
|
||||
var manifestData = GetSanitizedManifestString(manifest);
|
||||
var request = new WitSyncVRequest(configuration);
|
||||
VLog.SuppressLogs = suppressLogs;
|
||||
request.RequestImportData(manifestData, (error, responseData) =>
|
||||
{
|
||||
VLog.SuppressLogs = false;
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
{
|
||||
onComplete?.Invoke(false, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
onComplete?.Invoke(true, string.Empty);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a serialized version of the manifest after removing internal data that should not be sent to IDM.
|
||||
/// </summary>
|
||||
/// <param name="manifest">The manifest to process.</param>
|
||||
private static string GetSanitizedManifestString(Manifest manifest)
|
||||
{
|
||||
var filter = new WitParameterFilter();
|
||||
foreach (var action in manifest.Actions)
|
||||
{
|
||||
action.Parameters.RemoveAll(a => filter.ShouldFilterOut(a.EntityType));
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(manifest);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region REFRESH
|
||||
// Refreshes configuration data
|
||||
public static void RefreshAppInfo(this WitConfiguration configuration, Action<string> onRefreshComplete = null)
|
||||
{
|
||||
// Ignore during runtime
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
onRefreshComplete?.Invoke(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update application info
|
||||
WitAppInfoUtility.Update(configuration, (info, s) =>
|
||||
{
|
||||
// Set application info
|
||||
configuration.SetApplicationInfo(info);
|
||||
|
||||
// Complete
|
||||
onRefreshComplete?.Invoke(s);
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67da0cb4ba914f6cb2a97a343ff81db1
|
||||
timeCreated: 1631316958
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
using Meta.WitAi.Configuration;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(WitEndpointConfig))]
|
||||
public class WitEndpointConfigDrawer : WitPropertyDrawer
|
||||
{
|
||||
// All WitEndpointConfig parameters
|
||||
private const string FIELD_URISCHEME = "_uriScheme";
|
||||
private const string FIELD_AUTHORITY = "_authority";
|
||||
private const string FIELD_PORT = "_port";
|
||||
private const string FIELD_API = "_witApiVersion";
|
||||
private const string FIELD_SPEECH = "_speech";
|
||||
private const string FIELD_MESSAGE = "_message";
|
||||
private const string FIELD_DICTATION = "_dictation";
|
||||
private const string FIELD_SYNTHESIZE = "_synthesize";
|
||||
|
||||
// Allow edit with lock
|
||||
protected override WitPropertyEditType EditType => WitPropertyEditType.LockEdit;
|
||||
// Get default fields
|
||||
protected override string GetDefaultFieldValue(SerializedProperty property, FieldInfo subfield)
|
||||
{
|
||||
// Iterate options
|
||||
switch (subfield.Name)
|
||||
{
|
||||
case FIELD_URISCHEME:
|
||||
return WitConstants.URI_SCHEME;
|
||||
case FIELD_AUTHORITY:
|
||||
return WitConstants.URI_AUTHORITY;
|
||||
case FIELD_PORT:
|
||||
return "0";
|
||||
case FIELD_API:
|
||||
return WitConstants.API_VERSION;
|
||||
case FIELD_SPEECH:
|
||||
return WitConstants.ENDPOINT_SPEECH;
|
||||
case FIELD_MESSAGE:
|
||||
return WitConstants.ENDPOINT_MESSAGE;
|
||||
case FIELD_DICTATION:
|
||||
return WitConstants.ENDPOINT_DICTATION;
|
||||
case FIELD_SYNTHESIZE:
|
||||
return WitConstants.ENDPOINT_TTS;
|
||||
case "_event":
|
||||
return WitConstants.ENDPOINT_COMPOSER_MESSAGE;
|
||||
case "_converse":
|
||||
return WitConstants.ENDPOINT_COMPOSER_SPEECH;
|
||||
}
|
||||
|
||||
// Return base
|
||||
return base.GetDefaultFieldValue(property, subfield);
|
||||
}
|
||||
// Use name value for title if possible
|
||||
protected override string GetLocalizedText(SerializedProperty property, string key)
|
||||
{
|
||||
// Iterate options
|
||||
switch (key)
|
||||
{
|
||||
case LocalizedTitleKey:
|
||||
return WitTexts.Texts.ConfigurationEndpointTitleLabel;
|
||||
case FIELD_URISCHEME:
|
||||
return WitTexts.Texts.ConfigurationEndpointUriLabel;
|
||||
case FIELD_AUTHORITY:
|
||||
return WitTexts.Texts.ConfigurationEndpointAuthLabel;
|
||||
case FIELD_PORT:
|
||||
return WitTexts.Texts.ConfigurationEndpointPortLabel;
|
||||
case FIELD_API:
|
||||
return WitTexts.Texts.ConfigurationEndpointApiLabel;
|
||||
case FIELD_SPEECH:
|
||||
return WitTexts.Texts.ConfigurationEndpointSpeechLabel;
|
||||
case FIELD_MESSAGE:
|
||||
return WitTexts.Texts.ConfigurationEndpointMessageLabel;
|
||||
case FIELD_DICTATION:
|
||||
return WitTexts.Texts.ConfigurationEndpointDictationLabel;
|
||||
case FIELD_SYNTHESIZE:
|
||||
return WitTexts.Texts.ConfigurationEndpointSynthesizeLabel;
|
||||
case "_event":
|
||||
return WitTexts.Texts.ConfigurationEndpointComposerEventLabel;
|
||||
case "_converse":
|
||||
return WitTexts.Texts.ConfigurationEndpointComposerConverseLabel;
|
||||
}
|
||||
// Default to base
|
||||
return base.GetLocalizedText(property, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5fff8addd8c86d94d9e793036f5e5538
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Meta.WitAi.Data;
|
||||
using Meta.WitAi.Lib;
|
||||
using Meta.Conduit.Editor;
|
||||
using Meta.WitAi.Json;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Filters out parameters of specific types.
|
||||
/// </summary>
|
||||
internal class WitParameterFilter : IParameterFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests if a parameter type should be filtered out.
|
||||
/// </summary>
|
||||
/// <param name="type">The data type.</param>
|
||||
/// <returns>True if the parameter type should be filtered out. False otherwise.</returns>
|
||||
public bool ShouldFilterOut(Type type)
|
||||
{
|
||||
return type == typeof(WitResponseNode) || type == typeof(VoiceSession);
|
||||
}
|
||||
|
||||
public bool ShouldFilterOut(string typeName)
|
||||
{
|
||||
return typeName == nameof(WitResponseNode) || typeName == nameof(VoiceSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32bad071f0c2d4fa1b657f119f712adc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Meta.WitAi.Data;
|
||||
using Meta.WitAi.Json;
|
||||
using Meta.Conduit.Editor;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates whether a data type if supported by Wit.
|
||||
/// </summary>
|
||||
internal class WitParameterValidator : IParameterValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// These are the types that we natively support.
|
||||
/// </summary>
|
||||
private readonly HashSet<Type> _builtInTypes = new HashSet<Type>()
|
||||
{ typeof(string), typeof(int), typeof(DateTime), typeof(float), typeof(double), typeof(decimal) };
|
||||
|
||||
/// <summary>
|
||||
/// Tests if a parameter type can be supplied directly to a callback method from.
|
||||
/// </summary>
|
||||
/// <param name="type">The data type.</param>
|
||||
/// <returns>True if the parameter type is supported. False otherwise.</returns>
|
||||
public bool IsSupportedParameterType(Type type)
|
||||
{
|
||||
return type.IsEnum || _builtInTypes.Contains(type) || type == typeof(WitResponseNode) || type == typeof(VoiceSession) || type == typeof(Exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b06aba70db204455b215439ad07b8253
|
||||
timeCreated: 1653423412
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Meta.WitAi.Data.Configuration;
|
||||
using Meta.WitAi.Lib;
|
||||
using Meta.WitAi.Requests;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
public class WitWelcomeWizard : WitScriptableWizard
|
||||
{
|
||||
protected string serverToken;
|
||||
public Action<WitConfiguration> successAction;
|
||||
|
||||
protected override Texture2D HeaderIcon => WitTexts.HeaderIcon;
|
||||
protected override GUIContent Title => WitTexts.SetupTitleContent;
|
||||
protected override string ButtonLabel => WitTexts.Texts.SetupSubmitButtonLabel;
|
||||
protected override string ContentSubheaderLabel => WitTexts.Texts.SetupSubheaderLabel;
|
||||
|
||||
// Whether currently using a client token
|
||||
private bool _isCheckingToken = false;
|
||||
private bool _usingClientToken = false;
|
||||
private VRequest _request;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
_isCheckingToken = false;
|
||||
_usingClientToken = false;
|
||||
serverToken = string.Empty;
|
||||
WitAuthUtility.ServerToken = serverToken;
|
||||
}
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
StopTokenCheck();
|
||||
}
|
||||
protected override bool DrawWizardGUI()
|
||||
{
|
||||
// Layout base
|
||||
base.DrawWizardGUI();
|
||||
// True if valid server token
|
||||
return WitConfigurationUtility.IsServerTokenValid(serverToken);
|
||||
}
|
||||
protected override void LayoutFields()
|
||||
{
|
||||
// Token label
|
||||
string serverTokenLabelText = WitTexts.Texts.SetupServerTokenLabel;
|
||||
serverTokenLabelText = serverTokenLabelText.Replace(WitStyles.WitLinkKey, WitStyles.WitLinkColor);
|
||||
if (GUILayout.Button(serverTokenLabelText, WitStyles.Label))
|
||||
{
|
||||
Application.OpenURL(WitTexts.GetAppURL("", WitTexts.WitAppEndpointType.Settings));
|
||||
}
|
||||
// Token field
|
||||
bool updated = false;
|
||||
WitEditorUI.LayoutPasswordField(null, ref serverToken, ref updated);
|
||||
|
||||
// Verifying
|
||||
if (_isCheckingToken)
|
||||
{
|
||||
WitEditorUI.LayoutLabel(WitTexts.Texts.SetupServerTokenVerifyLabel);
|
||||
}
|
||||
// Client token warning
|
||||
else if (_usingClientToken)
|
||||
{
|
||||
WitEditorUI.LayoutErrorLabel(WitTexts.Texts.SetupClientTokenWarningLabel);
|
||||
}
|
||||
|
||||
// Determine if new token is a server token
|
||||
if (updated && WitConfigurationUtility.IsServerTokenValid(serverToken))
|
||||
{
|
||||
CheckToken();
|
||||
}
|
||||
}
|
||||
private void CheckToken()
|
||||
{
|
||||
// Cancel previous check
|
||||
StopTokenCheck();
|
||||
|
||||
// Begin checking
|
||||
_isCheckingToken = true;
|
||||
|
||||
// Perform request
|
||||
_request = WitConfigurationUtility.CheckServerToken(serverToken, (success) =>
|
||||
{
|
||||
_usingClientToken = !success;
|
||||
_isCheckingToken = false;
|
||||
});
|
||||
}
|
||||
private void StopTokenCheck()
|
||||
{
|
||||
// Ignore if not checking
|
||||
if (!_isCheckingToken)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Kill request
|
||||
if (_request != null)
|
||||
{
|
||||
_request.Cancel();
|
||||
_request = null;
|
||||
}
|
||||
|
||||
// Done checking
|
||||
_isCheckingToken = false;
|
||||
}
|
||||
protected override void OnWizardCreate()
|
||||
{
|
||||
ValidateAndClose();
|
||||
}
|
||||
protected virtual void ValidateAndClose()
|
||||
{
|
||||
// Verify
|
||||
if (_isCheckingToken)
|
||||
{
|
||||
VLog.E(WitTexts.Texts.SetupServerTokenVerifyWarning);
|
||||
return;
|
||||
}
|
||||
// Check client token
|
||||
if (_usingClientToken)
|
||||
{
|
||||
if (!WitConfigurationUtility.IsClientTokenValid(serverToken))
|
||||
{
|
||||
VLog.E(WitTexts.Texts.SetupSubmitFailLabel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Check server token
|
||||
else
|
||||
{
|
||||
WitAuthUtility.ServerToken = serverToken;
|
||||
if (!WitAuthUtility.IsServerTokenValid())
|
||||
{
|
||||
VLog.E(WitTexts.Texts.SetupSubmitFailLabel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Create configuration
|
||||
int index = CreateConfiguration(serverToken);
|
||||
if (index != -1)
|
||||
{
|
||||
// Complete
|
||||
Close();
|
||||
WitConfiguration c = WitConfigurationUtility.WitConfigs[index];
|
||||
if (successAction == null)
|
||||
{
|
||||
WitWindowUtility.OpenConfigurationWindow(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
successAction(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected virtual int CreateConfiguration(string newToken)
|
||||
{
|
||||
// Generate asset with client token
|
||||
if (_usingClientToken)
|
||||
{
|
||||
WitConfiguration configuration = ScriptableObject.CreateInstance<WitConfiguration>();
|
||||
configuration.SetClientAccessToken(newToken);
|
||||
return WitConfigurationUtility.SaveConfiguration(string.Empty, configuration);
|
||||
}
|
||||
// Generate asset with server token
|
||||
return WitConfigurationUtility.CreateConfiguration(newToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 842ab427b28d8450597f95ef8c8689f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Meta.Voice.TelemetryUtilities;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Meta.WitAi.Data.Configuration;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
public class WitWindow : WitConfigurationWindow
|
||||
{
|
||||
protected WitConfigurationEditor witInspector;
|
||||
protected string serverToken;
|
||||
protected override GUIContent Title => WitTexts.SettingsTitleContent;
|
||||
protected override string HeaderUrl => witInspector ? witInspector.HeaderUrl : base.HeaderUrl;
|
||||
|
||||
// VLog log level
|
||||
private static int _logLevel = -1;
|
||||
private static string[] _logLevelNames;
|
||||
private static readonly VLogLevel[] _logLevels = (Enum.GetValues(typeof(VLogLevel)) as VLogLevel[])?.Reverse().ToArray();
|
||||
|
||||
#if VSDK_TELEMETRY_AVAILABLE
|
||||
private static int _telemetryLogLevel = -1;
|
||||
private static string[] _telemetryLogLevelNames;
|
||||
private static readonly TelemetryLogLevel[] _telemetryLogLevels = new TelemetryLogLevel[]
|
||||
{ TelemetryLogLevel.Off, TelemetryLogLevel.Basic, TelemetryLogLevel.Verbose };
|
||||
#endif
|
||||
public virtual bool ShowWitConfiguration => true;
|
||||
public virtual bool ShowGeneralSettings => true;
|
||||
|
||||
public static bool ShowTooltips
|
||||
{
|
||||
get => EditorPrefs.GetBool("VSDK::Settings::Tooltips", true);
|
||||
set => EditorPrefs.SetBool("VSDK::Settings::Tooltips", value);
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
if (string.IsNullOrEmpty(serverToken))
|
||||
{
|
||||
serverToken = WitAuthUtility.ServerToken;
|
||||
}
|
||||
RefreshLogLevel();
|
||||
InitializeTelemetryLevelOptions();
|
||||
SetWitEditor();
|
||||
}
|
||||
|
||||
protected virtual void SetWitEditor()
|
||||
{
|
||||
// Destroy inspector
|
||||
if (witInspector != null)
|
||||
{
|
||||
DestroyImmediate(witInspector);
|
||||
witInspector = null;
|
||||
}
|
||||
// Generate new inspector & initialize immediately
|
||||
if (witConfiguration)
|
||||
{
|
||||
witInspector = (WitConfigurationEditor)Editor.CreateEditor(witConfiguration);
|
||||
witInspector.drawHeader = false;
|
||||
witInspector.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LayoutContent()
|
||||
{
|
||||
if (ShowGeneralSettings) DrawGeneralSettings();
|
||||
if (ShowWitConfiguration) DrawWitConfigurations();
|
||||
}
|
||||
|
||||
private void DrawGeneralSettings()
|
||||
{
|
||||
// VLog level
|
||||
bool updated = false;
|
||||
RefreshLogLevel();
|
||||
int logLevel = _logLevel;
|
||||
WitEditorUI.LayoutPopup(WitTexts.Texts.VLogLevelLabel, _logLevelNames, ref logLevel, ref updated);
|
||||
if (updated)
|
||||
{
|
||||
SetLogLevel(logLevel);
|
||||
}
|
||||
|
||||
var showTooltips = ShowTooltips;
|
||||
WitEditorUI.LayoutToggle(new GUIContent(WitTexts.Texts.ShowTooltipsLabel), ref showTooltips, ref updated);
|
||||
if (updated)
|
||||
{
|
||||
ShowTooltips = showTooltips;
|
||||
}
|
||||
|
||||
#if VSDK_TELEMETRY_AVAILABLE && UNITY_EDITOR_WIN
|
||||
var enableTelemetry = TelemetryConsentManager.ConsentProvided;
|
||||
WitEditorUI.LayoutToggle(new GUIContent(WitTexts.Texts.TelemetryEnabledLabel), ref enableTelemetry, ref updated);
|
||||
if (updated)
|
||||
{
|
||||
TelemetryConsentManager.ConsentProvided = enableTelemetry;
|
||||
}
|
||||
|
||||
var telemetryLogLevel = _telemetryLogLevel;
|
||||
WitEditorUI.LayoutPopup(WitTexts.Texts.TelemetryLevelLabel, _telemetryLogLevelNames, ref telemetryLogLevel, ref updated);
|
||||
if (updated)
|
||||
{
|
||||
_telemetryLogLevel = Math.Max(0, telemetryLogLevel);
|
||||
Telemetry.LogLevel = _telemetryLogLevels[_telemetryLogLevel];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void DrawWitConfigurations()
|
||||
{
|
||||
// Server access token
|
||||
GUILayout.BeginHorizontal();
|
||||
bool updated = false;
|
||||
WitEditorUI.LayoutPasswordField(WitTexts.SettingsServerTokenContent, ref serverToken, ref updated);
|
||||
if (updated)
|
||||
{
|
||||
RelinkServerToken(false);
|
||||
}
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.SettingsRelinkButtonLabel))
|
||||
{
|
||||
RelinkServerToken(true);
|
||||
}
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.SettingsAddButtonLabel))
|
||||
{
|
||||
OpenConfigGenerationWindow();
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(WitStyles.ButtonMargin);
|
||||
|
||||
// Configuration select
|
||||
base.LayoutContent();
|
||||
// Update inspector if needed
|
||||
if (witInspector == null || witConfiguration == null || witInspector.Configuration != witConfiguration)
|
||||
{
|
||||
SetWitEditor();
|
||||
}
|
||||
|
||||
// Layout configuration inspector
|
||||
if (witConfiguration && witInspector)
|
||||
{
|
||||
witInspector.OnInspectorGUI();
|
||||
}
|
||||
}
|
||||
|
||||
// Apply server token
|
||||
private void RelinkServerToken(bool closeIfInvalid)
|
||||
{
|
||||
// Open Setup if Invalid
|
||||
bool invalid = !WitConfigurationUtility.IsServerTokenValid(serverToken);
|
||||
if (invalid)
|
||||
{
|
||||
// Clear if desired
|
||||
if (string.IsNullOrEmpty(serverToken))
|
||||
{
|
||||
WitAuthUtility.ServerToken = serverToken;
|
||||
}
|
||||
// Open New & Close
|
||||
if (closeIfInvalid)
|
||||
{
|
||||
// Generate new configuration
|
||||
OpenConfigGenerationWindow();
|
||||
// Close
|
||||
Close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Set valid server token
|
||||
WitAuthUtility.ServerToken = serverToken;
|
||||
WitConfigurationUtility.SetServerToken(serverToken);
|
||||
}
|
||||
|
||||
private static void RefreshLogLevel()
|
||||
{
|
||||
if (_logLevelNames != null && _logLevelNames.Length == _logLevels.Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<string> logLevelOptions = new List<string>();
|
||||
foreach (var level in _logLevels)
|
||||
{
|
||||
logLevelOptions.Add(level.ToString());
|
||||
}
|
||||
_logLevelNames = logLevelOptions.ToArray();
|
||||
VLog.Init();
|
||||
_logLevel = logLevelOptions.IndexOf(VLog.EditorLogLevel.ToString());
|
||||
}
|
||||
private void SetLogLevel(int newLevel)
|
||||
{
|
||||
_logLevel = Mathf.Clamp(0, newLevel, _logLevels.Length);
|
||||
VLog.EditorLogLevel = _logLevels[_logLevel];
|
||||
}
|
||||
|
||||
private static void InitializeTelemetryLevelOptions()
|
||||
{
|
||||
#if VSDK_TELEMETRY_AVAILABLE
|
||||
_telemetryLogLevelNames = new string [_telemetryLogLevels.Length];
|
||||
for (int i = 0; i < _telemetryLogLevelNames.Length; ++i)
|
||||
{
|
||||
_telemetryLogLevelNames[i] = _telemetryLogLevels[i].ToString();
|
||||
}
|
||||
|
||||
var currentLevel = Telemetry.LogLevel.ToString();
|
||||
for (int i = 0; i < _telemetryLogLevelNames.Length; ++i)
|
||||
{
|
||||
if (_telemetryLogLevelNames[i] == currentLevel)
|
||||
{
|
||||
_telemetryLogLevel = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15c29f496a2443b4aa5e0ab283126a83
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_ViewDataDictionary: {instanceID: 0}
|
||||
- witIcon: {fileID: 2800000, guid: d3b5ac4c8b01ef14a8a66d7e2a4991cc, type: 3}
|
||||
- mainHeader: {fileID: 2800000, guid: 6a61dbb599169b64ca5584c8eebeb69e, type: 3}
|
||||
- continueButton: {fileID: 2800000, guid: 2ed0be21c4a8bce4fadffab71d5b6e85, type: 3}
|
||||
- witConfiguration: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using Meta.WitAi.Configuration;
|
||||
using Meta.WitAi.Data.Configuration;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Meta.WitAi.Data
|
||||
{
|
||||
public class WitDataCreation
|
||||
{
|
||||
const string PATH_KEY = "Facebook::Wit::ValuePath";
|
||||
|
||||
public static WitConfiguration FindDefaultWitConfig()
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:WitConfiguration");
|
||||
if(guids.Length > 0)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
return AssetDatabase.LoadAssetAtPath<WitConfiguration>(path);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void AddWitToScene()
|
||||
{
|
||||
var witGo = new GameObject
|
||||
{
|
||||
name = "Wit"
|
||||
};
|
||||
var wit = witGo.AddComponent<Wit>();
|
||||
var runtimeConfiguration = new WitRuntimeConfiguration()
|
||||
{
|
||||
witConfiguration = FindDefaultWitConfig()
|
||||
};
|
||||
wit.RuntimeConfiguration = runtimeConfiguration;
|
||||
}
|
||||
|
||||
public static WitStringValue CreateStringValue(string path)
|
||||
{
|
||||
var asset = ScriptableObject.CreateInstance<WitStringValue>();
|
||||
CreateValueAsset("Create String Value", path, asset);
|
||||
return asset;
|
||||
}
|
||||
|
||||
public static WitFloatValue CreateFloatValue(string path)
|
||||
{
|
||||
var asset = ScriptableObject.CreateInstance<WitFloatValue>();
|
||||
CreateValueAsset("Create Float Value", path, asset);
|
||||
return asset;
|
||||
}
|
||||
|
||||
public static WitIntValue CreateIntValue(string path)
|
||||
{
|
||||
var asset = ScriptableObject.CreateInstance<WitIntValue>();
|
||||
CreateValueAsset("Create Int Value", path, asset);
|
||||
return asset;
|
||||
}
|
||||
|
||||
private static void CreateValueAsset(string label, string path, WitValue asset)
|
||||
{
|
||||
asset.path = path;
|
||||
var saveDir = EditorPrefs.GetString(PATH_KEY, Application.dataPath);
|
||||
string name;
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
name = Regex.Replace(path, @"\[[\]0-9]+", "");
|
||||
name = name.Replace(".", " ");
|
||||
name = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = asset.GetType().Name;
|
||||
}
|
||||
|
||||
var filePath = EditorUtility.SaveFilePanelInProject(label, name, "asset", "Please select a location for your asset.");
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
EditorPrefs.SetString(PATH_KEY, filePath);
|
||||
if (filePath.StartsWith("Assets/StreamingAssets"))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Restricted Folder","Cannot use StreamingAssets folder for saving normal assets. \nPlease select another folder inside Assets.", "OK");
|
||||
return;
|
||||
}
|
||||
AssetDatabase.CreateAsset(asset, filePath);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40da7661eee64aaa81d3a0886ce34911
|
||||
timeCreated: 1624319178
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c20804a44a34d2e96ef9eccbcd956b3
|
||||
timeCreated: 1656461095
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using Meta.WitAi.Utilities;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Drawers
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(DynamicRangeAttribute))]
|
||||
public class DynamicRangeAttributeDrawer : PropertyDrawer
|
||||
{
|
||||
private Object _targetObject;
|
||||
private float _min;
|
||||
private float _max;
|
||||
private PropertyInfo _rangePropertyField;
|
||||
private object _parentValue;
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var value = property.floatValue;
|
||||
var attr = attribute as DynamicRangeAttribute;
|
||||
var parentPropertyName =
|
||||
property.propertyPath.Substring(0, property.propertyPath.IndexOf("."));
|
||||
var parentProperty = property.serializedObject.FindProperty(parentPropertyName);
|
||||
|
||||
var targetObject = property.serializedObject.targetObject;
|
||||
if(targetObject != _targetObject)
|
||||
{
|
||||
_targetObject = targetObject;
|
||||
var targetObjectClassType = targetObject.GetType();
|
||||
var field = targetObjectClassType.GetField(parentProperty.propertyPath,
|
||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
if (null != field)
|
||||
{
|
||||
_parentValue = field.GetValue(targetObject);
|
||||
var parentType = _parentValue.GetType();
|
||||
_rangePropertyField = parentType.GetProperty(attr.RangeProperty,
|
||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
}
|
||||
}
|
||||
|
||||
_min = attr.DefaultMin;
|
||||
_max = attr.DefaultMax;
|
||||
if (null != _rangePropertyField)
|
||||
{
|
||||
var range = (Vector2) _rangePropertyField.GetValue(_parentValue);
|
||||
_min = range.x;
|
||||
_max = range.y;
|
||||
}
|
||||
|
||||
property.floatValue = EditorGUI.Slider(position, label, property.floatValue,
|
||||
_min, _max);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c71bbccdffacf4cfea501a346b0b9d1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Meta.WitAi.Data.ValueReferences;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Drawers
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(StringReference<>), true)]
|
||||
public class StringReferenceDrawer : PropertyDrawer
|
||||
{
|
||||
private const int buttonWidth = 20;
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
SerializedProperty stringValueProperty = property.FindPropertyRelative("stringValue");
|
||||
SerializedProperty stringObjectProperty = property.FindPropertyRelative("stringObject");
|
||||
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
// Draw the label
|
||||
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
|
||||
|
||||
// Draw the text field
|
||||
Rect textFieldRect = new Rect(position);
|
||||
textFieldRect.width -= buttonWidth;
|
||||
Rect objFieldRect = new Rect(position.x + textFieldRect.width, position.y, buttonWidth,
|
||||
EditorGUIUtility.singleLineHeight);
|
||||
|
||||
EditorGUI.PropertyField(stringObjectProperty.objectReferenceValue == null ? objFieldRect : position,
|
||||
stringObjectProperty, GUIContent.none);
|
||||
if (stringObjectProperty.objectReferenceValue == null)
|
||||
{
|
||||
stringValueProperty.stringValue = EditorGUI.TextField(textFieldRect, stringValueProperty.stringValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
stringValueProperty.stringValue = ((IStringReference)stringObjectProperty.objectReferenceValue).Value;
|
||||
}
|
||||
|
||||
Type targetType = fieldInfo.FieldType.BaseType.GenericTypeArguments[0];
|
||||
// Handle drag and drop
|
||||
if (Event.current.type == EventType.DragUpdated && textFieldRect.Contains(Event.current.mousePosition))
|
||||
{
|
||||
var validType = false;
|
||||
foreach (var draggedObject in DragAndDrop.objectReferences)
|
||||
{
|
||||
if (draggedObject.GetType() == targetType)
|
||||
{
|
||||
validType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (validType)
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||
}
|
||||
Event.current.Use();
|
||||
}
|
||||
else if (Event.current.type == EventType.DragPerform && textFieldRect.Contains(Event.current.mousePosition))
|
||||
{
|
||||
DragAndDrop.AcceptDrag();
|
||||
|
||||
foreach (var draggedObject in DragAndDrop.objectReferences)
|
||||
{
|
||||
if (draggedObject.GetType() == targetType)
|
||||
{
|
||||
stringObjectProperty.objectReferenceValue = draggedObject;
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Event.current.Use();
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e885f2612e2647c1813153fb6981e5e9
|
||||
timeCreated: 1680299773
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using Meta.WitAi.Attributes;
|
||||
using Meta.WitAi.Windows;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Drawers
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(TooltipBoxAttribute))]
|
||||
public class TooltipBoxDrawer : DecoratorDrawer
|
||||
{
|
||||
private float _spaceAfterBox = 4;
|
||||
private float _iconSize = 32;
|
||||
private float _lastViewWidth;
|
||||
|
||||
public override float GetHeight()
|
||||
{
|
||||
if (!WitWindow.ShowTooltips) return 0;
|
||||
|
||||
TooltipBoxAttribute infoBoxAttribute = (TooltipBoxAttribute)attribute;
|
||||
var height = EditorStyles.helpBox.CalcHeight(new GUIContent(infoBoxAttribute.Text), _lastViewWidth - _iconSize);
|
||||
return Mathf.Max(_iconSize, height) + _spaceAfterBox;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position)
|
||||
{
|
||||
if (!WitWindow.ShowTooltips) return;
|
||||
_lastViewWidth = EditorGUIUtility.currentViewWidth;
|
||||
|
||||
var iconRect = EditorGUI.IndentedRect(position);
|
||||
iconRect.width = _iconSize;
|
||||
iconRect.height = _iconSize;
|
||||
GUIContent infoIcon = EditorGUIUtility.IconContent("console.infoicon");
|
||||
infoIcon.tooltip = "You can turn off these tooltips in Voice SDK Settings.";
|
||||
EditorGUI.LabelField(iconRect, infoIcon);
|
||||
|
||||
var tooltip = (TooltipBoxAttribute) attribute;
|
||||
var rect = EditorGUI.IndentedRect(position);
|
||||
rect.x += _iconSize;
|
||||
rect.width -= _iconSize;
|
||||
rect.height -= _spaceAfterBox;
|
||||
EditorGUI.TextArea(rect, tooltip.Text, EditorStyles.helpBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5be6165094d84fbb9377d595397a1dbc
|
||||
timeCreated: 1680127468
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "Meta.WitAi.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:1c28d8b71ced07540b7c271537363cc6",
|
||||
"GUID:4504b1a6e0fdcc3498c30b266e4a63bf",
|
||||
"GUID:f02292e638368584080af0193f81ff5c",
|
||||
"GUID:70c988d11fbc4814db519eecb47cca75",
|
||||
"GUID:5c61c7ae4b0c6f94299e51352f802670",
|
||||
"GUID:3e75c68ea2ce130409f7b96ae2110237",
|
||||
"GUID:4c3436cc699cb25459568e9fa95b7fd7"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.meta.xr.sdk.voice.telemetry",
|
||||
"expression": "",
|
||||
"define": "VSDK_TELEMETRY_AVAILABLE"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa958eb9f0171754fb207d563a15ddfa
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bd8be981a6845f186f01908998f57e8
|
||||
timeCreated: 1626727424
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Meta.WitAi.Events.Editor
|
||||
{
|
||||
public abstract class EventPropertyDrawer<T> : PropertyDrawer
|
||||
{
|
||||
private const int CONTROL_SPACING = 5;
|
||||
private const int UNSELECTED = -1;
|
||||
private const int BUTTON_WIDTH = 75;
|
||||
private const int PROPERTY_FIELD_SPACING = 25;
|
||||
|
||||
private bool showEvents = false;
|
||||
|
||||
private int selectedCategoryIndex = 0;
|
||||
private int selectedEventIndex = 0;
|
||||
|
||||
private int propertyOffset;
|
||||
|
||||
private static Dictionary<string, string[]> _eventCategories;
|
||||
|
||||
public virtual string DocumentationUrl => string.Empty;
|
||||
public virtual string DocumentationTooltip => string.Empty;
|
||||
|
||||
private const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
|
||||
private void InitializeEventCategories(Type eventsType)
|
||||
{
|
||||
// Get all category events in type & base type
|
||||
Dictionary<string, List<string>> categoryLists = new Dictionary<string, List<string>>();
|
||||
foreach (var field in eventsType.GetFields(FLAGS))
|
||||
{
|
||||
AddCustomField(field, categoryLists);
|
||||
}
|
||||
foreach (var baseField in eventsType.BaseType.GetFields(FLAGS))
|
||||
{
|
||||
AddCustomField(baseField, categoryLists);
|
||||
}
|
||||
|
||||
// Apply
|
||||
_eventCategories = new Dictionary<string, string[]>();
|
||||
foreach (var category in categoryLists.Keys)
|
||||
{
|
||||
_eventCategories[category] = categoryLists[category].ToArray();
|
||||
}
|
||||
}
|
||||
private void AddCustomField(FieldInfo field, Dictionary<string, List<string>> categoryLists)
|
||||
{
|
||||
if (!ShouldShowField(field))
|
||||
{
|
||||
return;
|
||||
}
|
||||
EventCategoryAttribute[] attributes = field.GetCustomAttributes(
|
||||
typeof(EventCategoryAttribute), false) as EventCategoryAttribute[];
|
||||
if (attributes == null || attributes.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var eventCategory in attributes)
|
||||
{
|
||||
List<string> values = categoryLists.ContainsKey(eventCategory.Category) ? categoryLists[eventCategory.Category] : new List<string>();
|
||||
string fieldName = GetDisplayFieldName(field);
|
||||
if (!values.Contains(fieldName))
|
||||
{
|
||||
values.Add(fieldName);
|
||||
}
|
||||
categoryLists[eventCategory.Category] = values;
|
||||
}
|
||||
}
|
||||
private bool ShouldShowField(FieldInfo field)
|
||||
{
|
||||
if (field.IsStatic)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!field.IsPublic && !Attribute.IsDefined(field, typeof(SerializeField)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Attribute.IsDefined(field, typeof(HideInInspector)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Attribute.IsDefined(field, typeof(EventCategoryAttribute));
|
||||
}
|
||||
private string GetDisplayFieldName(FieldInfo field)
|
||||
{
|
||||
string result = field.Name.TrimStart('_');
|
||||
return result[0].ToString().ToUpper() + result.Substring(1, result.Length - 1);
|
||||
}
|
||||
private string GetFieldNameFromDisplay(string fieldDisplayName)
|
||||
{
|
||||
return "_" + fieldDisplayName[0].ToString().ToLower() + fieldDisplayName.Substring(1, fieldDisplayName.Length - 1);
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var eventObject = fieldInfo.GetValue(property.serializedObject.targetObject) as EventRegistry;
|
||||
|
||||
var lineHeight = EditorGUIUtility.singleLineHeight;
|
||||
var lines = 1;
|
||||
var height = 0;
|
||||
|
||||
// Allocate enough lines to display dropdown elements depending on which ones are showing.
|
||||
if (showEvents && Selection.activeTransform)
|
||||
lines++;
|
||||
|
||||
if (showEvents && selectedCategoryIndex != UNSELECTED)
|
||||
lines++;
|
||||
|
||||
height = Mathf.RoundToInt(lineHeight * lines);
|
||||
|
||||
// By default, the property elements appear directly below the dropdowns.
|
||||
propertyOffset = height + (int)WitStyles.TextButtonPadding;
|
||||
|
||||
// If the Events foldout is expanded and there are overridden properties, allocate space for them.
|
||||
if (eventObject != null && eventObject.OverriddenCallbacks.Count != 0 && showEvents)
|
||||
{
|
||||
var callbacksArray = eventObject.OverriddenCallbacks.ToArray();
|
||||
|
||||
foreach (var callback in callbacksArray)
|
||||
{
|
||||
var fieldProperty = GetPropertyFromDisplayFieldName(property, callback);
|
||||
if (fieldProperty != null)
|
||||
{
|
||||
height += Mathf.RoundToInt(EditorGUI.GetPropertyHeight(fieldProperty, true) + CONTROL_SPACING);
|
||||
}
|
||||
}
|
||||
|
||||
// Add some extra space so the last property field's +/- buttons don't overlap the next control.
|
||||
height += PROPERTY_FIELD_SPACING;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
showEvents = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), showEvents, "Events");
|
||||
|
||||
string url = DocumentationUrl;
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
Texture texture = WitStyles.HelpIcon.image;
|
||||
if (texture != null)
|
||||
{
|
||||
// Add a ? button
|
||||
Vector2 textureSize = WitStyles.IconButton.CalcSize(WitStyles.HelpIcon);
|
||||
Rect buttonRect = new Rect(position.x + position.width - textureSize.x, position.y, textureSize.x, textureSize.y);
|
||||
if (GUI.Button(buttonRect,
|
||||
new GUIContent(WitStyles.HelpIcon.image, DocumentationTooltip), WitStyles.IconButton))
|
||||
{
|
||||
Application.OpenURL(url);
|
||||
}
|
||||
// Add a tooltip
|
||||
if (!string.IsNullOrEmpty(DocumentationTooltip))
|
||||
{
|
||||
GUI.Label(buttonRect, GUI.tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showEvents && Selection.activeTransform)
|
||||
{
|
||||
if (_eventCategories == null)
|
||||
InitializeEventCategories(fieldInfo.FieldType);
|
||||
|
||||
var eventObject = fieldInfo.GetValue(property.serializedObject.targetObject) as EventRegistry;
|
||||
|
||||
var eventCategoriesKeyArray = _eventCategories.Keys.ToArray();
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
// Shift the control rectangle down one line to accomodate the category dropdown.
|
||||
position.y += EditorGUIUtility.singleLineHeight;
|
||||
position.height = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
selectedCategoryIndex = EditorGUI.Popup(position, "Event Category",
|
||||
selectedCategoryIndex, eventCategoriesKeyArray);
|
||||
|
||||
if (selectedCategoryIndex != UNSELECTED)
|
||||
{
|
||||
var eventsArray = _eventCategories[eventCategoriesKeyArray[selectedCategoryIndex]];
|
||||
|
||||
if (selectedEventIndex >= eventsArray.Length)
|
||||
selectedEventIndex = 0;
|
||||
|
||||
// Create a new rectangle to position the events dropdown and Add button.
|
||||
var selectedEventDropdownPosition = new Rect(position);
|
||||
|
||||
selectedEventDropdownPosition.y += EditorGUIUtility.singleLineHeight + 2;
|
||||
selectedEventDropdownPosition.width = position.width - (BUTTON_WIDTH + (int)WitStyles.TextButtonPadding);
|
||||
|
||||
selectedEventIndex = EditorGUI.Popup(selectedEventDropdownPosition, "Event", selectedEventIndex,
|
||||
eventsArray);
|
||||
|
||||
var selectedEventButtonPosition = new Rect(selectedEventDropdownPosition);
|
||||
|
||||
selectedEventButtonPosition.width = BUTTON_WIDTH;
|
||||
selectedEventButtonPosition.x =
|
||||
selectedEventDropdownPosition.x + selectedEventDropdownPosition.width + CONTROL_SPACING;
|
||||
|
||||
if (GUI.Button(selectedEventButtonPosition, "Add"))
|
||||
{
|
||||
var eventName = _eventCategories[eventCategoriesKeyArray[selectedCategoryIndex]][
|
||||
selectedEventIndex];
|
||||
|
||||
if (eventObject != null && selectedEventIndex != UNSELECTED &&
|
||||
!eventObject.IsCallbackOverridden(eventName))
|
||||
{
|
||||
var fieldName = GetFieldNameFromDisplay(eventName);
|
||||
if (eventObject.IsCallbackOverridden(fieldName))
|
||||
{
|
||||
eventObject.RemoveOverriddenCallback(fieldName);
|
||||
}
|
||||
fieldName = GetFieldNameFromDisplay(eventName).Substring(1);
|
||||
if (eventObject.IsCallbackOverridden(fieldName))
|
||||
{
|
||||
eventObject.RemoveOverriddenCallback(fieldName);
|
||||
}
|
||||
eventObject.RegisterOverriddenCallback(eventName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If any overrides have been added to the property, allow them to be edited
|
||||
if (eventObject != null && eventObject.OverriddenCallbacks.Count != 0)
|
||||
{
|
||||
var propertyRect = new Rect(position.x, position.y + propertyOffset, position.width, 0);
|
||||
|
||||
foreach (var callback in eventObject.OverriddenCallbacks)
|
||||
{
|
||||
var fieldProperty = GetPropertyFromDisplayFieldName(property, callback);
|
||||
if (fieldProperty == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
propertyRect.height = EditorGUI.GetPropertyHeight(fieldProperty, true);
|
||||
|
||||
EditorGUI.PropertyField(propertyRect, fieldProperty);
|
||||
|
||||
propertyRect.y += propertyRect.height + CONTROL_SPACING;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
private SerializedProperty GetPropertyFromDisplayFieldName(SerializedProperty property, string fieldName)
|
||||
{
|
||||
SerializedProperty result = property.FindPropertyRelative(fieldName);
|
||||
if (result == null)
|
||||
{
|
||||
string fieldName2 = GetFieldNameFromDisplay(fieldName);
|
||||
result = property.FindPropertyRelative(fieldName2);
|
||||
if (result == null)
|
||||
{
|
||||
Debug.LogError($"Could not find serialized property field: {fieldName} ({fieldName2})");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7a8ed72b9df46b794029f8801197ec8
|
||||
timeCreated: 1658431087
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Meta.WitAi.Events.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(VoiceEvents))]
|
||||
public class VoiceEventPropertyDrawer : EventPropertyDrawer<VoiceEvents>
|
||||
{
|
||||
/// <summary>
|
||||
/// Voice event diagram name
|
||||
/// </summary>
|
||||
public const string VOICE_EVENT_DIAGRAM_NAME = "VoiceEventsDiagram";
|
||||
/// <summary>
|
||||
/// Voice event tooltip
|
||||
/// </summary>
|
||||
public const string VOICE_EVENT_DIAGRAM_TOOLTIP = "Open " + VOICE_EVENT_DIAGRAM_NAME + ".pdf";
|
||||
|
||||
/// <summary>
|
||||
/// Open voice event pdf
|
||||
/// </summary>
|
||||
public override string DocumentationUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_documentationUrl == null)
|
||||
{
|
||||
string[] assetPaths = AssetDatabase.FindAssets(VOICE_EVENT_DIAGRAM_NAME);
|
||||
if (assetPaths == null || assetPaths.Length == 0)
|
||||
{
|
||||
_documentationUrl = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
string guid = assetPaths[0];
|
||||
string localPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
_documentationUrl = $"file://{Path.GetFullPath(localPath)}";
|
||||
}
|
||||
}
|
||||
return _documentationUrl;
|
||||
}
|
||||
}
|
||||
private static string _documentationUrl = null;
|
||||
|
||||
/// <summary>
|
||||
/// Voice pdf tooltip
|
||||
/// </summary>
|
||||
public override string DocumentationTooltip => VOICE_EVENT_DIAGRAM_TOOLTIP;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77caabce96000174bb6230dea05b47f0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using Meta.Voice;
|
||||
using Meta.WitAi.Configuration;
|
||||
using Meta.WitAi.Requests;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Inspectors
|
||||
{
|
||||
public class WitInspector : Editor
|
||||
{
|
||||
// Text invocation message
|
||||
private string _activationMessage;
|
||||
|
||||
// Target
|
||||
private IVoiceActivationHandler _activationHandler;
|
||||
private IVoiceEventProvider _eventProvider;
|
||||
|
||||
// Current service request
|
||||
private VoiceServiceRequest _request;
|
||||
|
||||
// Transcription data tracking
|
||||
private string _lastTranscription;
|
||||
|
||||
// Mic data tracking
|
||||
private float _micMin;
|
||||
private float _micMax;
|
||||
private float _micCurrent;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
// Ignore if not playing
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (target is IVoiceEventProvider)
|
||||
{
|
||||
_eventProvider = (IVoiceEventProvider) target;
|
||||
}
|
||||
if (target is IVoiceActivationHandler)
|
||||
{
|
||||
_activationHandler = (IVoiceActivationHandler) target;
|
||||
}
|
||||
if (_activationHandler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Header
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Label("Editor Requests", EditorStyles.boldLabel);
|
||||
|
||||
// Add activation button
|
||||
if (_request != null && _request.IsActive)
|
||||
{
|
||||
// Deactivates current target
|
||||
GUILayout.BeginHorizontal();
|
||||
if (_request.InputType == NLPRequestInputType.Audio && GUILayout.Button("Deactivate"))
|
||||
{
|
||||
_request.DeactivateAudio();
|
||||
}
|
||||
// Deactivate & abort
|
||||
if (GUILayout.Button("Deactivate & Abort"))
|
||||
{
|
||||
_request.Cancel("Deactivated");
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
// Current request state
|
||||
GUILayout.Label($"State: {_request.State}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Activates via voice
|
||||
if (GUILayout.Button("Activate"))
|
||||
{
|
||||
_request = _activationHandler.Activate(GetRequestOptions(), GetRequestEvents());
|
||||
}
|
||||
|
||||
// Activates via text
|
||||
GUILayout.BeginHorizontal();
|
||||
_activationMessage = GUILayout.TextField(_activationMessage);
|
||||
if (GUILayout.Button("Send", GUILayout.Width(50)))
|
||||
{
|
||||
_request = _activationHandler.Activate(_activationMessage, GetRequestOptions(), GetRequestEvents());
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// Transcription data
|
||||
GUILayout.Label("Last Transcription", EditorStyles.boldLabel);
|
||||
GUILayout.TextArea(_lastTranscription);
|
||||
|
||||
// Mic data
|
||||
GUILayout.Label("Mic Status", EditorStyles.boldLabel);
|
||||
GUILayout.Label($"Mic range: {_micMin.ToString("F5")} - {_micMax.ToString("F5")}");
|
||||
GUILayout.Label($"Mic current: {_micCurrent.ToString("F5")}");
|
||||
}
|
||||
|
||||
// Returns events
|
||||
private WitRequestOptions GetRequestOptions() => new WitRequestOptions();
|
||||
|
||||
// Return events
|
||||
private VoiceServiceRequestEvents GetRequestEvents()
|
||||
{
|
||||
VoiceServiceRequestEvents events = new VoiceServiceRequestEvents();
|
||||
events.OnInit.AddListener(OnRequestInit);
|
||||
events.OnPartialTranscription.AddListener(OnTranscriptionChanged);
|
||||
events.OnFullTranscription.AddListener(OnTranscriptionChanged);
|
||||
events.OnComplete.AddListener(OnRequestComplete);
|
||||
return events;
|
||||
}
|
||||
|
||||
// Setup during an activation
|
||||
private void OnRequestInit(VoiceServiceRequest request)
|
||||
{
|
||||
// Add events
|
||||
if (_eventProvider != null)
|
||||
{
|
||||
_eventProvider.VoiceEvents.OnMicLevelChanged.AddListener(OnMicLevelChanged);
|
||||
}
|
||||
|
||||
// Init mic data
|
||||
_micMin = Mathf.Infinity;
|
||||
_micMax = Mathf.NegativeInfinity;
|
||||
|
||||
// Start repaint on update
|
||||
EditorApplication.update += UpdateForRepaint;
|
||||
}
|
||||
|
||||
// Mic level updates
|
||||
private void OnMicLevelChanged(float volume)
|
||||
{
|
||||
_micCurrent = volume;
|
||||
_micMin = Mathf.Min(volume, _micMin);
|
||||
_micMax = Mathf.Max(volume, _micMax);
|
||||
}
|
||||
|
||||
// Transcription updates
|
||||
private void OnTranscriptionChanged(string transcription)
|
||||
{
|
||||
_lastTranscription = transcription;
|
||||
}
|
||||
|
||||
// Repaint
|
||||
private void UpdateForRepaint()
|
||||
{
|
||||
Repaint();
|
||||
}
|
||||
|
||||
// Request completed
|
||||
private void OnRequestComplete(VoiceServiceRequest request)
|
||||
{
|
||||
// Remove events
|
||||
if (_eventProvider != null)
|
||||
{
|
||||
_eventProvider.VoiceEvents.OnMicLevelChanged.RemoveListener(OnMicLevelChanged);
|
||||
}
|
||||
|
||||
// Stop repaint on update
|
||||
EditorApplication.update -= UpdateForRepaint;
|
||||
|
||||
// Remove request
|
||||
_request = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55ca91fb24174b4db43031a3ab4b0214
|
||||
timeCreated: 1626727432
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using UnityEditor;
|
||||
|
||||
namespace Meta.WitAi.Inspectors
|
||||
{
|
||||
[CustomEditor(typeof(WitService))]
|
||||
public class WitServiceInspector : WitInspector { }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9bf649b62b784cb8905a93125b8f754e
|
||||
timeCreated: 1648513941
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f4bf1d9c20d66943bc5dab13c5d8d58
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc134e9335ed3814184f8a12b011b172
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using Meta.WitAi.Lib;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Meta.WitAi.Lib
|
||||
{
|
||||
[CustomEditor(typeof(Mic))]
|
||||
public class MicEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
var mic = (Mic) target;
|
||||
|
||||
int index = EditorGUILayout.Popup("Input", mic.CurrentDeviceIndex, mic.Devices.ToArray());
|
||||
if (index != mic.CurrentDeviceIndex)
|
||||
{
|
||||
mic.ChangeDevice(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 342830ab77bbe9c47a0f68027cc80da4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1aae00c8b15744747a605c719bafd378
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Utilities
|
||||
{
|
||||
public static class AssetDatabaseUtility
|
||||
{
|
||||
// Find Unity asset
|
||||
public static T FindUnityAsset<T>(string filter) where T : UnityEngine.Object
|
||||
{
|
||||
T[] results = FindUnityAssets<T>(filter, true);
|
||||
if (results != null && results.Length > 0)
|
||||
{
|
||||
return results[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get all unity objects matching the name
|
||||
public static T[] FindUnityAssets<T>(string filter, bool ignoreAdditional = false)
|
||||
where T : UnityEngine.Object
|
||||
{
|
||||
List<T> results = new List<T>();
|
||||
string[] guids = AssetDatabase.FindAssets(filter);
|
||||
if (guids != null && guids.Length > 0)
|
||||
{
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
T asset = AssetDatabase.LoadAssetAtPath<T>(assetPath);
|
||||
if (asset != null && !results.Contains(asset))
|
||||
{
|
||||
results.Add(asset);
|
||||
if (ignoreAdditional)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
// Gets the absolute string path of the asset(s) with the matching name
|
||||
public static string[] FindUnityAssetPath(string filter, bool ignoreAdditional = false)
|
||||
{
|
||||
var relativePaths = AssetDatabase.FindAssets(filter);
|
||||
char d = Path.DirectorySeparatorChar;
|
||||
|
||||
List<string> results = new List<string>();
|
||||
foreach (var relPath in relativePaths)
|
||||
{
|
||||
results.Add($"{Application.dataPath}{d}..{d}{AssetDatabase.GUIDToAssetPath(relPath)}");
|
||||
if (ignoreAdditional)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d247ae64c6547e4282a35e0b6b17b6f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Meta.Conduit.Editor;
|
||||
using Meta.Voice.TelemetryUtilities;
|
||||
using Meta.WitAi.Data.Configuration;
|
||||
using Meta.WitAi.Utilities;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the Conduit manifest generation.
|
||||
/// </summary>
|
||||
public class ConduitManifestGenerationManager: IPreprocessBuildWithReport
|
||||
{
|
||||
/// <summary>
|
||||
/// The priority for preprocess build callback.
|
||||
/// </summary>
|
||||
public int callbackOrder => 0;
|
||||
|
||||
/// <summary>
|
||||
/// The assembly miner.
|
||||
/// </summary>
|
||||
private static readonly AssemblyMiner AssemblyMiner = new AssemblyMiner(new WitParameterValidator());
|
||||
|
||||
/// <summary>
|
||||
/// Maps individual configurations to their associated managers. This is needed to allow static resolution
|
||||
/// on global events like building or running.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, ConduitManifestGenerationManager> ConfigurationToManagerMap =
|
||||
new Dictionary<string, ConduitManifestGenerationManager>();
|
||||
|
||||
/// <summary>
|
||||
/// Locally collected Conduit statistics.
|
||||
/// </summary>
|
||||
private static ConduitStatistics _statistics;
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if code had changed since last manifest generation.
|
||||
/// We start with this set to true to handle changes when the editor is not running.
|
||||
/// </summary>
|
||||
private static bool _codeChanged = true;
|
||||
|
||||
/// <summary>
|
||||
/// The manifest generator used for this configuration.
|
||||
/// </summary>
|
||||
private readonly ManifestGenerator _manifestGenerator;
|
||||
|
||||
/// <summary>
|
||||
/// True when a manifest exists locally for this configuration.
|
||||
/// </summary>
|
||||
public bool ManifestAvailable { get; private set; }= false;
|
||||
|
||||
/// <summary>
|
||||
/// The assembly walker associated with this configuration.
|
||||
/// </summary>
|
||||
internal AssemblyWalker AssemblyWalker { get; private set; } = new AssemblyWalker();
|
||||
|
||||
/// <summary>
|
||||
/// Locally collected Conduit statistics.
|
||||
/// </summary>
|
||||
private static ConduitStatistics Statistics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_statistics == null)
|
||||
{
|
||||
_statistics = new ConduitStatistics(new PersistenceLayer());
|
||||
}
|
||||
return _statistics;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory method that creates a manager for the configuration if none exists. Otherwise, creates a new one.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration.</param>
|
||||
/// <returns>An instance of this class.</returns>
|
||||
public static ConduitManifestGenerationManager GetInstance(WitConfiguration configuration)
|
||||
{
|
||||
// This key has to match what we set in the constructor.
|
||||
var configurationKey = configuration.name;
|
||||
if (!ConfigurationToManagerMap.ContainsKey(configurationKey))
|
||||
{
|
||||
ConfigurationToManagerMap[configurationKey] = new ConduitManifestGenerationManager(configuration);
|
||||
}
|
||||
|
||||
ConfigurationToManagerMap[configurationKey].GenerateManifestIfNeeded(configuration);
|
||||
|
||||
return ConfigurationToManagerMap[configurationKey];
|
||||
}
|
||||
|
||||
static ConduitManifestGenerationManager()
|
||||
{
|
||||
EditorApplication.playModeStateChanged += OnPlayModeChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This default constructor is intended to be used by Unity only. Do not call it directly.
|
||||
/// </summary>
|
||||
public ConduitManifestGenerationManager()
|
||||
{
|
||||
}
|
||||
|
||||
private ConduitManifestGenerationManager(WitConfiguration configuration)
|
||||
{
|
||||
_manifestGenerator = new ManifestGenerator(AssemblyWalker, AssemblyMiner);
|
||||
ConfigurationToManagerMap[configuration.name] = this;
|
||||
}
|
||||
|
||||
public void OnPreprocessBuild(BuildReport report)
|
||||
{
|
||||
if (_codeChanged)
|
||||
{
|
||||
GenerateAllManifests();
|
||||
}
|
||||
else
|
||||
{
|
||||
GenerateMissingManifests();
|
||||
}
|
||||
}
|
||||
|
||||
[UnityEditor.Callbacks.DidReloadScripts]
|
||||
private static void OnScriptsReloaded()
|
||||
{
|
||||
_codeChanged = true;
|
||||
}
|
||||
|
||||
private static void OnPlayModeChanged(PlayModeStateChange state)
|
||||
{
|
||||
if (state != PlayModeStateChange.EnteredPlayMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_codeChanged)
|
||||
{
|
||||
GenerateAllManifests();
|
||||
}
|
||||
else
|
||||
{
|
||||
GenerateMissingManifests();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PersistStatistics()
|
||||
{
|
||||
Statistics.Persist();
|
||||
}
|
||||
|
||||
private static void GenerateMissingManifests()
|
||||
{
|
||||
foreach (var configuration in WitConfigurationUtility.GetLoadedConfigurations())
|
||||
{
|
||||
if (configuration == null || !configuration.useConduit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var manager = GetInstance(configuration);
|
||||
manager.GenerateManifest(configuration, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateAllManifests()
|
||||
{
|
||||
foreach (var configuration in WitConfigurationUtility.GetLoadedConfigurations())
|
||||
{
|
||||
if (configuration != null && configuration.useConduit)
|
||||
{
|
||||
var manager = GetInstance(configuration);
|
||||
manager.GenerateManifest(configuration, false);
|
||||
}
|
||||
}
|
||||
|
||||
_codeChanged = false;
|
||||
}
|
||||
|
||||
public List<string> ExtractManifestData()
|
||||
{
|
||||
return _manifestGenerator.ExtractManifestData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a manifest with empty entities and actions lists.
|
||||
/// </summary>
|
||||
/// <param name="domain">A friendly name to use for this app.</param>
|
||||
/// <param name="id">The App ID.</param>
|
||||
/// <returns>A JSON representation of the empty manifest.</returns>
|
||||
public string GenerateEmptyManifest(string domain, string id)
|
||||
{
|
||||
return _manifestGenerator.GenerateEmptyManifest(domain, id);
|
||||
}
|
||||
|
||||
private void GenerateManifestIfNeeded(WitConfiguration configuration)
|
||||
{
|
||||
if (!configuration.useConduit || configuration == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get full manifest path & ensure it exists
|
||||
var manifestPath = configuration.GetManifestEditorPath();
|
||||
ManifestAvailable = File.Exists(manifestPath);
|
||||
|
||||
// Auto-generate manifest
|
||||
if (!ManifestAvailable)
|
||||
{
|
||||
GenerateManifest(configuration, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetManifestFullPath(WitConfiguration configuration, bool shouldCreateDirectoryIfNotExist = false)
|
||||
{
|
||||
string directory = Application.dataPath + "/Oculus/Voice/Resources";
|
||||
if (shouldCreateDirectoryIfNotExist)
|
||||
{
|
||||
IOUtility.CreateDirectory(directory, true);
|
||||
}
|
||||
return directory + "/" + configuration.ManifestLocalPath;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Generates a manifest and optionally opens it in the editor.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration that we are generating the manifest for.</param>
|
||||
/// <param name="openManifest">If true, will open the manifest file in the code editor.</param>
|
||||
public void GenerateManifest(WitConfiguration configuration, bool openManifest)
|
||||
{
|
||||
var instanceKey = Telemetry.StartEvent(Telemetry.TelemetryEventId.GenerateManifest);
|
||||
AssemblyWalker.AssembliesToIgnore = new HashSet<string>(configuration.excludedAssemblies);
|
||||
|
||||
// Generate
|
||||
var startGenerationTime = DateTime.UtcNow;
|
||||
var appInfo = configuration.GetApplicationInfo();
|
||||
var manifest = _manifestGenerator.GenerateManifest(appInfo.name, appInfo.id);
|
||||
var endGenerationTime = DateTime.UtcNow;
|
||||
|
||||
// Get file path
|
||||
var fullPath = configuration.GetManifestEditorPath();
|
||||
if (string.IsNullOrEmpty(fullPath) || !File.Exists(fullPath))
|
||||
{
|
||||
fullPath = GetManifestFullPath(configuration, true);
|
||||
}
|
||||
|
||||
// Write to file
|
||||
try
|
||||
{
|
||||
var writer = new StreamWriter(fullPath);
|
||||
writer.NewLine = "\n";
|
||||
writer.WriteLine(manifest);
|
||||
writer.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
VLog.E($"Conduit manifest failed to generate\nPath: {fullPath}\n{e}");
|
||||
Telemetry.EndEventWithFailure(instanceKey, e.Message);
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var incompatibleSignatures = string.Join(" ", AssemblyMiner.IncompatibleSignatureFrequency.Keys);
|
||||
Telemetry.AnnotateEvent(instanceKey, Telemetry.AnnotationKey.IncompatibleSignatures, incompatibleSignatures);
|
||||
|
||||
var compatibleSignatures = string.Join(" ", AssemblyMiner.SignatureFrequency.Keys);
|
||||
Telemetry.AnnotateEvent(instanceKey, Telemetry.AnnotationKey.CompatibleSignatures, compatibleSignatures);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
VLog.W($"Failed to collect signature telemetry. Exception: {e}");
|
||||
}
|
||||
|
||||
|
||||
Telemetry.EndEvent(instanceKey, Telemetry.ResultType.Success);
|
||||
Statistics.SuccessfulGenerations++;
|
||||
Statistics.AddFrequencies(AssemblyMiner.SignatureFrequency);
|
||||
Statistics.AddIncompatibleFrequencies(AssemblyMiner.IncompatibleSignatureFrequency);
|
||||
var generationTime = endGenerationTime - startGenerationTime;
|
||||
var unityPath = fullPath.Replace(Application.dataPath, "Assets");
|
||||
AssetDatabase.ImportAsset(unityPath);
|
||||
ManifestAvailable = true;
|
||||
|
||||
var configName = configuration.name;
|
||||
var manifestName = Path.GetFileNameWithoutExtension(unityPath);
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
var configPath = AssetDatabase.GetAssetPath(configuration);
|
||||
configName = $"<a href=\"{configPath}\">{configName}</a>";
|
||||
manifestName = $"<a href=\"{unityPath}\">{manifestName}</a>";
|
||||
#endif
|
||||
VLog.D($"Conduit manifest generated\nConfiguration: {configName}\nManifest: {manifestName}\nGeneration Time: {generationTime.TotalMilliseconds} ms");
|
||||
|
||||
if (openManifest)
|
||||
{
|
||||
UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(fullPath, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 440fa12149634e98aee13b1ef38d530a
|
||||
timeCreated: 1685991879
|
||||
@@ -0,0 +1,714 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Meta.WitAi.CallbackHandlers;
|
||||
using Meta.WitAi.Configuration;
|
||||
using Meta.WitAi.Data;
|
||||
using Meta.WitAi.Json;
|
||||
using Meta.WitAi.Requests;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
public class WitUnderstandingViewer : WitConfigurationWindow
|
||||
{
|
||||
[FormerlySerializedAs("witHeader")] [SerializeField] private Texture2D _witHeader;
|
||||
[FormerlySerializedAs("responseText")] [SerializeField] private string _responseText;
|
||||
private string _utterance;
|
||||
private WitResponseNode _response;
|
||||
private Dictionary<string, bool> _foldouts;
|
||||
|
||||
// Current service
|
||||
private VoiceService[] _services;
|
||||
private string[] _serviceNames;
|
||||
private int _currentService = -1;
|
||||
public VoiceService service => _services != null && _currentService >= 0 && _currentService < _services.Length ? _services[_currentService] : null;
|
||||
public bool HasWit => service != null;
|
||||
|
||||
private DateTime _submitStart;
|
||||
private TimeSpan _requestLength;
|
||||
private string _status;
|
||||
private int _responseCode;
|
||||
private VoiceServiceRequest _request;
|
||||
private int _savePopup;
|
||||
private GUIStyle _hamburgerButton;
|
||||
|
||||
private enum HamburgerMenu
|
||||
{
|
||||
None = -1,
|
||||
Save = 0,
|
||||
CopyToClipboard = 1,
|
||||
CopyRequestID = 2
|
||||
}
|
||||
|
||||
private string[] HambergerMenuStrings = new string[]
|
||||
{
|
||||
"Save", "Copy to Clipboard", "Copy Request ID"
|
||||
};
|
||||
|
||||
class Content
|
||||
{
|
||||
public static GUIContent CopyPath;
|
||||
public static GUIContent CopyCode;
|
||||
public static GUIContent CreateStringValue;
|
||||
public static GUIContent CreateIntValue;
|
||||
public static GUIContent CreateFloatValue;
|
||||
|
||||
static Content()
|
||||
{
|
||||
CreateStringValue = new GUIContent("Create Value Reference/Create String");
|
||||
CreateIntValue = new GUIContent("Create Value Reference/Create Int");
|
||||
CreateFloatValue = new GUIContent("Create Value Reference/Create Float");
|
||||
|
||||
CopyPath = new GUIContent("Copy Path to Clipboard");
|
||||
CopyCode = new GUIContent("Copy Code to Clipboard");
|
||||
}
|
||||
}
|
||||
|
||||
protected override GUIContent Title => WitTexts.UnderstandingTitleContent;
|
||||
protected override WitTexts.WitAppEndpointType HeaderEndpointType => WitTexts.WitAppEndpointType.Understanding;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
RefreshVoiceServices();
|
||||
if (!string.IsNullOrEmpty(_responseText))
|
||||
{
|
||||
_response = WitResponseNode.Parse(_responseText);
|
||||
}
|
||||
_status = WitTexts.Texts.UnderstandingViewerPromptLabel;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
private void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
if (state == PlayModeStateChange.EnteredPlayMode && !HasWit)
|
||||
{
|
||||
RefreshVoiceServices();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSelectionChange()
|
||||
{
|
||||
if (Selection.activeGameObject)
|
||||
{
|
||||
SetVoiceService(Selection.activeGameObject.GetComponent<VoiceService>());
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetStartTime()
|
||||
{
|
||||
_submitStart = System.DateTime.Now;
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void OnSend(VoiceServiceRequest request)
|
||||
{
|
||||
_request = request;
|
||||
ResetStartTime();
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void ShowTranscription(string transcription)
|
||||
{
|
||||
_utterance = transcription;
|
||||
Repaint();
|
||||
}
|
||||
|
||||
// On gui
|
||||
protected override void OnGUI()
|
||||
{
|
||||
base.OnGUI();
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
WitEditorUI.LayoutStatusLabel(_status);
|
||||
GUILayout.BeginVertical(GUILayout.Width(24));
|
||||
GUILayout.Space(4);
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(4);
|
||||
var rect = GUILayoutUtility.GetLastRect();
|
||||
|
||||
if (null == _hamburgerButton)
|
||||
{
|
||||
// GUI.skin must be called from OnGUI
|
||||
_hamburgerButton = new GUIStyle(GUI.skin.GetStyle("PaneOptions"));
|
||||
_hamburgerButton.imagePosition = ImagePosition.ImageOnly;
|
||||
}
|
||||
|
||||
var value = (HamburgerMenu) EditorGUILayout.Popup(-1, HambergerMenuStrings, _hamburgerButton, GUILayout.Width(24));
|
||||
switch (value)
|
||||
{
|
||||
case HamburgerMenu.Save:
|
||||
{
|
||||
var path = EditorUtility.SaveFilePanel("Save Response Json", Application.dataPath,
|
||||
"result", "json");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
File.WriteAllText(path, _response.ToString());
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case HamburgerMenu.CopyToClipboard:
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = _response?.ToString() ?? _responseText;
|
||||
break;
|
||||
}
|
||||
case HamburgerMenu.CopyRequestID:
|
||||
{
|
||||
var requestId = _request?.Options?.RequestId;
|
||||
if (!string.IsNullOrEmpty(requestId))
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = requestId;
|
||||
_status = $"{requestId} copied to clipboard.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_status = "No request id to copy!";
|
||||
}
|
||||
Repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.EndVertical();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
protected override void LayoutContent()
|
||||
{
|
||||
// Get service
|
||||
VoiceService voiceService = null;
|
||||
|
||||
// Runtime Mode
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
// Refresh services
|
||||
if (_services == null)
|
||||
{
|
||||
RefreshVoiceServices();
|
||||
}
|
||||
// Services missing
|
||||
if (_services == null || _serviceNames == null || _services.Length == 0)
|
||||
{
|
||||
WitEditorUI.LayoutErrorLabel(WitTexts.Texts.UnderstandingViewerMissingServicesLabel);
|
||||
return;
|
||||
}
|
||||
// Voice service select
|
||||
int newService = _currentService;
|
||||
bool serviceUpdate = false;
|
||||
GUILayout.BeginHorizontal();
|
||||
// Clamp
|
||||
if (newService < 0 || newService >= _services.Length)
|
||||
{
|
||||
newService = 0;
|
||||
serviceUpdate = true;
|
||||
}
|
||||
// Layout
|
||||
WitEditorUI.LayoutPopup(WitTexts.Texts.UnderstandingViewerServicesLabel, _serviceNames, ref newService, ref serviceUpdate);
|
||||
// Update
|
||||
if (serviceUpdate)
|
||||
{
|
||||
SetVoiceService(newService);
|
||||
}
|
||||
// Select
|
||||
if (_currentService >= 0 && _currentService < _services.Length && WitEditorUI.LayoutTextButton(WitTexts.Texts.UnderstandingViewerSelectLabel))
|
||||
{
|
||||
Selection.activeObject = _services[_currentService];
|
||||
}
|
||||
// Refresh
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.ConfigurationRefreshButtonLabel))
|
||||
{
|
||||
RefreshVoiceServices();
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
// Ensure service exists
|
||||
voiceService = service;
|
||||
}
|
||||
// Editor Only
|
||||
else
|
||||
{
|
||||
// Configuration select
|
||||
base.LayoutContent();
|
||||
// Ensure configuration exists
|
||||
if (!witConfiguration)
|
||||
{
|
||||
WitEditorUI.LayoutErrorLabel(WitTexts.Texts.UnderstandingViewerMissingConfigLabel);
|
||||
return;
|
||||
}
|
||||
// Check client access token
|
||||
string clientAccessToken = witConfiguration.GetClientAccessToken();
|
||||
if (string.IsNullOrEmpty(clientAccessToken))
|
||||
{
|
||||
WitEditorUI.LayoutErrorLabel(WitTexts.Texts.UnderstandingViewerMissingClientTokenLabel);
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.UnderstandingViewerSettingsButtonLabel))
|
||||
{
|
||||
Selection.activeObject = witConfiguration;
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if input is allowed
|
||||
bool allowInput = !Application.isPlaying || (service != null && !service.Active);
|
||||
GUI.enabled = allowInput;
|
||||
|
||||
// Utterance field
|
||||
bool updated = false;
|
||||
WitEditorUI.LayoutTextField(new GUIContent(WitTexts.Texts.UnderstandingViewerUtteranceLabel), ref _utterance, ref updated);
|
||||
|
||||
// Begin Buttons
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
// Submit utterance
|
||||
if (allowInput && WitEditorUI.LayoutTextButton(WitTexts.Texts.UnderstandingViewerSubmitButtonLabel))
|
||||
{
|
||||
_responseText = "";
|
||||
if (!string.IsNullOrEmpty(_utterance))
|
||||
{
|
||||
SubmitUtterance();
|
||||
}
|
||||
else
|
||||
{
|
||||
_response = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Service buttons
|
||||
GUI.enabled = true;
|
||||
if (EditorApplication.isPlaying && voiceService)
|
||||
{
|
||||
if (!voiceService.Active)
|
||||
{
|
||||
// Activate
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.UnderstandingViewerActivateButtonLabel))
|
||||
{
|
||||
_request = voiceService.Activate(new VoiceServiceRequestEvents());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deactivate
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.UnderstandingViewerDeactivateButtonLabel))
|
||||
{
|
||||
voiceService.Deactivate();
|
||||
}
|
||||
// Abort
|
||||
if (WitEditorUI.LayoutTextButton(WitTexts.Texts.UnderstandingViewerAbortButtonLabel))
|
||||
{
|
||||
voiceService.DeactivateAndAbortRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
// Results
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
if (_response != null)
|
||||
{
|
||||
DrawResponse();
|
||||
}
|
||||
else if (voiceService && voiceService.MicActive)
|
||||
{
|
||||
WitEditorUI.LayoutWrapLabel(WitTexts.Texts.UnderstandingViewerListeningLabel);
|
||||
}
|
||||
else if (voiceService && voiceService.IsRequestActive)
|
||||
{
|
||||
WitEditorUI.LayoutWrapLabel(WitTexts.Texts.UnderstandingViewerLoadingLabel);
|
||||
}
|
||||
else if (string.IsNullOrEmpty(_responseText))
|
||||
{
|
||||
WitEditorUI.LayoutWrapLabel(WitTexts.Texts.UnderstandingViewerPromptLabel);
|
||||
}
|
||||
else
|
||||
{
|
||||
WitEditorUI.LayoutWrapLabel(_responseText);
|
||||
}
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void SubmitUtterance()
|
||||
{
|
||||
// Remove response
|
||||
_response = null;
|
||||
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
if (service)
|
||||
{
|
||||
_status = WitTexts.Texts.UnderstandingViewerListeningLabel;
|
||||
_responseText = _status;
|
||||
_request = service.Activate(_utterance, new VoiceServiceRequestEvents());
|
||||
// Hack to watch for loading to complete. Response does not
|
||||
// come back on the main thread so Repaint in onResponse in
|
||||
// the editor does nothing.
|
||||
EditorApplication.update += WatchForWitResponse;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_status = WitTexts.Texts.UnderstandingViewerLoadingLabel;
|
||||
_responseText = _status;
|
||||
_submitStart = System.DateTime.Now;
|
||||
_request = witConfiguration.CreateMessageRequest(new WitRequestOptions(), new VoiceServiceRequestEvents());
|
||||
_request.Options.Text = _utterance;
|
||||
_request.Events.OnSend.AddListener(OnSend);
|
||||
_request.Events.OnComplete.AddListener(OnComplete);
|
||||
_request.Send();
|
||||
}
|
||||
}
|
||||
|
||||
private void WatchForWitResponse()
|
||||
{
|
||||
if (service && !service.Active)
|
||||
{
|
||||
Repaint();
|
||||
EditorApplication.update -= WatchForWitResponse;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnComplete(VoiceServiceRequest request)
|
||||
{
|
||||
_responseCode = request.StatusCode;
|
||||
if (null != request.ResponseData)
|
||||
{
|
||||
ShowResponse(request.ResponseData, false);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(request.Results.Message))
|
||||
{
|
||||
_responseText = request.Results.Message;
|
||||
}
|
||||
else
|
||||
{
|
||||
_responseText = "No response. Status: " + request.StatusCode;
|
||||
}
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void ShowResponse(WitResponseNode r, bool isPartial)
|
||||
{
|
||||
_response = r;
|
||||
_responseText = _response.ToString();
|
||||
_requestLength = DateTime.Now - _submitStart;
|
||||
_status = $"{(isPartial ? "Partial" : "Full")}Response time: {_requestLength}";
|
||||
}
|
||||
|
||||
private void DrawResponse()
|
||||
{
|
||||
DrawResponseNode(_response);
|
||||
}
|
||||
|
||||
private void DrawResponseNode(WitResponseNode witResponseNode, string path = "")
|
||||
{
|
||||
if (null == witResponseNode?.AsObject) return;
|
||||
|
||||
if(string.IsNullOrEmpty(path)) DrawNode(witResponseNode["text"], "text", path);
|
||||
|
||||
var names = witResponseNode.AsObject.ChildNodeNames;
|
||||
Array.Sort(names);
|
||||
foreach (string child in names)
|
||||
{
|
||||
if (!(string.IsNullOrEmpty(path) && child == "text"))
|
||||
{
|
||||
var childNode = witResponseNode[child];
|
||||
DrawNode(childNode, child, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawNode(WitResponseNode childNode, string child, string path, bool isArrayElement = false)
|
||||
{
|
||||
if (childNode == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
string childPath;
|
||||
|
||||
if (path.Length > 0)
|
||||
{
|
||||
childPath = isArrayElement ? $"{path}[{child}]" : $"{path}.{child}";
|
||||
}
|
||||
else
|
||||
{
|
||||
childPath = child;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(childNode.Value))
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(15 * EditorGUI.indentLevel);
|
||||
if (GUILayout.Button($"{child} = {childNode.Value}", WitStyles.LabelWrap))
|
||||
{
|
||||
ShowNodeMenu(childNode, childPath);
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
else
|
||||
{
|
||||
var childObject = childNode.AsObject;
|
||||
var childArray = childNode.AsArray;
|
||||
|
||||
if ((null != childObject || null != childArray) && Foldout(childPath, child))
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
if (null != childObject)
|
||||
{
|
||||
DrawResponseNode(childNode, childPath);
|
||||
}
|
||||
|
||||
if (null != childArray)
|
||||
{
|
||||
DrawArray(childArray, childPath);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowNodeMenu(WitResponseNode node, string path)
|
||||
{
|
||||
GenericMenu menu = new GenericMenu();
|
||||
menu.AddItem(Content.CreateStringValue, false, () => WitDataCreation.CreateStringValue(path));
|
||||
menu.AddItem(Content.CreateIntValue, false, () => WitDataCreation.CreateIntValue(path));
|
||||
menu.AddItem(Content.CreateFloatValue, false, () => WitDataCreation.CreateFloatValue(path));
|
||||
menu.AddSeparator("");
|
||||
menu.AddItem(Content.CopyPath, false, () =>
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = path;
|
||||
});
|
||||
menu.AddItem(Content.CopyCode, false, () =>
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = WitResultUtilities.GetCodeFromPath(path);
|
||||
});
|
||||
|
||||
if (Selection.activeGameObject)
|
||||
{
|
||||
menu.AddSeparator("");
|
||||
|
||||
var label =
|
||||
new GUIContent($"Add response matcher to {Selection.activeObject.name}");
|
||||
|
||||
menu.AddItem(label, false, () =>
|
||||
{
|
||||
var valueHandler = Selection.activeGameObject.AddComponent<WitResponseMatcher>();
|
||||
valueHandler.intent = _response.GetIntentName();
|
||||
valueHandler.valueMatchers = new ValuePathMatcher[]
|
||||
{
|
||||
new ValuePathMatcher() { path = path }
|
||||
};
|
||||
});
|
||||
|
||||
AddMultiValueUpdateItems(path, menu);
|
||||
}
|
||||
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
private void AddMultiValueUpdateItems(string path, GenericMenu menu)
|
||||
{
|
||||
|
||||
string name = path;
|
||||
int index = path.LastIndexOf('.');
|
||||
if (index > 0)
|
||||
{
|
||||
name = name.Substring(index + 1);
|
||||
}
|
||||
|
||||
var mvhs = Selection.activeGameObject.GetComponents<WitResponseMatcher>();
|
||||
if (mvhs.Length > 1)
|
||||
{
|
||||
for (int i = 0; i < mvhs.Length; i++)
|
||||
{
|
||||
var handler = mvhs[i];
|
||||
menu.AddItem(
|
||||
new GUIContent($"Add {name} matcher to {Selection.activeGameObject.name}/Handler {(i + 1)}"),
|
||||
false, (h) => AddNewEventHandlerPath((WitResponseMatcher) h, path), handler);
|
||||
}
|
||||
}
|
||||
else if (mvhs.Length == 1)
|
||||
{
|
||||
var handler = mvhs[0];
|
||||
menu.AddItem(
|
||||
new GUIContent($"Add {name} matcher to {Selection.activeGameObject.name}'s Response Matcher"),
|
||||
false, (h) => AddNewEventHandlerPath((WitResponseMatcher) h, path), handler);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddNewEventHandlerPath(WitResponseMatcher handler, string path)
|
||||
{
|
||||
Array.Resize(ref handler.valueMatchers, handler.valueMatchers.Length + 1);
|
||||
handler.valueMatchers[handler.valueMatchers.Length - 1] = new ValuePathMatcher()
|
||||
{
|
||||
path = path
|
||||
};
|
||||
}
|
||||
|
||||
private void DrawArray(WitResponseArray childArray, string childPath)
|
||||
{
|
||||
for (int i = 0; i < childArray.Count; i++)
|
||||
{
|
||||
DrawNode(childArray[i], i.ToString(), childPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
private bool Foldout(string path, string label)
|
||||
{
|
||||
if (null == _foldouts) _foldouts = new Dictionary<string, bool>();
|
||||
if (!_foldouts.TryGetValue(path, out var state))
|
||||
{
|
||||
state = false;
|
||||
_foldouts[path] = state;
|
||||
}
|
||||
|
||||
var newState = EditorGUILayout.Foldout(state, label);
|
||||
if (newState != state)
|
||||
{
|
||||
_foldouts[path] = newState;
|
||||
}
|
||||
|
||||
return newState;
|
||||
}
|
||||
|
||||
#region SERVICES
|
||||
// Refresh voice services
|
||||
protected void RefreshVoiceServices()
|
||||
{
|
||||
// Remove previous service
|
||||
VoiceService previous = service;
|
||||
SetVoiceService(-1);
|
||||
|
||||
// Get all services
|
||||
VoiceService[] services = Resources.FindObjectsOfTypeAll<VoiceService>();
|
||||
|
||||
// Get unique services
|
||||
List<GameObject> serviceGOs = new List<GameObject>();
|
||||
List<VoiceService> serviceList = new List<VoiceService>();
|
||||
foreach (var s in services)
|
||||
{
|
||||
// Add unique gameobjects
|
||||
GameObject serviceGO = s.gameObject;
|
||||
if (serviceGO.scene.rootCount > 0 && !serviceGOs.Contains(serviceGO))
|
||||
{
|
||||
serviceGOs.Add(serviceGO);
|
||||
serviceList.Add(serviceGO.GetComponent<VoiceService>());
|
||||
}
|
||||
}
|
||||
|
||||
// Get service gameobject names
|
||||
_services = serviceList.ToArray();
|
||||
_serviceNames = new string[_services.Length];
|
||||
for (int i = 0; i < _services.Length; i++)
|
||||
{
|
||||
_serviceNames[i] = GetVoiceServiceName(_services[i]);
|
||||
}
|
||||
|
||||
// Set as first found
|
||||
if (previous == null)
|
||||
{
|
||||
SetVoiceService(0);
|
||||
}
|
||||
// Set as previous
|
||||
else
|
||||
{
|
||||
SetVoiceService(previous);
|
||||
}
|
||||
}
|
||||
// Get voice service name
|
||||
private string GetVoiceServiceName(VoiceService service)
|
||||
{
|
||||
IWitRuntimeConfigProvider configProvider = service.GetComponent<IWitRuntimeConfigProvider>();
|
||||
if (configProvider != null && configProvider.RuntimeConfiguration != null && configProvider.RuntimeConfiguration.witConfiguration != null)
|
||||
{
|
||||
return $"{configProvider.RuntimeConfiguration.witConfiguration.name} [{service.gameObject.name}]";
|
||||
}
|
||||
return service.gameObject.name;
|
||||
}
|
||||
// Set voice service
|
||||
protected void SetVoiceService(VoiceService newService)
|
||||
{
|
||||
// Cannot set without services
|
||||
if (_services == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Find & apply
|
||||
int newServiceIndex = Array.FindIndex(_services, (s) => s == newService);
|
||||
|
||||
// Apply
|
||||
SetVoiceService(newServiceIndex);
|
||||
}
|
||||
// Set
|
||||
protected void SetVoiceService(int newServiceIndex)
|
||||
{
|
||||
// Cannot set without services
|
||||
if (_services == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove listeners to current service
|
||||
RemoveVoiceListeners(service);
|
||||
|
||||
// Get current index
|
||||
_currentService = newServiceIndex;
|
||||
|
||||
// Add listeners to current service
|
||||
AddVoiceListeners(service);
|
||||
}
|
||||
// Add listeners
|
||||
private void AddVoiceListeners(VoiceService voiceService)
|
||||
{
|
||||
// Ignore
|
||||
if (voiceService == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Add delegates
|
||||
voiceService.VoiceEvents.OnSend.AddListener(OnSend);
|
||||
voiceService.VoiceEvents.OnComplete.AddListener(OnComplete);
|
||||
voiceService.VoiceEvents.OnPartialTranscription.AddListener(ShowTranscription);
|
||||
voiceService.VoiceEvents.OnFullTranscription.AddListener(ShowTranscription);
|
||||
voiceService.VoiceEvents.OnStoppedListening.AddListener(ResetStartTime);
|
||||
}
|
||||
// Remove listeners
|
||||
private void RemoveVoiceListeners(VoiceService voiceService)
|
||||
{
|
||||
// Ignore
|
||||
if (voiceService == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Remove delegates
|
||||
voiceService.VoiceEvents.OnSend.RemoveListener(OnSend);
|
||||
voiceService.VoiceEvents.OnComplete.RemoveListener(OnComplete);
|
||||
voiceService.VoiceEvents.OnFullTranscription.RemoveListener(ShowTranscription);
|
||||
voiceService.VoiceEvents.OnPartialTranscription.RemoveListener(ShowTranscription);
|
||||
voiceService.VoiceEvents.OnStoppedListening.RemoveListener(ResetStartTime);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18eb340e3f39b0a4f8f9e9749e97f9b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Meta.WitAi.Events;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// This class provides a common API for accessing properties and methods of the various *Service classes
|
||||
/// used in the Understanding Viewer. In order to add support for a new Service type, derive a child
|
||||
/// class from this one and provide implementations for the getter methods.
|
||||
/// </summary>
|
||||
public abstract class WitUnderstandingViewerServiceAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// The base Component/Service class this object wraps.
|
||||
/// Child classes will provide a properly-cast reference to the component in their implementation.
|
||||
/// </summary>
|
||||
private MonoBehaviour _serviceComponent;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the service. Gotten once and cached for future use.
|
||||
/// Child classes may override the base implementation if necessary.
|
||||
/// </summary>
|
||||
private String _serviceName;
|
||||
|
||||
/// <summary>
|
||||
/// Flags to indicate whether or not the component supports voice and/or text activation.
|
||||
/// </summary>
|
||||
protected bool _hasVoiceActivation;
|
||||
protected bool _hasTextActivation;
|
||||
|
||||
/// <summary>
|
||||
/// This flag dictates whether or not the service should send a network request as part of its
|
||||
/// (de)activation handling.
|
||||
/// </summary>
|
||||
protected bool _shouldSubmitUtterance;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="serviceComponent">The Service Component (VoiceService, DictationService, etc.
|
||||
/// this API will wrap.</param>
|
||||
public WitUnderstandingViewerServiceAPI(MonoBehaviour serviceComponent)
|
||||
{
|
||||
_serviceComponent = serviceComponent;
|
||||
}
|
||||
|
||||
public MonoBehaviour ServiceComponent
|
||||
{
|
||||
get => _serviceComponent;
|
||||
}
|
||||
|
||||
public bool HasVoiceActivation
|
||||
{
|
||||
get => _hasVoiceActivation;
|
||||
}
|
||||
|
||||
public bool HasTextActivation
|
||||
{
|
||||
get => _hasTextActivation;
|
||||
}
|
||||
|
||||
public bool ShouldSubmitUtterance
|
||||
{
|
||||
get => _shouldSubmitUtterance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Most services have a common way of querying their service name. For those that don't,
|
||||
/// override this method. The name is cached after first query.
|
||||
/// </summary>
|
||||
public virtual string ServiceName {
|
||||
get
|
||||
{
|
||||
// Has the service name been cached to the local variable yet?
|
||||
if (_serviceName == null)
|
||||
{
|
||||
if (_serviceComponent == null)
|
||||
return "";
|
||||
|
||||
var configProvider = _serviceComponent.GetComponent<IWitRuntimeConfigProvider>();
|
||||
|
||||
if (configProvider != null)
|
||||
{
|
||||
// If no Witconfig is set for the component we get a NullPointerException here
|
||||
if (configProvider.RuntimeConfiguration.witConfiguration == null)
|
||||
{
|
||||
VLog.E($"No Wit configuration found for {_serviceComponent.gameObject.name}");
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
_serviceName =
|
||||
$"{configProvider.RuntimeConfiguration.witConfiguration.name} [{_serviceComponent.gameObject.name}]";
|
||||
}
|
||||
else
|
||||
{
|
||||
_serviceName = _serviceComponent.name;
|
||||
}
|
||||
}
|
||||
|
||||
return _serviceName;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract bool Active { get; }
|
||||
|
||||
public abstract bool MicActive { get; }
|
||||
|
||||
public abstract bool IsRequestActive { get; }
|
||||
|
||||
// API methods - override these to provide functionality
|
||||
public abstract void Activate();
|
||||
|
||||
public abstract void Activate(string text);
|
||||
|
||||
public abstract void Deactivate();
|
||||
|
||||
public abstract void DeactivateAndAbortRequest();
|
||||
|
||||
// Event Callback Registration
|
||||
public abstract VoiceServiceRequestEvent OnSend { get; }
|
||||
public abstract WitTranscriptionEvent OnPartialTranscription { get; }
|
||||
public abstract WitTranscriptionEvent OnFullTranscription { get; }
|
||||
public abstract UnityEvent OnStoppedListening { get; }
|
||||
public abstract VoiceServiceRequestEvent OnComplete { get; }
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b05455360ebd3644ebe86cbb40446615
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
public static class WitUnderstandingViewerServiceApiFactory
|
||||
{
|
||||
public delegate WitUnderstandingViewerServiceAPI Create(MonoBehaviour m);
|
||||
|
||||
private static Dictionary<string, Create> factoryMethods = new Dictionary<string, Create>();
|
||||
|
||||
public static void Register(string interfaceName, Create method)
|
||||
{
|
||||
factoryMethods.Add(interfaceName, method);
|
||||
}
|
||||
|
||||
public static WitUnderstandingViewerServiceAPI CreateWrapper(MonoBehaviour service)
|
||||
{
|
||||
foreach (var interfaceType in service.GetType().GetInterfaces())
|
||||
{
|
||||
if (factoryMethods.ContainsKey(interfaceType.Name))
|
||||
{
|
||||
return factoryMethods[interfaceType.Name](service);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fcd6b77ae500a7b43923e35d15cc5144
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using Meta.WitAi.Events;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class WitUnderstandingViewerVoiceServiceAPI : WitUnderstandingViewerServiceAPI
|
||||
{
|
||||
private VoiceService _service;
|
||||
|
||||
static WitUnderstandingViewerVoiceServiceAPI()
|
||||
{
|
||||
WitUnderstandingViewerServiceApiFactory.Register("IVoiceService", CreateApiWrapper);
|
||||
}
|
||||
|
||||
public WitUnderstandingViewerVoiceServiceAPI(VoiceService service) : base(service)
|
||||
{
|
||||
_service = service;
|
||||
|
||||
_hasVoiceActivation = true;
|
||||
_hasTextActivation = true;
|
||||
_shouldSubmitUtterance = true;
|
||||
}
|
||||
|
||||
public override bool Active
|
||||
{
|
||||
get => _service.Active;
|
||||
}
|
||||
|
||||
public override bool MicActive
|
||||
{
|
||||
get => _service.MicActive;
|
||||
}
|
||||
|
||||
public override bool IsRequestActive
|
||||
{
|
||||
get => _service.IsRequestActive;
|
||||
}
|
||||
|
||||
public override void Activate()
|
||||
{
|
||||
_service.Activate();
|
||||
}
|
||||
|
||||
public override void Activate(string text)
|
||||
{
|
||||
_service.Activate(text);
|
||||
}
|
||||
|
||||
public override void Deactivate()
|
||||
{
|
||||
_service.Deactivate();
|
||||
}
|
||||
|
||||
public override void DeactivateAndAbortRequest()
|
||||
{
|
||||
_service.DeactivateAndAbortRequest();
|
||||
}
|
||||
|
||||
public override VoiceServiceRequestEvent OnSend
|
||||
{
|
||||
get => _service.VoiceEvents.OnSend;
|
||||
}
|
||||
|
||||
public override WitTranscriptionEvent OnPartialTranscription
|
||||
{
|
||||
get => _service.VoiceEvents.OnPartialTranscription;
|
||||
}
|
||||
|
||||
public override WitTranscriptionEvent OnFullTranscription
|
||||
{
|
||||
get => _service.VoiceEvents.OnFullTranscription;
|
||||
}
|
||||
|
||||
public override UnityEvent OnStoppedListening
|
||||
{
|
||||
get => _service.VoiceEvents.OnStoppedListening;
|
||||
}
|
||||
|
||||
public override VoiceServiceRequestEvent OnComplete
|
||||
{
|
||||
get => _service.VoiceEvents.OnComplete;
|
||||
}
|
||||
|
||||
public static WitUnderstandingViewerServiceAPI CreateApiWrapper(MonoBehaviour service)
|
||||
{
|
||||
return new WitUnderstandingViewerVoiceServiceAPI((VoiceService)service);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd3a9e82a16233040a917414603b56f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 238ea3e4fd8c0934d914485b43977e1f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b85d9061b83ffc449be84c9b95e52f7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Windows.Components
|
||||
{
|
||||
public static class WitMultiSelectionPopup
|
||||
{
|
||||
public static void Show(IList<string> options, HashSet<string> disabledOptions, Action<IList<string>> callback) {
|
||||
// TODO It should be a rect of a button which triggers this popup, so the popup is shown next to that button.
|
||||
Rect parentRect = new Rect(0, 0, 50, 50);
|
||||
WitMultiSelectionPopupContent content = new WitMultiSelectionPopupContent(options, disabledOptions, callback);
|
||||
PopupWindow.Show(parentRect, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b64f2d401365d47218d23cd6e1295d63
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Windows.Components
|
||||
{
|
||||
public class WitMultiSelectionPopupContent: PopupWindowContent
|
||||
{
|
||||
private Dictionary<string, bool> options;
|
||||
private Action<IList<string>> callback;
|
||||
|
||||
private const float WINDOW_WIDTH = 400f;
|
||||
|
||||
public WitMultiSelectionPopupContent(IList<string> options, HashSet<string> disabledOptions, Action<IList<string>> callback)
|
||||
{
|
||||
this.options = new Dictionary<string, bool>();
|
||||
this.callback = callback;
|
||||
|
||||
options.ToList().ForEach(optName => this.options[optName] = !disabledOptions.Contains(optName));
|
||||
}
|
||||
|
||||
public override Vector2 GetWindowSize()
|
||||
{
|
||||
var lineHeight = 20;
|
||||
var height = 25 + (options.Count() * lineHeight);
|
||||
return new Vector2(WINDOW_WIDTH, height);
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect rect)
|
||||
{
|
||||
var initialLabelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = WINDOW_WIDTH - 30;
|
||||
|
||||
GUILayout.Label("Assemblies to include in the generated Manifest", EditorStyles.boldLabel);
|
||||
var keys = new List<string>(options.Keys);
|
||||
foreach (var optName in keys) {
|
||||
options[optName] = EditorGUILayout.Toggle(optName, options[optName], WitStyles.Toggle);
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = initialLabelWidth;
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
var deselectedValues = this.options.Keys.Where(optName => false == this.options[optName]).ToList();
|
||||
callback(deselectedValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b720c5fa963394864bd7ed8ef330d0bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
public class FieldGUI
|
||||
{
|
||||
// Base type
|
||||
public Type baseType { get; private set; }
|
||||
// Fields
|
||||
public FieldInfo[] fields { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom gui layout callback, returns true if field is
|
||||
/// </summary>
|
||||
public Func<FieldInfo, bool> onCustomGuiLayout;
|
||||
|
||||
/// <summary>
|
||||
/// Custom gui layout callback, returns true if field is
|
||||
/// </summary>
|
||||
public Action onAdditionalGuiLayout;
|
||||
|
||||
// Refresh field list
|
||||
public void RefreshFields(Type newBaseType)
|
||||
{
|
||||
// Set base type
|
||||
baseType = newBaseType;
|
||||
|
||||
// Obtain all public, instance fields
|
||||
fields = GetFields(baseType);
|
||||
}
|
||||
|
||||
// Obtain all public, instance fields
|
||||
public static FieldInfo[] GetFields(Type newBaseType, Comparison<FieldInfo> customSort = null)
|
||||
{
|
||||
// Results
|
||||
FieldInfo[] results = newBaseType.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
// Sort parent class fields to top
|
||||
Comparison<FieldInfo> sort = customSort ?? ((f1, f2) =>
|
||||
{
|
||||
if (f1.DeclaringType != f2.DeclaringType)
|
||||
{
|
||||
if (f1.DeclaringType == newBaseType)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (f2.DeclaringType == newBaseType)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Sort
|
||||
Array.Sort(results, sort);
|
||||
|
||||
// Return results
|
||||
return results;
|
||||
}
|
||||
|
||||
// Gui Layout
|
||||
public void OnGuiLayout(SerializedObject serializedObject)
|
||||
{
|
||||
// Ignore without object
|
||||
if (serializedObject == null || serializedObject.targetObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Attempt a setup if needed
|
||||
Type desType = serializedObject.targetObject.GetType();
|
||||
if (baseType != desType || fields == null)
|
||||
{
|
||||
RefreshFields(desType);
|
||||
}
|
||||
// Ignore
|
||||
if (fields == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Iterate all fields
|
||||
foreach (var field in fields)
|
||||
{
|
||||
// Custom handle
|
||||
if (onCustomGuiLayout != null && onCustomGuiLayout(field))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Default layout
|
||||
var property = serializedObject.FindProperty(field.Name);
|
||||
EditorGUILayout.PropertyField(property);
|
||||
}
|
||||
|
||||
// Additional items
|
||||
onAdditionalGuiLayout?.Invoke();
|
||||
|
||||
// Apply
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c6c2ebe0a6e80f4fa83611a03e7fecd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e6781ff766e1a740ab27299b2e559ae
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Meta.WitAi.CallbackHandlers;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ConfidenceRange))]
|
||||
public class ConfidenceRangeDrawer : WitPropertyDrawer
|
||||
{
|
||||
private Vector2 fieldScroll;
|
||||
private bool showOutsideConfidence;
|
||||
|
||||
private Dictionary<SerializedProperty, bool> eventFoldouts =
|
||||
new Dictionary<SerializedProperty, bool>();
|
||||
|
||||
private float GetEventContentsHeight(SerializedProperty property)
|
||||
{
|
||||
var height = EditorGUIUtility.singleLineHeight;
|
||||
var trigger = property.FindPropertyRelative("onWithinConfidenceRange");
|
||||
if (trigger.isExpanded)
|
||||
{
|
||||
height += EditorGUI.GetPropertyHeight(trigger);
|
||||
if (showOutsideConfidence)
|
||||
{
|
||||
trigger = property.FindPropertyRelative("onOutsideConfidenceRange");
|
||||
height += EditorGUI.GetPropertyHeight(trigger);
|
||||
}
|
||||
|
||||
height += EditorGUIUtility.singleLineHeight * 1.5f;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var height = EditorGUIUtility.singleLineHeight * 4;
|
||||
height += GetEventContentsHeight(property);
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
var rect = position;
|
||||
rect.height = EditorGUIUtility.singleLineHeight;
|
||||
var minConfidence = property.FindPropertyRelative("minConfidence");
|
||||
var maxConfidence = property.FindPropertyRelative("maxConfidence");
|
||||
var minVal = minConfidence.floatValue;
|
||||
var maxVal = maxConfidence.floatValue;
|
||||
EditorGUI.MinMaxSlider(rect, ref minVal, ref maxVal, 0, 1);
|
||||
rect.y += EditorGUIUtility.singleLineHeight;
|
||||
|
||||
|
||||
var minRect = new Rect(rect);
|
||||
minRect.width = Mathf.Min(position.width / 2.0f - 4, 75f);
|
||||
|
||||
EditorGUI.TextField(minRect, minVal.ToString());
|
||||
|
||||
var maxRect = new Rect(minRect);
|
||||
maxRect.xMin = position.xMax - maxRect.width;
|
||||
maxRect.xMax = position.xMax;
|
||||
EditorGUI.TextField(maxRect, maxVal.ToString());
|
||||
|
||||
rect.y += EditorGUIUtility.singleLineHeight * 1.5f;
|
||||
|
||||
minConfidence.floatValue = minVal;
|
||||
maxConfidence.floatValue = maxVal;
|
||||
|
||||
var eventRect = new Rect(rect);
|
||||
eventRect.height = GetEventContentsHeight(property);
|
||||
EditorGUI.DrawRect(eventRect, Color.gray);
|
||||
rect.xMin += 16;
|
||||
rect.width = rect.xMax - rect.xMin - 16;
|
||||
var trigger = property.FindPropertyRelative("onWithinConfidenceRange");
|
||||
trigger.isExpanded = EditorGUI.Foldout(rect, trigger.isExpanded, "Events");
|
||||
rect.y += EditorGUIUtility.singleLineHeight;
|
||||
if (trigger.isExpanded)
|
||||
{
|
||||
rect.height = EditorGUI.GetPropertyHeight(trigger);
|
||||
EditorGUI.PropertyField(rect, trigger);
|
||||
rect.y += rect.height;
|
||||
rect.height = EditorGUIUtility.singleLineHeight;
|
||||
showOutsideConfidence = EditorGUI.Foldout(rect, showOutsideConfidence,
|
||||
"Outside Confidence Range Triggers");
|
||||
rect.y += EditorGUIUtility.singleLineHeight;
|
||||
if (showOutsideConfidence)
|
||||
{
|
||||
trigger = property.FindPropertyRelative("onOutsideConfidenceRange");
|
||||
rect.height = EditorGUI.GetPropertyHeight(trigger);
|
||||
EditorGUI.PropertyField(rect, trigger);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6225499212e66974991865e4777c77ab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
public class WitApplicationPropertyDrawer : WitPropertyDrawer
|
||||
{
|
||||
// Whether to use a foldout
|
||||
protected override bool FoldoutEnabled => false;
|
||||
// Use name value for title if possible
|
||||
protected override string GetLocalizedText(SerializedProperty property, string key)
|
||||
{
|
||||
// Determine by ids
|
||||
switch (key)
|
||||
{
|
||||
case LocalizedTitleKey:
|
||||
return WitTexts.Texts.ConfigurationApplicationTabLabel;
|
||||
case LocalizedMissingKey:
|
||||
return WitTexts.Texts.ConfigurationApplicationMissingLabel;
|
||||
case "name":
|
||||
return WitTexts.Texts.ConfigurationApplicationNameLabel;
|
||||
case "id":
|
||||
return WitTexts.Texts.ConfigurationApplicationIdLabel;
|
||||
case "lang":
|
||||
return WitTexts.Texts.ConfigurationApplicationLanguageLabel;
|
||||
case "isPrivate":
|
||||
return WitTexts.Texts.ConfigurationApplicationPrivateLabel;
|
||||
case "createdAt":
|
||||
return WitTexts.Texts.ConfigurationApplicationCreatedLabel;
|
||||
case "trainingStatus":
|
||||
return WitTexts.Texts.ConfigurationApplicationTrainingStatus;
|
||||
case "lastTrainDuration":
|
||||
return WitTexts.Texts.ConfigurationApplicationTrainingLastDuration;
|
||||
case "lastTrainedAt":
|
||||
return WitTexts.Texts.ConfigurationApplicationTrainingLast;
|
||||
case "nextTrainAt":
|
||||
return WitTexts.Texts.ConfigurationApplicationTrainingNext;
|
||||
}
|
||||
|
||||
// Default to base
|
||||
return base.GetLocalizedText(property, key);
|
||||
}
|
||||
// Skip wit configuration field
|
||||
protected override bool ShouldLayoutField(SerializedProperty property, FieldInfo subfield)
|
||||
{
|
||||
switch (subfield.Name)
|
||||
{
|
||||
case "intents":
|
||||
case "entities":
|
||||
case "traits":
|
||||
case "voices":
|
||||
return false;
|
||||
}
|
||||
return base.ShouldLayoutField(property, subfield);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abf5ee4c48cd9b646ada260f9bf23b3d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
using Meta.WitAi.Data.Configuration;
|
||||
using Meta.WitAi.Data.Info;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(WitEntityInfo))]
|
||||
public class WitEntityPropertyDrawer : WitPropertyDrawer
|
||||
{
|
||||
// Use name value for title if possible
|
||||
protected override string GetLocalizedText(SerializedProperty property, string key)
|
||||
{
|
||||
// Determine by ids
|
||||
switch (key)
|
||||
{
|
||||
case LocalizedTitleKey:
|
||||
string title = GetFieldStringValue(property, "name");
|
||||
if (!string.IsNullOrEmpty(title))
|
||||
{
|
||||
return title;
|
||||
}
|
||||
break;
|
||||
case "id":
|
||||
return WitTexts.Texts.ConfigurationEntitiesIdLabel;
|
||||
case "lookups":
|
||||
return WitTexts.Texts.ConfigurationEntitiesLookupsLabel;
|
||||
case "roles":
|
||||
return WitTexts.Texts.ConfigurationEntitiesRolesLabel;
|
||||
case "keywords":
|
||||
return WitTexts.Texts.ConfigurationEntitiesKeywordsLabel;
|
||||
}
|
||||
|
||||
// Default to base
|
||||
return base.GetLocalizedText(property, key);
|
||||
}
|
||||
// Determine if should layout field
|
||||
protected override bool ShouldLayoutField(SerializedProperty property, FieldInfo subfield)
|
||||
{
|
||||
switch (subfield.Name)
|
||||
{
|
||||
case "name":
|
||||
return false;
|
||||
}
|
||||
return base.ShouldLayoutField(property, subfield);
|
||||
}
|
||||
|
||||
protected override void OnDrawLabelInline(SerializedProperty property)
|
||||
{
|
||||
var configuration = property.serializedObject.targetObject as WitConfiguration;
|
||||
if (configuration == null || !configuration.useConduit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var assemblyWalker = ConduitManifestGenerationManager.GetInstance(configuration).AssemblyWalker;
|
||||
if (assemblyWalker == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var entityName = property.displayName;
|
||||
|
||||
if (WitEditorUI.LayoutIconButton(EditorGUIUtility.IconContent("UxmlScript Icon")))
|
||||
{
|
||||
var manifest = ManifestLoader.LoadManifest(configuration.ManifestLocalPath);
|
||||
var sourceCodeFile = CodeMapper.GetSourceFilePathFromTypeName(entityName, manifest, assemblyWalker);
|
||||
|
||||
if (string.IsNullOrEmpty(sourceCodeFile))
|
||||
{
|
||||
VLog.W($"Failed to local source code for {entityName}");
|
||||
return;
|
||||
}
|
||||
|
||||
UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(sourceCodeFile, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 005e6c58c9128dd4e8a1f14f07ce0fc8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using UnityEditor;
|
||||
using Meta.WitAi.Data.Info;
|
||||
|
||||
namespace Meta.WitAi.Windows
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(WitEntityRoleInfo))]
|
||||
public class WitEntityRolePropertyDrawer : WitSimplePropertyDrawer
|
||||
{
|
||||
// Key = Name
|
||||
protected override string GetKeyFieldName()
|
||||
{
|
||||
return "name";
|
||||
}
|
||||
// Value = ID
|
||||
protected override string GetValueFieldName()
|
||||
{
|
||||
return "id";
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8fe3908d473555449a5fed7799862a3
|
||||
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