private void _一定時間が経っていれば空行を挿入する() { double 今回の入力リスト追加時刻 = QPCTimer.生カウント相対値を秒へ変換して返す(QPCTimer.生カウント); // 1秒以上経っていれば改行 if (1.0 < (今回の入力リスト追加時刻 - this._前回の入力リスト追加時刻)) { this.listView入力リスト.Items.Add(""); } this._前回の入力リスト追加時刻 = 今回の入力リスト追加時刻; }
public void 表示する() { using (Log.Block(FDKUtilities.現在のメソッド名)) { // (1) メインウィンドウ用の入力管理をいったん破棄し、このダイアログ用の入力管理を生成する。 App.入力管理.Dispose(); using (var 入力管理 = new 入力管理(this.Handle)) { 入力管理.キーバインディングを取得する = () => App.システム設定.キーバインディング; 入力管理.キーバインディングを保存する = () => App.システム設定.保存する(); 入力管理.初期化する(); // (2) ダイアログを表示。 using (var timer = new Timer()) { #region " 設定値で初期化。" //---------------- foreach (ドラム入力種別 drum in Enum.GetValues(typeof(ドラム入力種別))) { if (drum == ドラム入力種別.Unknown || drum == ドラム入力種別.HiHat_Control) { continue; // 除外(設定変更不可) } this.comboBoxパッドリスト.Items.Add(drum.ToString()); } // 変更後のキーバインディングを、現在の設定値で初期化。 this._変更後のキーバインディング = (キーバインディング)App.システム設定.キーバインディング.Clone(); // 最初のパッドを選択し、割り当て済みリストを更新。 this.comboBoxパッドリスト.SelectedIndex = 0; // その他の初期化。 this._前回の入力リスト追加時刻 = QPCTimer.生カウント相対値を秒へ変換して返す(QPCTimer.生カウント); this._FootPedal現在値 = 0; this.textBoxFootPedal現在値.Text = "0"; this.textBoxFootPedal最小値.Text = this._変更後のキーバインディング.FootPedal最小値.ToString(); this.textBoxFootPedal最大値.Text = this._変更後のキーバインディング.FootPedal最大値.ToString(); this._変更あり = false; // 初期メッセージを出力。 this.listView入力リスト.Items.Add($"KEYBOARD \"{入力管理.Keyboard.DeviceName}\" の受付を開始しました。"); for (int i = 0; i < 入力管理.MidiIn.DeviceName.Count; i++) { this.listView入力リスト.Items.Add($"MIDI IN [{i}] \"{入力管理.MidiIn.DeviceName[ i ]}\" の受付を開始しました。"); } this.listView入力リスト.Items.Add(""); this.listView入力リスト.Items.Add("* タイミングクロック信号、アクティブ信号は無視します。"); this.listView入力リスト.Items.Add("* 入力と入力の間が500ミリ秒以上開いた場合は、間に空行を表示します。"); this.listView入力リスト.Items.Add(""); this.listView入力リスト.Items.Add("キーボードまたはMIDI信号を入力してください。"); //---------------- #endregion // タイマーイベントを使って、定期的に、入力値の表示とフットペダル開度ゲージの描画を行う。 timer.Interval = 100; timer.Tick += (sender, arg) => { #region " キーボードをポーリングし、入力値を入力リストへ出力。" //---------------- 入力管理.Keyboard.ポーリングする(); for (int i = 0; i < 入力管理.Keyboard.入力イベントリスト.Count; i++) { var inputEvent = 入力管理.Keyboard.入力イベントリスト[i]; if (inputEvent.押された) { var item = new ListViewItem入力リスト用(InputDeviceType.Keyboard, inputEvent); if (inputEvent.Key == (int)Key.Escape) // 割り当てされてほしくないキーはここへ。 { item.割り当て可能 = false; } // 既に割り当てられていたらそのドラム種別を表示。 var drumType = this._変更後のキーバインディング.キーボードtoドラム .Where((kvp) => (kvp.Key.deviceId == item.inputEvent.DeviceID && kvp.Key.key == item.inputEvent.Key)) .Select((kvp) => kvp.Value); if (0 < drumType.Count()) { item.Text += $" (現在の割り当て: {drumType.ElementAt( 0 )})"; } this._一定時間が経っていれば空行を挿入する(); this.listView入力リスト.Items.Add(item); this.listView入力リスト.EnsureVisible(this.listView入力リスト.Items.Count - 1); } else if (inputEvent.離された) { // キーボードについては表示しない。 } } //---------------- #endregion #region " MIDI入力をポーリングし、入力値を入力リストへ出力。" //---------------- // MidiInChecker の機能もかねて、NoteOFF や ControlChange も表示する。(割り当てはできない。) 入力管理.MidiIn.ポーリングする(); for (int i = 0; i < 入力管理.MidiIn.入力イベントリスト.Count; i++) { var inputEvent = 入力管理.MidiIn.入力イベントリスト[i]; if (inputEvent.押された && (255 == inputEvent.Key) && (4 == inputEvent.Control)) { #region " (A) フットペダルコントロールの場合 → 入力リストではなく専用のUIで表示。" //---------------- if (this._FootPedal現在値 != inputEvent.Velocity) { // 現在値 this._FootPedal現在値 = inputEvent.Velocity; this.textBoxFootPedal現在値.Text = this._FootPedal現在値.ToString(); // 最大値 if (this._FootPedal現在値 > this._変更後のキーバインディング.FootPedal最大値) { this._変更後のキーバインディング.FootPedal最大値 = this._FootPedal現在値; this.textBoxFootPedal最大値.Text = this._変更後のキーバインディング.FootPedal最大値.ToString(); } // 最小値 if (this._FootPedal現在値 <= this._変更後のキーバインディング.FootPedal最小値) { this._変更後のキーバインディング.FootPedal最小値 = this._FootPedal現在値; this.textBoxFootPedal最小値.Text = this._変更後のキーバインディング.FootPedal最小値.ToString(); } } //---------------- #endregion } else { #region " (B) その他のMIDI入出力 → 入力リストに表示。" //---------------- var item = new ListViewItem入力リスト用(InputDeviceType.MidiIn, inputEvent); // 既に割り当てられていたらそのドラム種別を表示。 var drumType = this._変更後のキーバインディング.MIDItoドラム .Where((kvp) => (kvp.Key.deviceId == item.inputEvent.DeviceID && kvp.Key.key == item.inputEvent.Key)) .Select((kvp) => kvp.Value); if (0 < drumType.Count()) { item.Text += $" (現在の割り当て: {drumType.ElementAt( 0 )})"; } this._一定時間が経っていれば空行を挿入する(); this.listView入力リスト.Items.Add(item); this.listView入力リスト.EnsureVisible(this.listView入力リスト.Items.Count - 1); //---------------- #endregion } } //---------------- #endregion #region " MIDIフットペダルの開度ゲージを描画。" //---------------- using (var g = pictureBoxFootPedal.CreateGraphics()) { var 全体矩形 = pictureBoxFootPedal.ClientRectangle; var 背景色 = new System.Drawing.SolidBrush(pictureBoxFootPedal.BackColor); var 最大値ゲージ色 = System.Drawing.Brushes.LightBlue; var ゲージ色 = System.Drawing.Brushes.Blue; g.FillRectangle(背景色, 全体矩形); int 最大値用差分 = (int)(全体矩形.Height * (1.0 - this._変更後のキーバインディング.FootPedal最大値 / 127.0)); var 最大値ゲージ矩形 = new System.Drawing.Rectangle( 全体矩形.X, 全体矩形.Y + 最大値用差分, 全体矩形.Width, 全体矩形.Height - 最大値用差分); g.FillRectangle(最大値ゲージ色, 最大値ゲージ矩形); int 現在値用差分 = (int)(全体矩形.Height * (1.0 - this._FootPedal現在値 / 127.0)); var ゲージ矩形 = new System.Drawing.Rectangle( 全体矩形.X, 全体矩形.Y + 現在値用差分, 全体矩形.Width, 全体矩形.Height - 現在値用差分); g.FillRectangle(ゲージ色, ゲージ矩形); } //---------------- #endregion }; timer.Start(); #region " ダイアログを表示。" //---------------- Cursor.Show(); var dr = this.ShowDialog(Program.App); if (App.全画面モード) { Cursor.Hide(); } //---------------- #endregion timer.Stop(); if (dr == DialogResult.OK) { // 設定値を反映する。 App.システム設定.キーバインディング = (キーバインディング)this._変更後のキーバインディング.Clone(); 入力管理.キーバインディングを保存する(); } } } // (3) メインウィンドウ用の入力管理を復活する。 App.入力管理 = new 入力管理(Program.App.Handle) { キーバインディングを取得する = () => App.システム設定.キーバインディング, キーバインディングを保存する = () => App.システム設定.保存する(), }; App.入力管理.初期化する(); } }
public void 表示する() { using var _ = new LogBlock(Log.現在のメソッド名); using var timer = new Timer(); #region " 設定値で初期化。" //---------------- foreach (ドラム入力種別?drum in Enum.GetValues(typeof(ドラム入力種別))) { if (!drum.HasValue || drum == ドラム入力種別.Unknown || drum == ドラム入力種別.HiHat_Control) { continue; // 除外(設定変更不可) } this.comboBoxパッドリスト.Items.Add(drum.Value.ToString()); } // 変更後のキーバインディングを、現在の設定値で初期化。 this._変更後のシステム設定 = Global.App.システム設定.Clone(); // 最初のパッドを選択し、割り当て済みリストを更新。 this.comboBoxパッドリスト.SelectedIndex = 0; // その他の初期化。 this._前回の入力リスト追加時刻 = QPCTimer.生カウント相対値を秒へ変換して返す(QPCTimer.生カウント); this._FootPedal現在値 = 0; this.textBoxFootPedal現在値.Text = "0"; this.textBoxFootPedal最小値.Text = this._変更後のシステム設定.FootPedal最小値.ToString(); this.textBoxFootPedal最大値.Text = this._変更後のシステム設定.FootPedal最大値.ToString(); this._変更あり = false; // 初期メッセージを出力。 this.listView入力リスト.Items.Add($"HID Keyboard の受付を開始しました。"); for (int i = 0; i < Global.AppForm.MidiIns.DeviceName.Count; i++) { this.listView入力リスト.Items.Add($"MIDI IN [{i}] '{Global.AppForm.MidiIns.DeviceName[ i ]}' の受付を開始しました。"); } this.listView入力リスト.Items.Add(""); this.listView入力リスト.Items.Add("* タイミングクロック信号、アクティブ信号は無視します。"); this.listView入力リスト.Items.Add("* 入力と入力の間が500ミリ秒以上開いた場合は、間に空行を表示します。"); this.listView入力リスト.Items.Add(""); this.listView入力リスト.Items.Add("キーボードまたはMIDI信号を入力してください。"); //---------------- #endregion // タイマーイベントを使って、定期的に、ゲームコントローラ/MIDI入力値の表示と、MIDIフットペダル開度ゲージの描画を行う。 timer.Interval = 100; timer.Tick += (sender, arg) => { #region " ゲームコントローラをポーリングし、入力値を入力リストへ出力。" //---------------- Global.AppForm.GameControllersHID.ポーリングする(); for (int i = 0; i < Global.AppForm.GameControllersHID.入力イベントリスト.Count; i++) { var inputEvent = Global.AppForm.GameControllersHID.入力イベントリスト[i]; if (inputEvent.押された) { // 入力リストに表示。 var item = new ListViewItem入力リスト用(InputDeviceType.GameController, inputEvent); // 既に割り当てられていたらそのドラム種別を表示。 var drumType = this._変更後のシステム設定.ゲームコントローラtoドラム .Where((kvp) => (kvp.Key.deviceId == item.inputEvent.DeviceID && kvp.Key.key == item.inputEvent.Key)) .Select((kvp) => kvp.Value); if (0 < drumType.Count()) { item.Text += $" (現在の割り当て: {drumType.ElementAt( 0 )})"; } this._一定時間が経っていれば空行を挿入する(); this.listView入力リスト.Items.Add(item); this.listView入力リスト.EnsureVisible(this.listView入力リスト.Items.Count - 1); } } //---------------- #endregion #region " MIDI入力をポーリングし、入力値を入力リストへ出力。" //---------------- // MidiInChecker の機能もかねて、NoteOFF や ControlChange も表示する。(割り当てはできない。) Global.AppForm.MidiIns.ポーリングする(); for (int i = 0; i < Global.AppForm.MidiIns.入力イベントリスト.Count; i++) { var inputEvent = Global.AppForm.MidiIns.入力イベントリスト[i]; if (inputEvent.押された && (255 == inputEvent.Key) && (4 == inputEvent.Control)) { #region " (A) フットペダルコントロールの場合 → 入力リストではなく専用のUIで表示。" //---------------- if (this._FootPedal現在値 != inputEvent.Velocity) { // 現在値 this._FootPedal現在値 = inputEvent.Velocity; this.textBoxFootPedal現在値.Text = this._FootPedal現在値.ToString(); // 最大値 if (this._FootPedal現在値 > this._変更後のシステム設定.FootPedal最大値) { this._変更後のシステム設定.FootPedal最大値 = this._FootPedal現在値; this.textBoxFootPedal最大値.Text = this._変更後のシステム設定.FootPedal最大値.ToString(); } // 最小値 if (this._FootPedal現在値 <= this._変更後のシステム設定.FootPedal最小値) { this._変更後のシステム設定.FootPedal最小値 = this._FootPedal現在値; this.textBoxFootPedal最小値.Text = this._変更後のシステム設定.FootPedal最小値.ToString(); } } //---------------- #endregion } else { #region " (B) その他のMIDI入出力 → 入力リストに表示。" //---------------- var item = new ListViewItem入力リスト用(InputDeviceType.MidiIn, inputEvent); // 既に割り当てられていたらそのドラム種別を表示。 var drumType = this._変更後のシステム設定.MIDItoドラム .Where((kvp) => (kvp.Key.deviceId == item.inputEvent.DeviceID && kvp.Key.key == item.inputEvent.Key)) .Select((kvp) => kvp.Value); if (0 < drumType.Count()) { item.Text += $" (現在の割り当て: {drumType.ElementAt( 0 )})"; } this._一定時間が経っていれば空行を挿入する(); this.listView入力リスト.Items.Add(item); this.listView入力リスト.EnsureVisible(this.listView入力リスト.Items.Count - 1); //---------------- #endregion } } //---------------- #endregion #region " MIDIフットペダルの開度ゲージを描画。" //---------------- using (var g = pictureBoxFootPedal.CreateGraphics()) { var 全体矩形 = pictureBoxFootPedal.ClientRectangle; var 背景色 = new System.Drawing.SolidBrush(pictureBoxFootPedal.BackColor); var 最大値ゲージ色 = System.Drawing.Brushes.LightBlue; var ゲージ色 = System.Drawing.Brushes.Blue; g.FillRectangle(背景色, 全体矩形); int 最大値用差分 = (int)(全体矩形.Height * (1.0 - this._変更後のシステム設定.FootPedal最大値 / 127.0)); var 最大値ゲージ矩形 = new System.Drawing.Rectangle( 全体矩形.X, 全体矩形.Y + 最大値用差分, 全体矩形.Width, 全体矩形.Height - 最大値用差分); g.FillRectangle(最大値ゲージ色, 最大値ゲージ矩形); int 現在値用差分 = (int)(全体矩形.Height * (1.0 - this._FootPedal現在値 / 127.0)); var ゲージ矩形 = new System.Drawing.Rectangle( 全体矩形.X, 全体矩形.Y + 現在値用差分, 全体矩形.Width, 全体矩形.Height - 現在値用差分); g.FillRectangle(ゲージ色, ゲージ矩形); } //---------------- #endregion }; this.KeyPreview = true; // Control への入力を先に Form が受け取れるようにする。 this.KeyDown += (sender, arg) => { // ダイアログで RawInput を使う方法が分からないので KeyDown を使う #region " キーボードの入力値を入力リストへ出力。" //---------------- var inputEvent = new InputEvent() { DeviceID = 0, Key = (int)arg.KeyCode, TimeStamp = 0, Velocity = 100, 押された = true, Control = 0, }; var item = new ListViewItem入力リスト用(InputDeviceType.Keyboard, inputEvent); if (inputEvent.Key == (int)Keys.Escape) // 割り当てされてほしくないキーはここへ。 { item.割り当て可能 = false; } // 既に割り当てられていたらそのドラム種別を表示。 var drumType = this._変更後のシステム設定.キーボードtoドラム .Where((kvp) => (kvp.Key.deviceId == item.inputEvent.DeviceID && kvp.Key.key == item.inputEvent.Key)) .Select((kvp) => kvp.Value); if (0 < drumType.Count()) { item.Text += $" (現在の割り当て: {drumType.ElementAt( 0 )})"; } this._一定時間が経っていれば空行を挿入する(); this.listView入力リスト.Items.Add(item); this.listView入力リスト.EnsureVisible(this.listView入力リスト.Items.Count - 1); //---------------- #endregion }; timer.Start(); #region " ダイアログを表示。" //---------------- Cursor.Show(); var dr = this.ShowDialog(Global.AppForm); if (Global.AppForm.ScreenMode.IsFullscreenMode) { Cursor.Hide(); } //---------------- #endregion timer.Stop(); if (dr == DialogResult.OK) { // 設定値を反映する。 Global.App.システム設定 = this._変更後のシステム設定.Clone(); Global.App.システム設定.保存する(); } }
public override void 高速進行する() { try { if (this._初めての進行描画) { this._初めての進行描画 = false; } // 高速進行 this._FPS.FPSをカウントしプロパティを更新する(); switch (this.現在のフェーズ) { case フェーズ.フェードイン: if (this._フェードインカウンタ.終了値に達した) { #region " フェードインが終わったので、演奏開始。 " //---------------- Log.Info("演奏を開始します。"); this._描画開始チップ番号 = 0; // -1 から 0 に変われば演奏開始。 App.サウンドタイマ.リセットする(); this.現在のフェーズ = フェーズ.表示; // ここで break; すると、次の表示フェーズまで1フレーム分の時間(数ミリ秒)が空いてしまう。 // なので、フレームが空かないように、ここですぐさま最初の表示フェーズを実行する。 this.高速進行する(); //---------------- #endregion } break; case フェーズ.表示: // ※注:クリアや失敗の判定は、ここではなく、進行描画側で行っている。 double 現在の演奏時刻sec = this._演奏開始からの経過時間secを返す(); long 現在の演奏時刻qpc = QPCTimer.生カウント; // AutoPlay 判定 #region " 自動ヒット処理。" //---------------- this._描画範囲内のすべてのチップに対して(現在の演奏時刻sec, (chip, index, ヒット判定バーと描画との時間sec, ヒット判定バーと発声との時間sec, ヒット判定バーとの距離dpx) => { var ユーザ設定 = App.ユーザ管理.ログオン中のユーザ; var ドラムチッププロパティ = ユーザ設定.ドラムチッププロパティ管理[chip.チップ種別]; var AutoPlay = ユーザ設定.AutoPlay[ドラムチッププロパティ.AutoPlay種別]; bool チップはヒット済みである = this._チップの演奏状態[chip].ヒット済みである; bool チップはまだヒットされていない = !(チップはヒット済みである); bool チップはMISSエリアに達している = (ヒット判定バーと描画との時間sec > ユーザ設定.最大ヒット距離sec[判定種別.OK]); bool チップは描画についてヒット判定バーを通過した = (0 <= ヒット判定バーと描画との時間sec); bool チップは発声についてヒット判定バーを通過した = (0 <= ヒット判定バーと発声との時間sec); if (チップはまだヒットされていない && チップはMISSエリアに達している) { #region " MISS判定。" //---------------- if (AutoPlay && ドラムチッププロパティ.AutoPlayON_Miss判定) { this._チップのヒット処理を行う( chip, 判定種別.MISS, ドラムチッププロパティ.AutoPlayON_自動ヒット_再生, ドラムチッププロパティ.AutoPlayON_自動ヒット_判定, ドラムチッププロパティ.AutoPlayON_自動ヒット_非表示, ヒット判定バーと発声との時間sec); return; } else if (!AutoPlay && ドラムチッププロパティ.AutoPlayOFF_Miss判定) { this._チップのヒット処理を行う( chip, 判定種別.MISS, ドラムチッププロパティ.AutoPlayOFF_ユーザヒット_再生, ドラムチッププロパティ.AutoPlayOFF_ユーザヒット_判定, ドラムチッププロパティ.AutoPlayOFF_ユーザヒット_非表示, ヒット判定バーと発声との時間sec); this.成績.エキサイトゲージを加算する(判定種別.MISS); // 手動演奏なら MISS はエキサイトゲージに反映。 return; } else { // 通過。 } //---------------- #endregion } // ヒット処理(1) 発声時刻 if (チップは発声についてヒット判定バーを通過した) // ヒット済みかどうかには関係ない { #region " 自動ヒット判定。" //---------------- if ((AutoPlay && ドラムチッププロパティ.AutoPlayON_自動ヒット_再生) || (!AutoPlay && ドラムチッププロパティ.AutoPlayOFF_自動ヒット_再生)) { // チップの発声がまだなら発声を行う。 if (!(this._チップの演奏状態[chip].発声済みである)) { this.チップの発声を行う(chip, ユーザ設定.ドラムの音を発声する); this._チップの演奏状態[chip].発声済みである = true; } } //---------------- #endregion } // ヒット処理(2) 描画時刻 if (チップはまだヒットされていない && チップは描画についてヒット判定バーを通過した) { #region " 自動ヒット判定。" //---------------- if (AutoPlay && ドラムチッププロパティ.AutoPlayON_自動ヒット) { this._チップのヒット処理を行う( chip, 判定種別.PERFECT, // AutoPlay 時は Perfect 扱い。 ドラムチッププロパティ.AutoPlayON_自動ヒット_再生, ドラムチッププロパティ.AutoPlayON_自動ヒット_判定, ドラムチッププロパティ.AutoPlayON_自動ヒット_非表示, ヒット判定バーと発声との時間sec); //this.成績.エキサイトゲージを加算する( 判定種別.PERFECT ); -> エキサイトゲージには反映しない。 this._ドラムキットとヒットバーEXPERT.ヒットアニメ開始(ドラムチッププロパティ.表示レーン種別); return; } else if (!AutoPlay && ドラムチッププロパティ.AutoPlayOFF_自動ヒット) { this._チップのヒット処理を行う( chip, 判定種別.PERFECT, // AutoPlay OFF でも自動ヒットする場合は Perfect 扱い。 ドラムチッププロパティ.AutoPlayOFF_自動ヒット_再生, ドラムチッププロパティ.AutoPlayOFF_自動ヒット_判定, ドラムチッププロパティ.AutoPlayOFF_自動ヒット_非表示, ヒット判定バーと発声との時間sec); //this.成績.エキサイトゲージを加算する( 判定種別.PERFECT ); -> エキサイトゲージには反映しない。 this._ドラムキットとヒットバーEXPERT.ヒットアニメ開始(ドラムチッププロパティ.表示レーン種別); return; } else { // 通過。 } //---------------- #endregion } }); //---------------- #endregion // 入力(1) 手動演奏 App.入力管理.すべての入力デバイスをポーリングする(入力履歴を記録する: false); #region " ユーザヒット処理。" //---------------- { var ヒット処理済み入力 = new List <ドラム入力イベント>(); // ヒット処理が終わった入力は、二重処理しないよう、この中に追加しておく。 var ユーザ設定 = App.ユーザ管理.ログオン中のユーザ; #region " 描画範囲内のすべてのチップについて、対応する入力があればヒット処理を行う。" //---------------- this._描画範囲内のすべてのチップに対して(現在の演奏時刻sec, (chip, index, ヒット判定バーと描画との時間sec, ヒット判定バーと発声との時間sec, ヒット判定バーとの距離) => { // ユーザ入力については、判定位置調整を適用する。(自動ヒットについては適用しない。) ヒット判定バーと描画との時間sec += (App.システム設定.判定位置調整ms / 1000.0); ヒット判定バーと発声との時間sec += (App.システム設定.判定位置調整ms / 1000.0); #region " チップにヒットしている入力を探す。" //---------------- var ドラムチッププロパティ = ユーザ設定.ドラムチッププロパティ管理[chip.チップ種別]; var AutoPlayである = ユーザ設定.AutoPlay[ドラムチッププロパティ.AutoPlay種別]; bool チップはヒット済みである = this._チップの演奏状態[chip].ヒット済みである; bool チップはMISSエリアに達している = (ヒット判定バーと描画との時間sec > ユーザ設定.最大ヒット距離sec[判定種別.OK]); bool チップは描画についてヒット判定バーを通過した = (0 <= ヒット判定バーと描画との時間sec); bool チップは発声についてヒット判定バーを通過した = (0 <= ヒット判定バーと発声との時間sec); if (チップはヒット済みである || // ヒット済みなら何もしない。 AutoPlayである || // AutoPlay チップなので何もしない。 !(ドラムチッププロパティ.AutoPlayOFF_ユーザヒット) || // このチップは AutoPlay OFF の時でもユーザヒットの対象ではないので何もしない。 !(ヒット判定バーと描画との時間sec >= -(ユーザ設定.最大ヒット距離sec[判定種別.OK]) && !(チップはMISSエリアに達している))) // チップはヒット可能エリアの外にあるので何もしない。 { return; } var チップにヒットしている入力 = App.入力管理.ポーリング結果.FirstOrDefault((入力) => { if (入力.InputEvent.離された || // 押下入力じゃないなら無視。 ヒット処理済み入力.Contains(入力) || // すでに今回のターンで処理済み(=処理済み入力リストに追加済み)なら無視。 入力.Type == ドラム入力種別.HiHat_Control) // HiHat_Control 入力はここでは無視。 { return(false); } var チップの入力グループ = ドラムチッププロパティ.入力グループ種別; // (A) 入力グループ種別 が Unknown の場合 → ドラム入力種別で比較 if (チップの入力グループ == 入力グループ種別.Unknown) { return(ドラムチッププロパティ.ドラム入力種別 == 入力.Type); } // (B) 入力グループ種別が Unknown ではない場合 → 入力グループ種別で比較 else { var 入力の入力グループ種別リスト = from kvp in ユーザ設定.ドラムチッププロパティ管理.チップtoプロパティ where (kvp.Value.ドラム入力種別 == 入力.Type) select kvp.Value.入力グループ種別; foreach (var 入力の入力グループ種別 in 入力の入力グループ種別リスト) { if (チップの入力グループ == 入力の入力グループ種別) { return(true); } } } return(false); }); //---------------- #endregion if (null != チップにヒットしている入力) // チップにヒットした入力があった { #region " チップの手動ヒット処理。" //---------------- ヒット処理済み入力.Add(チップにヒットしている入力); // この入力はこのチップでヒット処理した。 // 入力とチップとの時間差を算出。 double ヒット判定バーと入力との時間sec = QPCTimer.生カウント相対値を秒へ変換して返す(現在の演奏時刻qpc - チップにヒットしている入力.InputEvent.TimeStamp); // 常に正 double 入力とチップの間隔sec = Math.Abs(ヒット判定バーと入力との時間sec - ヒット判定バーと描画との時間sec); // 時間差から判定を算出。 var 判定 = (入力とチップの間隔sec <= ユーザ設定.最大ヒット距離sec[判定種別.PERFECT]) ? 判定種別.PERFECT : (入力とチップの間隔sec <= ユーザ設定.最大ヒット距離sec[判定種別.GREAT]) ? 判定種別.GREAT : (入力とチップの間隔sec <= ユーザ設定.最大ヒット距離sec[判定種別.GOOD]) ? 判定種別.GOOD : 判定種別.OK; // ヒット処理。 this._チップのヒット処理を行う( chip, 判定, (ユーザ設定.ドラムの音を発声する) ? ドラムチッププロパティ.AutoPlayOFF_ユーザヒット_再生 : false, ドラムチッププロパティ.AutoPlayOFF_ユーザヒット_判定, ドラムチッププロパティ.AutoPlayOFF_ユーザヒット_非表示, ヒット判定バーと発声との時間sec); // エキサイトゲージに反映する。 this.成績.エキサイトゲージを加算する(判定); //---------------- #endregion } }); //---------------- #endregion #region " ヒットしてようがしてまいが起こすアクションを実行。" //---------------- { var アクション済み入力 = new List <ドラム入力イベント>(); // ヒット処理が終わった入力は、二重処理しないよう、この中に追加しておく。 foreach (var 入力 in App.入力管理.ポーリング結果) { // 押下入力じゃないなら無視。 if (入力.InputEvent.離された) { continue; } var プロパティs = ユーザ設定.ドラムチッププロパティ管理.チップtoプロパティ.Where((kvp) => (kvp.Value.ドラム入力種別 == 入力.Type)); if (プロパティs.Count() > 0) { //for( int i = 0; i < プロパティs.Count(); i++ ) int i = 0; // 1つの入力で処理するのは、1つの表示レーン種別のみ。 { var laneType = プロパティs.ElementAt(i).Value.表示レーン種別; if (ユーザ設定.演奏モード == PlayMode.BASIC) { this._ドラムパッドBASIC.ヒットする(laneType); this._レーンフラッシュBASIC.開始する(laneType); } if (ユーザ設定.演奏モード == PlayMode.EXPERT) { this._ドラムキットとヒットバーEXPERT.ヒットアニメ開始(laneType); this._レーンフラッシュEXPERT.開始する(laneType); } } } } } //---------------- #endregion #region " どのチップにもヒットしなかった入力は空打ちとみなし、空打ち音を再生する。" //---------------- if (ユーザ設定.ドラムの音を発声する) { foreach (var 入力 in App.入力管理.ポーリング結果) { if (ヒット処理済み入力.Contains(入力) || // ヒット済みなら無視。 入力.InputEvent.離された) // 押下じゃないなら無視。 { continue; } var プロパティs = ユーザ設定.ドラムチッププロパティ管理.チップtoプロパティ.Where((kvp) => (kvp.Value.ドラム入力種別 == 入力.Type)); for (int i = 0; i < プロパティs.Count(); i++) { var prop = プロパティs.ElementAt(i).Value; if (0 < App.演奏スコア.空打ちチップマップ.Count) { #region " DTX他の場合(空うちチップマップ使用)" //---------------- int zz = App.演奏スコア.空打ちチップマップ[prop.レーン種別]; // (A) 空打ちチップの指定があるなら、それを発声する。 if (0 != zz) { App.WAV管理.発声する(zz, prop.チップ種別, prop.発声前消音, prop.消音グループ種別, true); } // (B) 空打ちチップの指定がないなら、一番近いチップを検索し、それを発声する。 else { var chip = this.指定された時刻に一番近いチップを返す(現在の演奏時刻sec, 入力.Type); if (null != chip) { this.チップの発声を行う(chip, true); break; // 複数のチップが該当する場合でも、最初のチップの発声のみ行う。 } } //---------------- #endregion } else { #region " SSTFの場合(空うちチップマップ未使用)" //---------------- App.ドラムサウンド.発声する(prop.チップ種別, 0, prop.発声前消音, prop.消音グループ種別); //---------------- #endregion } } } } //---------------- #endregion ヒット処理済み入力 = null; } //---------------- #endregion // 入力(2) 演奏以外の操作(※演奏中なのでドラム入力は無視。) if (App.入力管理.Keyboard.キーが押された(0, Key.Escape)) { #region " ESC → 演奏中断 " //---------------- Log.Info("ESC キーが押されました。演奏を中断します。"); this.BGMを停止する(); App.WAV管理.すべての発声を停止する(); // DTXでのBGMサウンドはこっちに含まれる。 // 進行描画スレッドへの通知フェーズを挟む。 this.現在のフェーズ = フェーズ.キャンセル通知; //---------------- #endregion } if (App.入力管理.Keyboard.キーが押された(0, Key.Up)) { #region " 上 → 譜面スクロールを加速 " //---------------- const double 最大倍率 = 8.0; App.ユーザ管理.ログオン中のユーザ.譜面スクロール速度 = Math.Min(App.ユーザ管理.ログオン中のユーザ.譜面スクロール速度 + 0.5, 最大倍率); //---------------- #endregion } if (App.入力管理.Keyboard.キーが押された(0, Key.Down)) { #region " 下 → 譜面スクロールを減速 " //---------------- const double 最小倍率 = 0.5; App.ユーザ管理.ログオン中のユーザ.譜面スクロール速度 = Math.Max(App.ユーザ管理.ログオン中のユーザ.譜面スクロール速度 - 0.5, 最小倍率); //---------------- #endregion } if (App.ユーザ管理.ログオン中のユーザ.演奏モード == PlayMode.EXPERT) { #region " ハイハットの開閉 " //---------------- foreach (var ev in App.入力管理.MidiIn.入力イベントリスト.Where((ie) => (255 == ie.Key))) { this._ドラムキットとヒットバーEXPERT.ハイハットの開度を設定する(ev.Velocity); } //---------------- #endregion } break; case フェーズ.キャンセル完了: case フェーズ.キャンセル時フェードアウト: case フェーズ.キャンセル通知: case フェーズ.クリア: break; } } catch (Exception e) { Log.ERROR($"!!! 高速進行スレッドで例外が発生しました !!! [{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( e.Message )}]"); } }