• R/O
  • HTTP
  • SSH
  • HTTPS

CsWin10Desktop3: Commit

Visual C# 7.0, Windows10 Desktop App


Commit MetaInfo

Revisiond675368ece4bc5049286ba08317dcf9d6a9e6835 (tree)
Time2017-01-09 20:38:12
Authorくまかみ工房 <kumakamikoubou@gmai...>
Commiterくまかみ工房

Log Message

Merge branch 'ドラム入力の実装' into develop

Change Summary

Incremental Difference

--- /dev/null
+++ b/FDK24/DTXPlay.bat
@@ -0,0 +1,2 @@
1+echo off
2+"D:\作業場\開発\@DTXMania\Git\実行時フォルダ(DTXCreator)\DTXV.exe" -n %1
--- a/FDK24/入力/個別/MidiIn.cs
+++ b/FDK24/入力/個別/MidiIn.cs
@@ -194,9 +194,9 @@ namespace FDK.入力
194194 byte p1 = (byte) ( ( dwParam1 >> 8 ) & 0xFF );
195195 byte p2 = (byte) ( ( dwParam1 >> 16 ) & 0xFF );
196196
197- if( ( ( 0x90 == ev ) && ( 0 != p2 ) ) || // Note ON (Velocity==0 は NoteOFF 扱いとする機器があるのでそれに倣う)
198- ( ( 0xB0 == ev ) && ( 4 == p1 ) ) ) // コントロールチェンジ#04: Foot controller
197+ if( ( 0x90 == ev ) && ( 0 != p2 ) )
199198 {
199+ // Note ON (Velocity==0 は NoteOFF 扱いとする機器があるのでそれに倣う)
200200 this._蓄積用入力イベントリスト.Add(
201201 new InputEvent() {
202202 Key = p1,
@@ -205,6 +205,17 @@ namespace FDK.入力
205205 Velocity = p2,
206206 } );
207207 }
208+ else if( ( 0xB0 == ev ) && ( 4 == p1 ) )
209+ {
210+ // コントロールチェンジ#04: Foot controller
211+ this._蓄積用入力イベントリスト.Add(
212+ new InputEvent() {
213+ Key = 255, // キーは 255 とする。
214+ 押された = true,
215+ TimeStamp = timeStamp,
216+ Velocity = p2,
217+ } );
218+ }
208219 }
209220 }
210221
--- a/StrokeStyleT/StrokeStyleT.cs
+++ b/StrokeStyleT/StrokeStyleT.cs
@@ -6,13 +6,12 @@ using System.Linq;
66 using System.ServiceModel;
77 using System.Windows.Forms;
88 using FDK;
9-using FDK.入力;
109 using SoundDevice = FDK.メディア.サウンド.WASAPI.Device;
1110 using SSTFormat.v2;
1211 using SST.曲;
1312 using SST.設定;
1413 using SST.ユーザ;
15-using SST.ステージ;
14+using SST.入力;
1615 using SST.ステージ.起動;
1716 using SST.ステージ.タイトル;
1817 using SST.ステージ.ログイン;
@@ -42,6 +41,8 @@ namespace SST
4241
4342 public static Config Config { get; protected set; }
4443
44+ public static 入力管理 入力管理 { get; protected set; }
45+
4546 public static bool ビュアーモードである
4647 {
4748 get;
@@ -56,17 +57,9 @@ namespace SST
5657
5758 public static ViewerMessage 最後に取得したビュアーメッセージ { get; protected set; }
5859
59- public static Keyboard キーボード入力 { get; protected set; }
60-
61- public static MidiIn MIDI入力 { get; protected set; }
62-
63- /// <remarks>
64- /// 追加の入力デバイスクラスを実装したら、ここにポーリングコードを追加すること。
65- /// </remarks>
66- public static void すべての入力デバイスをポーリングする()
60+ public static void すべての入力デバイスをポーリングする( bool 入力履歴を記録する = true )
6761 {
68- StrokeStyleT.キーボード入力?.ポーリングする();
69- StrokeStyleT.MIDI入力?.ポーリングする();
62+ StrokeStyleT.入力管理.すべての入力デバイスをポーリングする( 入力履歴を記録する );
7063 }
7164
7265
@@ -365,14 +358,9 @@ namespace SST
365358 StrokeStyleT.サウンドデバイス = new SoundDevice( CSCore.CoreAudioAPI.AudioClientShareMode.Shared );
366359 //----------------
367360 #endregion
368- #region " キーボード入力 を初期化する。"
361+ #region " 入力 を初期化する。"
369362 //-----------------
370- StrokeStyleT.キーボード入力 = new Keyboard( this._MainForm.Handle );
371- //-----------------
372- #endregion
373- #region " MIDI入力 を初期化する。"
374- //-----------------
375- StrokeStyleT.MIDI入力 = new MidiIn();
363+ StrokeStyleT.入力管理 = new 入力管理( this._MainForm.Handle );
376364 //-----------------
377365 #endregion
378366
@@ -432,18 +420,10 @@ namespace SST
432420 //----------------
433421 #endregion
434422
435- #region " MIDI入力デバイスを解放する。"
436- //-----------------
437- Log.Info( "MIDI入力デバイスを解放します。" );
438- StrokeStyleT.MIDI入力.Dispose();
439- StrokeStyleT.MIDI入力 = null;
440- //-----------------
441- #endregion
442- #region " キーボード入力デバイスを解放する。"
423+ #region " 入力を解放する(保存しない)。"
443424 //-----------------
444- Log.Info( "キーボード入力デバイスを解放します。" );
445- StrokeStyleT.キーボード入力.Dispose();
446- StrokeStyleT.キーボード入力 = null;
425+ StrokeStyleT.入力管理.Dispose();
426+ StrokeStyleT.入力管理 = null;
447427 //-----------------
448428 #endregion
449429 #region " サウンドデバイスを解放する。"
--- a/StrokeStyleT/StrokeStyleT.csproj
+++ b/StrokeStyleT/StrokeStyleT.csproj
@@ -101,6 +101,10 @@
101101 <Compile Include="Win32.cs" />
102102 <Compile Include="ViewerMessage.cs" />
103103 <Compile Include="ステージ\コンソールフォント.cs" />
104+ <Compile Include="入力\キーバインディング.cs" />
105+ <Compile Include="入力\入力種別.cs" />
106+ <Compile Include="入力\操作コマンド種別.cs" />
107+ <Compile Include="入力\入力管理.cs" />
104108 <Compile Include="曲\タイトルテクスチャ.cs" />
105109 <Compile Include="ステージ\選曲\曲パネルビュー.cs" />
106110 <Compile Include="設定\Config.cs" />
--- a/StrokeStyleT/ステージ/タイトル/タイトルステージ.cs
+++ b/StrokeStyleT/ステージ/タイトル/タイトルステージ.cs
@@ -2,6 +2,7 @@
22 using System.Collections.Generic;
33 using System.Diagnostics;
44 using System.Linq;
5+using SharpDX.DirectInput;
56 using FDK;
67 using FDK.メディア;
78
@@ -53,13 +54,14 @@ namespace SST.ステージ.タイトル
5354
5455 StrokeStyleT.すべての入力デバイスをポーリングする();
5556
56- // Enter 押下 → 確定&ステージ終了
57- if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Return ) )
57+ // 決定 → 確定&ステージ終了
58+ if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.決定 ) )
5859 {
5960 this.現在のフェーズ = フェーズ.確定;
6061 }
61- // Esc 押下 → キャンセル&ステージ終了
62- else if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Escape ) )
62+ // キャンセル or ESC → キャンセル&ステージ終了
63+ else if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.キャンセル ) ||
64+ StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Escape ) )
6365 {
6466 this.現在のフェーズ = フェーズ.キャンセル;
6567 }
--- a/StrokeStyleT/ステージ/ログイン/ログインステージ.cs
+++ b/StrokeStyleT/ステージ/ログイン/ログインステージ.cs
@@ -116,7 +116,7 @@ namespace SST.ステージ.ログイン
116116 this.ユーザインデックス = Math.Max( this.ユーザインデックス - 1, 0 );
117117 }
118118 #else
119-#warning ユーザ選択画面が完成するまでは、AutoPlayer で自動的にログインするようにする。
119+//#warning ユーザ選択画面が完成するまでは、AutoPlayer で自動的にログインするようにする。
120120 StrokeStyleT.ユーザ管理.ユーザを選択する( Properties.Resources.AUTOPLAYER );
121121 this.現在のフェーズ = フェーズ.確定;
122122 return;
--- a/StrokeStyleT/ステージ/演奏/演奏ステージ.cs
+++ b/StrokeStyleT/ステージ/演奏/演奏ステージ.cs
@@ -4,6 +4,7 @@ using System.Collections.Generic;
44 using System.Diagnostics;
55 using System.Linq;
66 using SharpDX;
7+using SharpDX.DirectInput;
78 using FDK;
89 using FDK.メディア;
910 using FDK.メディア.サウンド.WASAPI;
@@ -302,23 +303,24 @@ namespace SST.ステージ.演奏
302303
303304 // 入力。
304305
305- StrokeStyleT.すべての入力デバイスをポーリングする();
306+ // 演奏ステージでは、入力履歴(=操作コマンド)を使わず、キーバインディングにも依存せず、ダイレクトにキーを判別する。
307+ StrokeStyleT.すべての入力デバイスをポーリングする( 入力履歴を記録する: false );
306308
307309 // ESC 押下 → キャンセル
308- if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Escape ) &&
310+ if( StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Escape ) &&
309311 StrokeStyleT.ビュアーモードではない ) // ビュアーモードでは無効。
310312 {
311313 this.BGMを停止する();
312314 this.現在のフェーズ.Value = フェーズ.キャンセル;
313315 }
314316 // 上矢印押下 → 譜面スクロール速度の倍率を +0.5
315- else if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Up ) )
317+ else if( StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Up ) )
316318 {
317319 StrokeStyleT.ユーザ管理.現在選択されているユーザ.オプション.譜面スクロール速度の倍率 =
318320 Math.Min( StrokeStyleT.ユーザ管理.現在選択されているユーザ.オプション.譜面スクロール速度の倍率 + 0.5, 8.0 ); // 最大 8.0
319321 }
320322 // 下矢印押下 → 譜面スクロール速度の倍率を -0.5
321- else if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Down ) )
323+ else if( StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Down ) )
322324 {
323325 StrokeStyleT.ユーザ管理.現在選択されているユーザ.オプション.譜面スクロール速度の倍率 =
324326 Math.Max( StrokeStyleT.ユーザ管理.現在選択されているユーザ.オプション.譜面スクロール速度の倍率 - 0.5, 0.5 ); // 最小 0.5
--- a/StrokeStyleT/ステージ/結果/結果ステージ.cs
+++ b/StrokeStyleT/ステージ/結果/結果ステージ.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
33 using System.Diagnostics;
44 using System.Linq;
55 using SharpDX;
6+using SharpDX.DirectInput;
67 using FDK.メディア;
78
89 namespace SST.ステージ.結果
@@ -78,9 +79,10 @@ namespace SST.ステージ.結果
7879
7980 StrokeStyleT.すべての入力デバイスをポーリングする();
8081
81- // Enter or ESC 押下 → ステージ終了。
82- if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Return ) ||
83- StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Escape ) )
82+ // 決定 or キャンセル or ESC → ステージ終了。
83+ if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.決定 ) ||
84+ StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.キャンセル ) ||
85+ StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Escape ) )
8486 {
8587 this.現在のフェーズ = フェーズ.終了;
8688 }
--- a/StrokeStyleT/ステージ/起動/起動ステージ.cs
+++ b/StrokeStyleT/ステージ/起動/起動ステージ.cs
@@ -125,8 +125,8 @@ namespace SST.ステージ.起動
125125
126126 StrokeStyleT.すべての入力デバイスをポーリングする();
127127
128- // Enter 押下 → このステージを抜ける。
129- if( StrokeStyleT.キーボード入力.キーが押された( Key.Return ) )
128+ // 決定 → このステージを抜ける。
129+ if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.決定 ) )
130130 {
131131 Log.Info( "起動ステージをスキップします。" );
132132 this.現在のフェーズ = フェーズ.終了;
--- a/StrokeStyleT/ステージ/選曲/選曲ステージ.cs
+++ b/StrokeStyleT/ステージ/選曲/選曲ステージ.cs
@@ -2,6 +2,7 @@
22 using System.Collections.Generic;
33 using System.Diagnostics;
44 using System.Linq;
5+using SharpDX.DirectInput;
56 using FDK.メディア;
67
78 namespace SST.ステージ.選曲
@@ -84,8 +85,8 @@ namespace SST.ステージ.選曲
8485
8586 StrokeStyleT.すべての入力デバイスをポーリングする();
8687
87- // Enter 押下
88- if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Return ) )
88+ // 決定 → 現在選択されているノードによって異なる。
89+ if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.決定 ) )
8990 {
9091 if( StrokeStyleT.曲ツリー管理.現在選択されているノード is 曲.MusicNode )
9192 {
@@ -111,26 +112,32 @@ namespace SST.ステージ.選曲
111112 Trace.Fail( "[バグあり] 確定された曲が、曲でも BOX でも 戻る でも null でもありません。" );
112113 }
113114 }
114- // Esc 押下 → 戻る
115- else if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Escape ) )
115+ // キャンセル or ESC → 戻る
116+ else if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.キャンセル ) ||
117+ StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Escape ) )
118+
116119 {
117120 this.現在のフェーズ = フェーズ.キャンセル;
118121 }
119122
120- // カーソルキー(キーバインドに寄らず固定)→ 選曲カーソル移動
121- else if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Left ) )
123+ // 上下左右またはカーソルキー(キーバインドに寄らず固定)→ 選曲カーソル移動
124+ else if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.左 ) ||
125+ StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Left ) )
122126 {
123127 this._曲パネルビュー.カーソルを左に移動する();
124128 }
125- else if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Right ) )
129+ else if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.右 ) ||
130+ StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Right ) )
126131 {
127132 this._曲パネルビュー.カーソルを右に移動する();
128133 }
129- else if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Up ) )
134+ else if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.上 ) ||
135+ StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Up ) )
130136 {
131137 this._曲パネルビュー.カーソルを上に移動する();
132138 }
133- else if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Down ) )
139+ else if( StrokeStyleT.入力管理.操作コマンドが入力された( 入力.操作コマンド種別.下 ) ||
140+ StrokeStyleT.入力管理.キーボード入力.キーが押された( Key.Down ) )
134141 {
135142 this._曲パネルビュー.カーソルを下に移動する();
136143 }
--- /dev/null
+++ b/StrokeStyleT/入力/キーバインディング.cs
@@ -0,0 +1,216 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Diagnostics;
4+using System.IO;
5+using System.Linq;
6+using System.Runtime.Serialization;
7+using System.Xml;
8+using SharpDX.DirectInput;
9+
10+namespace SST.入力
11+{
12+ [DataContract( Name = "キーバインディング", Namespace = "" )]
13+ class キーバインディング : IExtensibleDataObject
14+ {
15+ [DataMember]
16+ public Dictionary<操作コマンド種別, 入力種別[][]> 操作コマンドtoストロークシーケンス { get; protected set; }
17+
18+ [DataMember]
19+ public Dictionary<int, 入力種別> キーボードto入力 { get; protected set; }
20+
21+ /// <summary>
22+ /// Key は、MIDI-ID(0~7) × 1000 + Note 。
23+ /// </summary>
24+ [DataMember]
25+ public Dictionary<int, 入力種別> MIDIto入力 { get; protected set; }
26+
27+ /// <summary>
28+ /// コンストラクタ。
29+ /// </summary>
30+ public キーバインディング()
31+ {
32+ this._初期化する( new StreamingContext() );
33+ }
34+
35+ public int MidiID( int midiKey )
36+ {
37+ return ( midiKey / 1000 );
38+ }
39+ public int MidiNote( int midiKey )
40+ {
41+ return ( midiKey % 1000 );
42+ }
43+ public int MidiKey( int midiID, int midiNote )
44+ {
45+ return ( midiID * 1000 + midiNote );
46+ }
47+
48+ /// <summary>
49+ /// DataContract オブジェクトをシリアル化してXMLファイルに保存する。
50+ /// </summary>
51+ public void 保存する( string XMLファイルパス )
52+ {
53+ string xmlPath = フォルダ.絶対パスに含まれるフォルダ変数を展開して返す( XMLファイルパス );
54+
55+ try
56+ {
57+ var serializer = new DataContractSerializer( typeof( キーバインディング ) );
58+
59+ var settings = new XmlWriterSettings() {
60+ Encoding = new System.Text.UTF8Encoding( false ), // UTF-8, BOMなし
61+ NewLineChars = Environment.NewLine, // 改行コード
62+ NewLineHandling = NewLineHandling.Replace, // 改行コードを統一(上書き)
63+ Indent = true, // 改行&インデントを使う(falseにすると改行もされなくなる)
64+ };
65+
66+ using( var writer = XmlWriter.Create( xmlPath, settings ) )
67+ {
68+ serializer.WriteObject( writer, this );
69+ }
70+ }
71+ catch( Exception e )
72+ {
73+ FDK.Log.ERROR( $"キーバインディングファイルの保存に失敗しました。[{e.Message}][{XMLファイルパス}]" );
74+ }
75+ }
76+
77+ /// <summary>
78+ /// XMLファイルを逆シリアル化して、DataContract オブジェクトを生成する。
79+ /// </summary>
80+ /// <remarks>
81+ /// DataContract 属性を持つ型の逆シリアル時には、コンストラクタは呼び出されないので注意。
82+ /// 各メンバは 0 または null になるが、それがイヤなら OnDeserializing コールバックなどを用意して、個別に初期化すること。
83+ /// </remarks>
84+ public static キーバインディング 読み込む( string XMLファイルパス )
85+ {
86+ var keyBinding = new キーバインディング();
87+
88+ string xmlPath = FDK.フォルダ.絶対パスに含まれるフォルダ変数を展開して返す( XMLファイルパス );
89+
90+ if( File.Exists( xmlPath ) )
91+ {
92+ try
93+ {
94+ var serializer = new DataContractSerializer( typeof( キーバインディング ) );
95+
96+ using( var reader = XmlReader.Create( xmlPath ) )
97+ {
98+ keyBinding = (キーバインディング) serializer.ReadObject( reader );
99+ }
100+ }
101+ catch( Exception e )
102+ {
103+ FDK.Log.ERROR( $"キーバインディングファイルの読み込みに失敗しました。[{e.Message}][{XMLファイルパス}]" );
104+ return new キーバインディング();
105+ }
106+ }
107+ else
108+ {
109+ FDK.Log.WARNING( $"キーバインディングファイルが存在しません。作成します。[{XMLファイルパス}]" );
110+ keyBinding.保存する( XMLファイルパス );
111+ }
112+
113+ return keyBinding;
114+ }
115+
116+ /// <summary>
117+ /// コンストラクタ時または逆シリアル化時のメンバの既定値を設定する。
118+ /// </summary>
119+ /// <param name="sc"></param>
120+ [OnDeserializing]
121+ private void _初期化する( StreamingContext context )
122+ {
123+ this.操作コマンドtoストロークシーケンス = new Dictionary<操作コマンド種別, 入力種別[][]>() {
124+
125+ // 決定: シンバル類
126+ { 操作コマンド種別.決定, new [] {
127+ new [] { 入力種別.LeftCrash },
128+ new [] { 入力種別.Ride },
129+ new [] { 入力種別.Ride_Cup },
130+ new [] { 入力種別.China },
131+ new [] { 入力種別.Splash }
132+ } },
133+
134+ // キャンセル: Bass×2
135+ { 操作コマンド種別.キャンセル, new [] { new [] { 入力種別.Bass, 入力種別.Bass } } },
136+
137+ // 上下左右: Snare,Tom
138+ { 操作コマンド種別.上, new [] { new [] { 入力種別.Tom2 } } },
139+ { 操作コマンド種別.下, new [] { new [] { 入力種別.Snare } } },
140+ { 操作コマンド種別.左, new [] { new [] { 入力種別.Tom1 } } },
141+ { 操作コマンド種別.右, new [] { new [] { 入力種別.Tom3 } } },
142+ };
143+
144+ this.キーボードto入力 = new Dictionary<int, 入力種別>() {
145+ { (int) Key.Q, 入力種別.LeftCrash },
146+ { (int) Key.Return, 入力種別.LeftCrash },
147+ { (int) Key.A, 入力種別.HiHat_Open },
148+ { (int) Key.Z, 入力種別.HiHat_Close },
149+ { (int) Key.X, 入力種別.Snare },
150+ { (int) Key.C, 入力種別.Bass },
151+ { (int) Key.Space, 入力種別.Bass },
152+ { (int) Key.V, 入力種別.Tom1 },
153+ { (int) Key.B, 入力種別.Tom2 },
154+ { (int) Key.N, 入力種別.Tom3 },
155+ { (int) Key.M, 入力種別.RightCrash },
156+ { (int) Key.K, 入力種別.Ride },
157+ };
158+
159+ this.MIDIto入力 = new Dictionary<int, 入力種別>() {
160+
161+ // とりあえず、DTXMania からベタ移植。
162+
163+ { this.MidiKey( 0, 42 ), 入力種別.HiHat_Close },
164+ { this.MidiKey( 0, 93 ), 入力種別.HiHat_Close },
165+ { this.MidiKey( 0, 46 ), 入力種別.HiHat_Open },
166+ { this.MidiKey( 0, 92 ), 入力種別.HiHat_Open },
167+ { this.MidiKey( 0, 44 ), 入力種別.HiHat_Foot },
168+ { this.MidiKey( 0, 255 ), 入力種別.HiHat_Control }, // FDK の MidiIn クラスは、FootControl を ノート 255 として扱う。
169+ { this.MidiKey( 0, 25 ), 入力種別.Snare },
170+ { this.MidiKey( 0, 26 ), 入力種別.Snare },
171+ { this.MidiKey( 0, 27 ), 入力種別.Snare },
172+ { this.MidiKey( 0, 28 ), 入力種別.Snare },
173+ { this.MidiKey( 0, 29 ), 入力種別.Snare },
174+ { this.MidiKey( 0, 31 ), 入力種別.Snare },
175+ { this.MidiKey( 0, 32 ), 入力種別.Snare },
176+ { this.MidiKey( 0, 34 ), 入力種別.Snare },
177+ { this.MidiKey( 0, 37 ), 入力種別.Snare },
178+ { this.MidiKey( 0, 38 ), 入力種別.Snare },
179+ { this.MidiKey( 0, 40 ), 入力種別.Snare },
180+ { this.MidiKey( 0, 113 ), 入力種別.Snare },
181+ { this.MidiKey( 0, 33 ), 入力種別.Bass },
182+ { this.MidiKey( 0, 35 ), 入力種別.Bass },
183+ { this.MidiKey( 0, 36 ), 入力種別.Bass },
184+ { this.MidiKey( 0, 112 ), 入力種別.Bass },
185+ { this.MidiKey( 0, 48 ), 入力種別.Tom1 },
186+ { this.MidiKey( 0, 50 ), 入力種別.Tom1 },
187+ { this.MidiKey( 0, 47 ), 入力種別.Tom2 },
188+ { this.MidiKey( 0, 41 ), 入力種別.Tom3 },
189+ { this.MidiKey( 0, 43 ), 入力種別.Tom3 },
190+ { this.MidiKey( 0, 45 ), 入力種別.Tom3 },
191+ { this.MidiKey( 0, 49 ), 入力種別.RightCrash },
192+ { this.MidiKey( 0, 52 ), 入力種別.RightCrash },
193+ { this.MidiKey( 0, 55 ), 入力種別.RightCrash },
194+ { this.MidiKey( 0, 57 ), 入力種別.RightCrash },
195+ { this.MidiKey( 0, 91 ), 入力種別.RightCrash },
196+ { this.MidiKey( 0, 51 ), 入力種別.Ride },
197+ { this.MidiKey( 0, 53 ), 入力種別.Ride },
198+ { this.MidiKey( 0, 59 ), 入力種別.Ride },
199+ { this.MidiKey( 0, 89 ), 入力種別.Ride },
200+ };
201+ }
202+
203+ #region " IExtensibleDataObject の実装 "
204+ //----------------
205+ private ExtensionDataObject _ExData;
206+
207+ public virtual ExtensionDataObject ExtensionData
208+ {
209+ get { return _ExData; }
210+ set { _ExData = value; }
211+ }
212+ //----------------
213+ #endregion
214+ }
215+}
216+
--- /dev/null
+++ b/StrokeStyleT/入力/入力種別.cs
@@ -0,0 +1,42 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Diagnostics;
4+using System.Linq;
5+
6+namespace SST.入力
7+{
8+ /// <summary>
9+ /// 入力データの定義。
10+ /// </summary>
11+ /// <remarks>
12+ /// 入力デバイスの入力データは、すべてこの(ドラム様式の)入力種別へマッピングされる。
13+ /// </remarks>
14+ enum 入力種別
15+ {
16+ Unknown,
17+ LeftCrash,
18+ Ride,
19+ Ride_Cup,
20+ China,
21+ Splash,
22+ HiHat_Open,
23+ //HiHat_HalfOpen, --> HiHat の開度で判断する
24+ HiHat_Close,
25+ HiHat_Foot,
26+ HiHat_Control, // 開度(入力信号である)
27+ Snare,
28+ Snare_OpenRim,
29+ Snare_ClosedRim,
30+ //Snare_Ghost, --> Snare の音量で判断する
31+ Bass,
32+ Tom1,
33+ Tom1_Rim,
34+ Tom2,
35+ Tom2_Rim,
36+ Tom3,
37+ Tom3_Rim,
38+ RightCrash,
39+ //LeftCymbal_Mute, --> 入力信号じゃない
40+ //RightCymbal_Mute, --> 入力信号じゃない
41+ }
42+}
--- /dev/null
+++ b/StrokeStyleT/入力/入力管理.cs
@@ -0,0 +1,284 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Diagnostics;
4+using System.IO;
5+using System.Linq;
6+using System.Runtime.Serialization;
7+using System.Xml;
8+using FDK;
9+using FDK.入力;
10+using FDK.カウンタ;
11+
12+namespace SST.入力
13+{
14+ class 入力管理 : IDisposable
15+ {
16+ public Keyboard キーボード入力 { get; protected set; }
17+
18+ public MidiIn MIDI入力 { get; protected set; }
19+
20+ /// <summary>
21+ /// コンストラクタ。入力デバイスを生成する。
22+ /// </summary>
23+ /// <param name="windowHandle">
24+ /// ウィンドウハンドル。キーボードのAcquireに使用する。
25+ /// </param>
26+ /// <param name="最大履歴数">
27+ /// 1つのストロークシーケンスを構成する最大入力サイズ。
28+ /// </param>
29+ public 入力管理( IntPtr windowHandle, int 最大履歴数 = 32 )
30+ {
31+ Trace.Assert( 0 < 最大履歴数 );
32+
33+ this.キーボード入力 = new Keyboard( windowHandle );
34+ this.MIDI入力 = new MidiIn();
35+
36+ this._最大履歴数 = 最大履歴数;
37+ this._入力履歴 = new List<入力種別>( this._最大履歴数 );
38+ this._前回の履歴追加時刻sec = null;
39+
40+ this._キーバインディング = キーバインディング.読み込む( this._KeyBindingsXmlファイルパス );
41+ }
42+
43+ /// <summary>
44+ /// 入力デバイスを解放する。
45+ /// </summary>
46+ public void Dispose()
47+ {
48+ this._キーバインディング.保存する( this._KeyBindingsXmlファイルパス );
49+
50+ this.MIDI入力?.Dispose();
51+ this.MIDI入力 = null;
52+
53+ this.キーボード入力?.Dispose();
54+ this.キーボード入力 = null;
55+ }
56+
57+ public void すべての入力デバイスをポーリングする( bool 入力履歴を記録する = true )
58+ {
59+ // 履歴の記録が OFF → ON に変わった際には、履歴をクリアする。
60+ if( 入力履歴を記録する && !this._入力履歴を記録中 )
61+ {
62+ this._入力履歴.Clear();
63+ this._前回の履歴追加時刻sec = null;
64+ }
65+ this._入力履歴を記録中 = 入力履歴を記録する;
66+
67+ // 追加の入力デバイスクラスを実装したら、ここにポーリングコードを追加すること。
68+
69+ #region " キーボード入力 "
70+ //----------------
71+ this.キーボード入力?.ポーリングする();
72+
73+ if( 入力履歴を記録する )
74+ {
75+ for( int i = 0; i < 256; i++ )
76+ {
77+ InputEvent ev;
78+ if( ( this.キーボード入力.キーが押された( i, out ev ) ) &&
79+ ( this._キーバインディング.キーボードto入力.ContainsKey( ev.Key ) ) )
80+ {
81+ this.履歴に追加する(
82+ this._キーバインディング.キーボードto入力[ ev.Key ],
83+ QPCTimer.生カウント相対値を秒へ変換して返す( ev.TimeStamp ) ); // 相対だろうが絶対だろうが、どっちかに統一さえされていればいい。
84+ }
85+ }
86+ }
87+ //----------------
88+ #endregion
89+
90+ #region " MIDI入力 "
91+ //----------------
92+ this.MIDI入力?.ポーリングする();
93+
94+ if( 入力履歴を記録する )
95+ {
96+ for( int i = 0; i < 256; i++ )
97+ {
98+ InputEvent ev;
99+ if( ( this.MIDI入力.キーが押された( i, out ev ) ) &&
100+ ( this._キーバインディング.MIDIto入力.ContainsKey( ev.Key ) ) )
101+ {
102+ this.履歴に追加する(
103+ this._キーバインディング.MIDIto入力[ ev.Key ],
104+ QPCTimer.生カウント相対値を秒へ変換して返す( ev.TimeStamp ) ); // 相対だろうが絶対だろうが、どっちかに統一さえされていればいい。
105+ }
106+ }
107+ }
108+ //----------------
109+ #endregion
110+ }
111+
112+ /// <summary>
113+ /// 履歴に新しい入力データを追加する。
114+ /// </summary>
115+ /// <param name="入力">
116+ /// 追加登録する入力。ただし、FootControl は追加の対象外となる。
117+ /// </param>
118+ /// <param name="入力時刻sec">
119+ /// 追加登録する入力が発生した時刻。全入力で同じ時間軸であること。
120+ /// </param>
121+ public void 履歴に追加する( 入力種別 入力, double 入力時刻sec )
122+ {
123+ // FootControl は履歴に追加しない。(操作コマンドに関係ないうえに、大量に発生して履歴を汚すので。)
124+ if( 入力 == 入力種別.HiHat_Control )
125+ return;
126+
127+ // 容量がいっぱいなら、古い履歴から削除する。
128+ if( this._入力履歴.Count >= this._最大履歴数 )
129+ this._入力履歴.RemoveRange( 0, ( this._入力履歴.Count - this._最大履歴数 + 1 ) );
130+
131+ // 前回の追加登録時刻からの経過時間がオーバーしているなら、履歴をすべて破棄する。
132+ if( null != this._前回の履歴追加時刻sec )
133+ {
134+ var 前回の登録からの経過時間sec = 入力時刻sec - this._前回の履歴追加時刻sec;
135+
136+ if( _連続入力だとみなす最大の間隔sec < 前回の登録からの経過時間sec )
137+ this._入力履歴.Clear();
138+ }
139+
140+ // 今回の入力を履歴に登録する。
141+ this._入力履歴.Add( 入力 );
142+ this._前回の履歴追加時刻sec = 入力時刻sec; // 更新。
143+ }
144+
145+ /// <summary>
146+ /// 現在の履歴において、指定した操作コマンドが成立しているかを確認する。
147+ /// </summary>
148+ /// <param name="操作コマンド">
149+ /// 確認したい操作コマンド。
150+ /// </param>
151+ /// <returns>
152+ /// 操作コマンドが成立しているなら true。
153+ /// </returns>
154+ /// <remarks>
155+ /// 指定した操作コマンドに対応するストロークシーケンスのうちの1つが現在の履歴の一部に見られれば、成立しているとみなす。
156+ /// 履歴内に複数存在している場合は、一番古いストロークシーケンスが対象となる。
157+ /// 成立した場合、そのシーケンスを含め、シーケンスより古い履歴はすべて削除される。
158+ /// </remarks>
159+ public bool 操作コマンドが入力された( 操作コマンド種別 操作コマンド )
160+ {
161+ if( this._キーバインディング.操作コマンドtoストロークシーケンス.ContainsKey( 操作コマンド ) )
162+ {
163+ var シーケンスリスト = this._キーバインディング.操作コマンドtoストロークシーケンス[ 操作コマンド ];
164+
165+ foreach( var シーケンス in シーケンスリスト )
166+ {
167+ if( 1 == シーケンス.Count() )
168+ {
169+ // 単一ストローク時の高速版
170+ if( this._操作コマンドが入力された( シーケンス[ 0 ] ) )
171+ return true;
172+ }
173+ else if( 1 < シーケンス.Count() )
174+ {
175+ // 複数ストローク時の通常版
176+ if( this._操作コマンドが入力された( シーケンス ) )
177+ return true;
178+ }
179+ }
180+ }
181+
182+ return false;
183+ }
184+
185+ private キーバインディング _キーバインディング = null;
186+
187+ private string _KeyBindingsXmlファイルパス = @"$(AppData)\KeyBindings.xml";
188+
189+ private const double _連続入力だとみなす最大の間隔sec = 0.5;
190+
191+ private int _最大履歴数;
192+
193+ private List<入力種別> _入力履歴 = null;
194+
195+ private bool _入力履歴を記録中 = true;
196+
197+ private double? _前回の履歴追加時刻sec = null;
198+
199+ /// <summary>
200+ /// 現在の履歴において、指定した操作コマンド(ストロークシーケンス)が成立しているかを確認する。
201+ /// </summary>
202+ /// <param name="操作コマンドのストロークシーケンス">
203+ /// 確認したい操作コマンドのストロークシーケンス。
204+ /// </param>
205+ /// <returns>
206+ /// 操作コマンドが成立しているなら true。
207+ /// </returns>
208+ /// <remarks>
209+ /// 指定したシーケンスが現在の履歴の一部に見られれば、成立しているとみなす。
210+ /// 履歴内に複数存在している場合は、一番古いストロークシーケンスが対象となる。
211+ /// 成立した場合、そのシーケンスを含め、シーケンスより古い履歴はすべて削除される。
212+ /// </remarks>
213+ private bool _操作コマンドが入力された( IEnumerable<入力種別> 操作コマンドのストロークシーケンス )
214+ {
215+ int ストローク数 = 操作コマンドのストロークシーケンス.Count();
216+
217+ if( 0 == ストローク数 )
218+ return false; // 空ストロークは常に不成立。
219+
220+ if( this._入力履歴.Count < ストローク数 )
221+ return false; // 履歴の長さが足りない。
222+
223+
224+ // 検索開始位置を探す。
225+
226+ int 履歴の検索開始位置 = this._入力履歴.IndexOf( 操作コマンドのストロークシーケンス.ElementAt( 0 ) );
227+
228+ if( -1 == 履歴の検索開始位置 )
229+ return false; // 最初のストロークが見つからない。
230+
231+ if( ( this._入力履歴.Count - 履歴の検索開始位置 ) < ストローク数 )
232+ return false; // 必要なストローク数が足りない。
233+
234+
235+ // 検索開始位置から末尾へ、すべてのストロークが一致するか確認する。
236+
237+ for( int i = 1; i < ストローク数; i++ )
238+ {
239+ if( this._入力履歴[ 履歴の検索開始位置 + i ] != 操作コマンドのストロークシーケンス.ElementAt( i ) )
240+ return false; // 一致しなかった。
241+ }
242+
243+
244+ // 見つけたシーケンスならびにそれより古い履歴を削除する。
245+
246+ this._入力履歴.RemoveRange( 0, ( 履歴の検索開始位置 + ストローク数 ) );
247+
248+ return true;
249+ }
250+
251+ /// <summary>
252+ /// 現在の履歴において、指定した操作コマンド(単一ストローク)が成立しているかを確認する。
253+ /// </summary>
254+ /// <param name="操作コマンドのストローク">
255+ /// 確認したい操作コマンドのストローク。
256+ /// </param>
257+ /// <returns>
258+ /// 操作コマンドが成立しているなら true。
259+ /// </returns>
260+ /// <remarks>
261+ /// 指定したストロークが現在の履歴内に見られれば、成立しているとみなす。
262+ /// 履歴内に複数存在している場合は、一番古いストロークが対象となる。
263+ /// 成立した場合、そのシーケンスを含め、シーケンスより古い履歴はすべて削除される。
264+ /// </remarks>
265+ private bool _操作コマンドが入力された( 入力種別 操作コマンドのストローク )
266+ {
267+ int ストローク数 = 1; // 固定。
268+
269+ if( this._入力履歴.Count < ストローク数 )
270+ return false; // 履歴の長さが足りない。
271+
272+
273+ int 検出位置 = this._入力履歴.IndexOf( 操作コマンドのストローク );
274+
275+ if( -1 == 検出位置 )
276+ return false; // ストロークが見つからない。
277+
278+ // 見つけたストロークならびにそれより古い履歴を削除する。
279+ this._入力履歴.RemoveRange( 0, ( 検出位置 + ストローク数 ) );
280+
281+ return true;
282+ }
283+ }
284+}
--- /dev/null
+++ b/StrokeStyleT/入力/操作コマンド種別.cs
@@ -0,0 +1,21 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Diagnostics;
4+using System.Linq;
5+
6+namespace SST.入力
7+{
8+ /// <summary>
9+ /// 入力をもとにしてアプリへ指示できる操作の定義。
10+ /// </summary>
11+ enum 操作コマンド種別
12+ {
13+ 何もしない,
14+ 上,
15+ 下,
16+ 左,
17+ 右,
18+ 決定,
19+ キャンセル,
20+ }
21+}
--- a/StrokeStyleTTests/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
1-using System.Reflection;
2-using System.Runtime.CompilerServices;
3-using System.Runtime.InteropServices;
4-
5-// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。
6-// アセンブリに関連付けられている情報を変更するには、
7-// これらの属性値を変更してください。
8-[assembly: AssemblyTitle( "StrokeStyleTTests" )]
9-[assembly: AssemblyDescription( "" )]
10-[assembly: AssemblyConfiguration( "" )]
11-[assembly: AssemblyCompany( "" )]
12-[assembly: AssemblyProduct( "StrokeStyleTTests" )]
13-[assembly: AssemblyCopyright( "Copyright © 2016" )]
14-[assembly: AssemblyTrademark( "" )]
15-[assembly: AssemblyCulture( "" )]
16-
17-// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから
18-// 参照できなくなります。このアセンブリ内で COM から型にアクセスする必要がある場合は、
19-// その型の ComVisible 属性を true に設定してください。
20-[assembly: ComVisible( false )]
21-
22-// このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります
23-[assembly: Guid( "5b825d04-0547-40b7-82b4-7d30bfc2b659" )]
24-
25-// アセンブリのバージョン情報は次の 4 つの値で構成されています:
26-//
27-// メジャー バージョン
28-// マイナー バージョン
29-// ビルド番号
30-// Revision
31-//
32-// すべての値を指定するか、以下のように '*' を使用してビルド番号とリビジョン番号を
33-// 既定値にすることができます:
34-//[アセンブリ: AssemblyVersion("1.0.*")]
35-[assembly: AssemblyVersion( "1.0.0.0" )]
36-[assembly: AssemblyFileVersion( "1.0.0.0" )]
--- a/StrokeStyleTTests/StrokeStyleTTests.csproj
+++ /dev/null
@@ -1,89 +0,0 @@
1-<?xml version="1.0" encoding="utf-8"?>
2-<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3- <PropertyGroup>
4- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6- <ProjectGuid>{5B825D04-0547-40B7-82B4-7D30BFC2B659}</ProjectGuid>
7- <OutputType>Library</OutputType>
8- <AppDesignerFolder>Properties</AppDesignerFolder>
9- <RootNamespace>StrokeStyleTTests</RootNamespace>
10- <AssemblyName>StrokeStyleTTests</AssemblyName>
11- <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
12- <FileAlignment>512</FileAlignment>
13- <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
14- <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
15- <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
16- <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
17- <IsCodedUITest>False</IsCodedUITest>
18- <TestProjectType>UnitTest</TestProjectType>
19- <TargetFrameworkProfile />
20- </PropertyGroup>
21- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
22- <DebugSymbols>true</DebugSymbols>
23- <DebugType>full</DebugType>
24- <Optimize>false</Optimize>
25- <OutputPath>bin\Debug\</OutputPath>
26- <DefineConstants>DEBUG;TRACE</DefineConstants>
27- <ErrorReport>prompt</ErrorReport>
28- <WarningLevel>4</WarningLevel>
29- </PropertyGroup>
30- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
31- <DebugType>pdbonly</DebugType>
32- <Optimize>true</Optimize>
33- <OutputPath>bin\Release\</OutputPath>
34- <DefineConstants>TRACE</DefineConstants>
35- <ErrorReport>prompt</ErrorReport>
36- <WarningLevel>4</WarningLevel>
37- </PropertyGroup>
38- <ItemGroup>
39- <Reference Include="System" />
40- </ItemGroup>
41- <Choose>
42- <When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
43- <ItemGroup>
44- <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
45- </ItemGroup>
46- </When>
47- <Otherwise>
48- <ItemGroup>
49- <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
50- </ItemGroup>
51- </Otherwise>
52- </Choose>
53- <ItemGroup>
54- <Compile Include="Properties\AssemblyInfo.cs" />
55- </ItemGroup>
56- <ItemGroup>
57- <ProjectReference Include="..\StrokeStyleT\StrokeStyleT.csproj">
58- <Project>{ED72FD06-C276-42DC-9301-83DE699BDF4C}</Project>
59- <Name>StrokeStyleT</Name>
60- </ProjectReference>
61- </ItemGroup>
62- <Choose>
63- <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
64- <ItemGroup>
65- <Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
66- <Private>False</Private>
67- </Reference>
68- <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
69- <Private>False</Private>
70- </Reference>
71- <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
72- <Private>False</Private>
73- </Reference>
74- <Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
75- <Private>False</Private>
76- </Reference>
77- </ItemGroup>
78- </When>
79- </Choose>
80- <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
81- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
82- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
83- Other similar extension points exist, see Microsoft.Common.targets.
84- <Target Name="BeforeBuild">
85- </Target>
86- <Target Name="AfterBuild">
87- </Target>
88- -->
89-</Project>
\ No newline at end of file
Show on old repository browser