1
1
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2
2
// See the LICENCE file in the repository root for full licence text.
3
3
4
+ using System ;
5
+ using System . Collections . Generic ;
4
6
using System . Linq ;
5
7
using osu . Framework . Allocation ;
6
8
using osu . Framework . Audio ;
@@ -40,30 +42,27 @@ public class OsuTextBox : BasicTextBox
40
42
Margin = new MarginPadding { Left = 2 } ,
41
43
} ;
42
44
43
- private readonly Sample ? [ ] textAddedSamples = new Sample [ 4 ] ;
44
- private Sample ? capsTextAddedSample ;
45
- private Sample ? textRemovedSample ;
46
- private Sample ? textCommittedSample ;
47
- private Sample ? caretMovedSample ;
48
-
49
- private Sample ? selectCharSample ;
50
- private Sample ? selectWordSample ;
51
- private Sample ? selectAllSample ;
52
- private Sample ? deselectSample ;
53
-
54
45
private OsuCaret ? caret ;
55
46
56
47
private bool selectionStarted ;
57
48
private double sampleLastPlaybackTime ;
58
49
59
- private enum SelectionSampleType
50
+ private enum FeedbackSampleType
60
51
{
61
- Character ,
62
- Word ,
63
- All ,
52
+ TextAdd ,
53
+ TextAddCaps ,
54
+ TextRemove ,
55
+ TextConfirm ,
56
+ TextInvalid ,
57
+ CaretMove ,
58
+ SelectCharacter ,
59
+ SelectWord ,
60
+ SelectAll ,
64
61
Deselect
65
62
}
66
63
64
+ private Dictionary < FeedbackSampleType , Sample ? [ ] > sampleMap = new Dictionary < FeedbackSampleType , Sample ? [ ] > ( ) ;
65
+
67
66
public OsuTextBox ( )
68
67
{
69
68
Height = 40 ;
@@ -87,18 +86,23 @@ private void load(OverlayColourProvider? colourProvider, OsuColour colour, Audio
87
86
88
87
Placeholder . Colour = colourProvider ? . Foreground1 ?? new Color4 ( 180 , 180 , 180 , 255 ) ;
89
88
89
+ var textAddedSamples = new Sample ? [ 4 ] ;
90
90
for ( int i = 0 ; i < textAddedSamples . Length ; i ++ )
91
91
textAddedSamples [ i ] = audio . Samples . Get ( $@ "Keyboard/key-press-{ 1 + i } ") ;
92
92
93
- capsTextAddedSample = audio . Samples . Get ( @"Keyboard/key-caps" ) ;
94
- textRemovedSample = audio . Samples . Get ( @"Keyboard/key-delete" ) ;
95
- textCommittedSample = audio . Samples . Get ( @"Keyboard/key-confirm" ) ;
96
- caretMovedSample = audio . Samples . Get ( @"Keyboard/key-movement" ) ;
97
-
98
- selectCharSample = audio . Samples . Get ( @"Keyboard/select-char" ) ;
99
- selectWordSample = audio . Samples . Get ( @"Keyboard/select-word" ) ;
100
- selectAllSample = audio . Samples . Get ( @"Keyboard/select-all" ) ;
101
- deselectSample = audio . Samples . Get ( @"Keyboard/deselect" ) ;
93
+ sampleMap = new Dictionary < FeedbackSampleType , Sample ? [ ] >
94
+ {
95
+ { FeedbackSampleType . TextAdd , textAddedSamples } ,
96
+ { FeedbackSampleType . TextAddCaps , new [ ] { audio . Samples . Get ( @"Keyboard/key-caps" ) } } ,
97
+ { FeedbackSampleType . TextRemove , new [ ] { audio . Samples . Get ( @"Keyboard/key-delete" ) } } ,
98
+ { FeedbackSampleType . TextConfirm , new [ ] { audio . Samples . Get ( @"Keyboard/key-confirm" ) } } ,
99
+ { FeedbackSampleType . TextInvalid , new [ ] { audio . Samples . Get ( @"Keyboard/key-invalid" ) } } ,
100
+ { FeedbackSampleType . CaretMove , new [ ] { audio . Samples . Get ( @"Keyboard/key-movement" ) } } ,
101
+ { FeedbackSampleType . SelectCharacter , new [ ] { audio . Samples . Get ( @"Keyboard/select-char" ) } } ,
102
+ { FeedbackSampleType . SelectWord , new [ ] { audio . Samples . Get ( @"Keyboard/select-word" ) } } ,
103
+ { FeedbackSampleType . SelectAll , new [ ] { audio . Samples . Get ( @"Keyboard/select-all" ) } } ,
104
+ { FeedbackSampleType . Deselect , new [ ] { audio . Samples . Get ( @"Keyboard/deselect" ) } }
105
+ } ;
102
106
}
103
107
104
108
private Color4 selectionColour ;
@@ -109,32 +113,42 @@ protected override void OnUserTextAdded(string added)
109
113
{
110
114
base . OnUserTextAdded ( added ) ;
111
115
116
+ if ( ! added . Any ( CanAddCharacter ) )
117
+ return ;
118
+
112
119
if ( added . Any ( char . IsUpper ) && AllowUniqueCharacterSamples )
113
- capsTextAddedSample ? . Play ( ) ;
120
+ playSample ( FeedbackSampleType . TextAddCaps ) ;
114
121
else
115
- playTextAddedSample ( ) ;
122
+ playSample ( FeedbackSampleType . TextAdd ) ;
116
123
}
117
124
118
125
protected override void OnUserTextRemoved ( string removed )
119
126
{
120
127
base . OnUserTextRemoved ( removed ) ;
121
128
122
- textRemovedSample ? . Play ( ) ;
129
+ playSample ( FeedbackSampleType . TextRemove ) ;
130
+ }
131
+
132
+ protected override void NotifyInputError ( )
133
+ {
134
+ base . NotifyInputError ( ) ;
135
+
136
+ playSample ( FeedbackSampleType . TextInvalid ) ;
123
137
}
124
138
125
139
protected override void OnTextCommitted ( bool textChanged )
126
140
{
127
141
base . OnTextCommitted ( textChanged ) ;
128
142
129
- textCommittedSample ? . Play ( ) ;
143
+ playSample ( FeedbackSampleType . TextConfirm ) ;
130
144
}
131
145
132
146
protected override void OnCaretMoved ( bool selecting )
133
147
{
134
148
base . OnCaretMoved ( selecting ) ;
135
149
136
150
if ( ! selecting )
137
- caretMovedSample ? . Play ( ) ;
151
+ playSample ( FeedbackSampleType . CaretMove ) ;
138
152
}
139
153
140
154
protected override void OnTextSelectionChanged ( TextSelectionType selectionType )
@@ -144,15 +158,15 @@ protected override void OnTextSelectionChanged(TextSelectionType selectionType)
144
158
switch ( selectionType )
145
159
{
146
160
case TextSelectionType . Character :
147
- playSelectSample ( SelectionSampleType . Character ) ;
161
+ playSample ( FeedbackSampleType . SelectCharacter ) ;
148
162
break ;
149
163
150
164
case TextSelectionType . Word :
151
- playSelectSample ( selectionStarted ? SelectionSampleType . Character : SelectionSampleType . Word ) ;
165
+ playSample ( selectionStarted ? FeedbackSampleType . SelectCharacter : FeedbackSampleType . SelectWord ) ;
152
166
break ;
153
167
154
168
case TextSelectionType . All :
155
- playSelectSample ( SelectionSampleType . All ) ;
169
+ playSample ( FeedbackSampleType . SelectAll ) ;
156
170
break ;
157
171
}
158
172
@@ -165,7 +179,7 @@ protected override void OnTextDeselected()
165
179
166
180
if ( ! selectionStarted ) return ;
167
181
168
- playSelectSample ( SelectionSampleType . Deselect ) ;
182
+ playSample ( FeedbackSampleType . Deselect ) ;
169
183
170
184
selectionStarted = false ;
171
185
}
@@ -184,36 +198,36 @@ protected override void OnImeComposition(string newComposition, int removedTextL
184
198
185
199
case 1 :
186
200
// composition probably ended by pressing backspace, or was cancelled.
187
- textRemovedSample ? . Play ( ) ;
201
+ playSample ( FeedbackSampleType . TextRemove ) ;
188
202
return ;
189
203
190
204
default :
191
205
// longer text removed, composition ended because it was cancelled.
192
206
// could be a different sample if desired.
193
- textRemovedSample ? . Play ( ) ;
207
+ playSample ( FeedbackSampleType . TextRemove ) ;
194
208
return ;
195
209
}
196
210
}
197
211
198
212
if ( addedTextLength > 0 )
199
213
{
200
214
// some text was added, probably due to typing new text or by changing the candidate.
201
- playTextAddedSample ( ) ;
215
+ playSample ( FeedbackSampleType . TextAdd ) ;
202
216
return ;
203
217
}
204
218
205
219
if ( removedTextLength > 0 )
206
220
{
207
221
// text was probably removed by backspacing.
208
222
// it's also possible that a candidate that only removed text was changed to.
209
- textRemovedSample ? . Play ( ) ;
223
+ playSample ( FeedbackSampleType . TextRemove ) ;
210
224
return ;
211
225
}
212
226
213
227
if ( caretMoved )
214
228
{
215
229
// only the caret/selection was moved.
216
- caretMovedSample ? . Play ( ) ;
230
+ playSample ( FeedbackSampleType . CaretMove ) ;
217
231
}
218
232
}
219
233
@@ -224,13 +238,13 @@ protected override void OnImeResult(string result, bool successful)
224
238
if ( successful )
225
239
{
226
240
// composition was successfully completed, usually by pressing the enter key.
227
- textCommittedSample ? . Play ( ) ;
241
+ playSample ( FeedbackSampleType . TextConfirm ) ;
228
242
}
229
243
else
230
244
{
231
245
// composition was prematurely ended, eg. by clicking inside the textbox.
232
246
// could be a different sample if desired.
233
- textCommittedSample ? . Play ( ) ;
247
+ playSample ( FeedbackSampleType . TextConfirm ) ;
234
248
}
235
249
}
236
250
@@ -259,43 +273,35 @@ protected override void OnFocusLost(FocusLostEvent e)
259
273
SelectionColour = SelectionColour ,
260
274
} ;
261
275
262
- private void playSelectSample ( SelectionSampleType selectionType )
276
+ private SampleChannel ? getSampleChannel ( FeedbackSampleType feedbackSampleType )
263
277
{
264
- if ( Time . Current < sampleLastPlaybackTime + 15 ) return ;
265
-
266
- SampleChannel ? channel ;
267
- double pitch = 0.98 + RNG . NextDouble ( 0.04 ) ;
278
+ var samples = sampleMap [ feedbackSampleType ] ;
268
279
269
- switch ( selectionType )
270
- {
271
- case SelectionSampleType . All :
272
- channel = selectAllSample ? . GetChannel ( ) ;
273
- break ;
280
+ if ( samples == null || samples . Length == 0 )
281
+ return null ;
274
282
275
- case SelectionSampleType . Word :
276
- channel = selectWordSample ? . GetChannel ( ) ;
277
- break ;
283
+ return samples [ RNG . Next ( 0 , samples . Length ) ] ? . GetChannel ( ) ;
284
+ }
278
285
279
- case SelectionSampleType . Deselect :
280
- channel = deselectSample ? . GetChannel ( ) ;
281
- break ;
286
+ private void playSample ( FeedbackSampleType feedbackSample )
287
+ {
288
+ if ( Time . Current < sampleLastPlaybackTime + 15 ) return ;
282
289
283
- default :
284
- channel = selectCharSample ? . GetChannel ( ) ;
285
- pitch += ( SelectedText . Length / ( double ) Text . Length ) * 0.15f ;
286
- break ;
287
- }
290
+ SampleChannel ? channel = getSampleChannel ( feedbackSample ) ;
288
291
289
292
if ( channel == null ) return ;
290
293
294
+ double pitch = 0.98 + RNG . NextDouble ( 0.04 ) ;
295
+
296
+ if ( feedbackSample == FeedbackSampleType . SelectCharacter )
297
+ pitch += ( ( double ) SelectedText . Length / Math . Max ( 1 , Text . Length ) ) * 0.15f ;
298
+
291
299
channel . Frequency . Value = pitch ;
292
300
channel . Play ( ) ;
293
301
294
302
sampleLastPlaybackTime = Time . Current ;
295
303
}
296
304
297
- private void playTextAddedSample ( ) => textAddedSamples [ RNG . Next ( 0 , textAddedSamples . Length ) ] ? . Play ( ) ;
298
-
299
305
private class OsuCaret : Caret
300
306
{
301
307
private const float caret_move_time = 60 ;
0 commit comments