-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
KeywordManager.cs
137 lines (121 loc) · 5.1 KB
/
KeywordManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Windows.Speech;
namespace HoloToolkit.Unity.InputModule
{
/// <summary>
/// KeywordManager allows you to specify keywords and methods in the Unity
/// Inspector, instead of registering them explicitly in code.
/// This also includes a setting to either automatically start the
/// keyword recognizer or allow your code to start it.
///
/// IMPORTANT: Please make sure to add the microphone capability in your app, in Unity under
/// Edit -> Project Settings -> Player -> Settings for Windows Store -> Publishing Settings -> Capabilities
/// or in your Visual Studio Package.appxmanifest capabilities.
/// </summary>
public partial class KeywordManager : MonoBehaviour
{
[System.Serializable]
public struct KeywordAndResponse
{
[Tooltip("The keyword to recognize.")]
public string Keyword;
[Tooltip("The KeyCode to recognize.")]
public KeyCode KeyCode;
[Tooltip("The UnityEvent to be invoked when the keyword is recognized.")]
public UnityEvent Response;
}
// This enumeration gives the manager two different ways to handle the recognizer. Both will
// set up the recognizer and add all keywords. The first causes the recognizer to start
// immediately. The second allows the recognizer to be manually started at a later time.
public enum RecognizerStartBehavior { AutoStart, ManualStart };
[Tooltip("An enumeration to set whether the recognizer should start on or off.")]
public RecognizerStartBehavior RecognizerStart;
[Tooltip("An array of string keywords and UnityEvents, to be set in the Inspector.")]
public KeywordAndResponse[] KeywordsAndResponses;
private KeywordRecognizer keywordRecognizer;
private Dictionary<string, UnityEvent> responses;
void Start()
{
if (KeywordsAndResponses.Length > 0)
{
// Convert the struct array into a dictionary, with the keywords and the keys and the methods as the values.
// This helps easily link the keyword recognized to the UnityEvent to be invoked.
responses = KeywordsAndResponses.ToDictionary(keywordAndResponse => keywordAndResponse.Keyword,
keywordAndResponse => keywordAndResponse.Response);
keywordRecognizer = new KeywordRecognizer(responses.Keys.ToArray());
keywordRecognizer.OnPhraseRecognized += KeywordRecognizer_OnPhraseRecognized;
if (RecognizerStart == RecognizerStartBehavior.AutoStart)
{
keywordRecognizer.Start();
}
}
else
{
Debug.LogError("Must have at least one keyword specified in the Inspector on " + gameObject.name + ".");
}
}
void Update()
{
if (keywordRecognizer.IsRunning)
{
ProcessKeyBindings();
}
}
void OnDestroy()
{
if (keywordRecognizer != null)
{
StopKeywordRecognizer();
keywordRecognizer.OnPhraseRecognized -= KeywordRecognizer_OnPhraseRecognized;
keywordRecognizer.Dispose();
}
}
private void ProcessKeyBindings()
{
foreach (var kvp in KeywordsAndResponses)
{
if (Input.GetKeyDown(kvp.KeyCode))
{
kvp.Response.Invoke();
return;
}
}
}
private void KeywordRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args)
{
UnityEvent keywordResponse;
// Check to make sure the recognized keyword exists in the methods dictionary, then invoke the corresponding method.
if (responses.TryGetValue(args.text, out keywordResponse))
{
keywordResponse.Invoke();
}
}
/// <summary>
/// Make sure the keyword recognizer is off, then start it.
/// Otherwise, leave it alone because it's already in the desired state.
/// </summary>
public void StartKeywordRecognizer()
{
if (keywordRecognizer != null && !keywordRecognizer.IsRunning)
{
keywordRecognizer.Start();
}
}
/// <summary>
/// Make sure the keyword recognizer is on, then stop it.
/// Otherwise, leave it alone because it's already in the desired state.
/// </summary>
public void StopKeywordRecognizer()
{
if (keywordRecognizer != null && keywordRecognizer.IsRunning)
{
keywordRecognizer.Stop();
}
}
}
}