Skip to content

Commit 5ebceb5

Browse files
committed
トリガー機能を追加
1 parent 8f6e2b4 commit 5ebceb5

8 files changed

Lines changed: 360 additions & 40 deletions

MacroPlayer.cs

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Nefarius.ViGEm.Client.Targets.Xbox360;
2+
using Nefarius.ViGEm.Client; // IXbox360Controller の定義元
23
using System;
34
using System.Collections.Generic;
45
using System.Globalization;
@@ -168,6 +169,215 @@ await Task.Run(() =>
168169
}, token);
169170
}
170171

172+
// PlayAsyncの引数にジョイスティックと設定を追加
173+
public async Task PlayAsync(
174+
List<string> macroNames,
175+
double frameMs,
176+
int playWaitFrames,
177+
bool isRepeat,
178+
bool isRandom,
179+
bool xAxisReverse,
180+
int frame,
181+
CancellationToken token,
182+
SharpDX.DirectInput.Joystick joystick = null,
183+
RecordSettingsForm.RecordSettingsConfig recordConfig = null)
184+
{
185+
var macroTriggers = new List<(string macroName, List<string> triggers, List<string> waitActions)>();
186+
foreach (var macroName in macroNames)
187+
{
188+
var macroText = File.ReadAllText(Path.Combine(macroFolder, macroName + ".csv"));
189+
var lines = macroText.Split('\n');
190+
var triggers = new List<string>();
191+
var waitActions = new List<string>();
192+
foreach (var line in lines)
193+
{
194+
var trimmed = line.Trim();
195+
if (trimmed.StartsWith("#TRIGGER:"))
196+
{
197+
triggers = trimmed.Substring("#TRIGGER:".Length)
198+
.Split(',')
199+
.Select(x =>
200+
{
201+
var key = x.Trim().ToUpper();
202+
if (xAxisReverse)
203+
{
204+
if (key == "LEFT") key = "RIGHT";
205+
else if (key == "RIGHT") key = "LEFT";
206+
}
207+
return key;
208+
})
209+
.Where(x => !string.IsNullOrEmpty(x))
210+
.ToList();
211+
}
212+
if (trimmed.StartsWith("#TRIGGERWAIT:"))
213+
{
214+
waitActions = trimmed.Substring("#TRIGGERWAIT:".Length)
215+
.Split(',')
216+
.Select(x =>
217+
{
218+
var key = x.Trim().ToUpper();
219+
if (xAxisReverse)
220+
{
221+
if (key == "LEFT") key = "RIGHT";
222+
else if (key == "RIGHT") key = "LEFT";
223+
}
224+
return key;
225+
})
226+
.Where(x => !string.IsNullOrEmpty(x))
227+
.ToList();
228+
}
229+
if (!trimmed.StartsWith("#") && (trimmed.Contains(":") || (trimmed.Length > 0 && !trimmed.StartsWith("#"))))
230+
break;
231+
}
232+
macroTriggers.Add((macroName, triggers, waitActions));
233+
}
234+
235+
var triggerMacros = macroTriggers.Where(mt => mt.triggers.Count > 0).ToList();
236+
// デバッグ出力追加
237+
System.Diagnostics.Debug.WriteLine("[MacroPlayer] triggerMacros:");
238+
foreach (var mt in triggerMacros)
239+
{
240+
System.Diagnostics.Debug.WriteLine(
241+
$" macroName={mt.macroName}, triggers=[{string.Join(",", mt.triggers)}], waitActions=[{string.Join(",", mt.waitActions)}]"
242+
);
243+
}
244+
System.Diagnostics.Debug.WriteLine($"[MacroPlayer] joystick: {(joystick == null ? "null" : joystick.ToString())}");
245+
System.Diagnostics.Debug.WriteLine($"[MacroPlayer] recordConfig: {(recordConfig == null ? "null" : $"ControllerGuid={recordConfig.ControllerGuid}, ButtonIndices={string.Join(",", recordConfig.ButtonIndices.Select(kv => kv.Key + "=" + (kv.Value?.ToString() ?? "null")))} ZValues={string.Join(",", recordConfig.ZValues.Select(kv => kv.Key + "=" + (kv.Value?.ToString() ?? "null")))}")}");
246+
247+
// 判定部分
248+
if (triggerMacros.Count == 0 || joystick == null || recordConfig == null)
249+
{
250+
System.Diagnostics.Debug.WriteLine("[MacroPlayer] PlayAsync(基本) 実行");
251+
await PlayAsync(
252+
macroNames,
253+
frameMs,
254+
playWaitFrames,
255+
isRepeat,
256+
isRandom,
257+
xAxisReverse,
258+
frame,
259+
token
260+
);
261+
return;
262+
}
263+
264+
// すべてのTRIGGERWAIT定義から最初のボタン群を抽出
265+
List<string> prioritizedWaitActions = null;
266+
foreach (var mt in triggerMacros)
267+
{
268+
if (mt.waitActions.Count > 0)
269+
{
270+
prioritizedWaitActions = mt.waitActions;
271+
break;
272+
}
273+
}
274+
275+
276+
// ジョイスティック判定
277+
Random rand = new Random();
278+
while (!token.IsCancellationRequested)
279+
{
280+
// トリガー待ちの間は prioritizedWaitActions のボタンを押す
281+
if (prioritizedWaitActions != null && prioritizedWaitActions.Count > 0)
282+
{
283+
var keyState = new MacroKeyState();
284+
foreach (var kv in prioritizedWaitActions)
285+
{
286+
string key = kv.ToUpper();
287+
// --- エイリアス対応 ---
288+
if (key == "LP") key = "X";
289+
else if (key == "LK") key = "A";
290+
else if (key == "MP") key = "Y";
291+
else if (key == "MK") key = "B";
292+
else if (key == "HP") key = "RB";
293+
else if (key == "HK") key = "LB";
294+
keyState.KeyStates[key] = true;
295+
}
296+
297+
short y = 0, x = 0;
298+
if (keyState.KeyStates["UP"] && !keyState.KeyStates["DOWN"]) y = short.MaxValue;
299+
else if (keyState.KeyStates["DOWN"] && !keyState.KeyStates["UP"]) y = short.MinValue;
300+
301+
bool reverse = xAxisReverse;
302+
if (!reverse)
303+
{
304+
if (keyState.KeyStates["LEFT"] && !keyState.KeyStates["RIGHT"]) x = short.MinValue;
305+
else if (keyState.KeyStates["RIGHT"] && !keyState.KeyStates["LEFT"]) x = short.MaxValue;
306+
}
307+
else
308+
{
309+
if (keyState.KeyStates["LEFT"] && !keyState.KeyStates["RIGHT"]) x = short.MaxValue;
310+
else if (keyState.KeyStates["RIGHT"] && !keyState.KeyStates["LEFT"]) x = short.MinValue;
311+
}
312+
313+
// 軸・ボタンを直接コントローラーに反映
314+
controllerService.Controller.SetAxisValue(Xbox360Axis.LeftThumbY, y);
315+
controllerService.Controller.SetAxisValue(Xbox360Axis.LeftThumbX, x);
316+
317+
controllerService.Controller.SetButtonState(Xbox360Button.A, keyState.KeyStates["A"]);
318+
controllerService.Controller.SetButtonState(Xbox360Button.B, keyState.KeyStates["B"]);
319+
controllerService.Controller.SetButtonState(Xbox360Button.X, keyState.KeyStates["X"]);
320+
controllerService.Controller.SetButtonState(Xbox360Button.Y, keyState.KeyStates["Y"]);
321+
controllerService.Controller.SetButtonState(Xbox360Button.LeftShoulder, keyState.KeyStates["LB"]);
322+
controllerService.Controller.SetButtonState(Xbox360Button.RightShoulder, keyState.KeyStates["RB"]);
323+
}
324+
325+
bool triggered = false;
326+
while (!triggered && !token.IsCancellationRequested)
327+
{
328+
var state = joystick.GetCurrentState();
329+
var pressedKeys = new List<string>();
330+
331+
foreach (var kv in recordConfig.ButtonIndices)
332+
{
333+
if (kv.Value != null && state.Buttons.Length > kv.Value.Value && state.Buttons[kv.Value.Value])
334+
pressedKeys.Add(kv.Key.Replace("Button", ""));
335+
}
336+
foreach (var kv in recordConfig.ZValues)
337+
{
338+
if (kv.Value != null && state.Z == kv.Value.Value)
339+
pressedKeys.Add(kv.Key.Replace("Button", ""));
340+
}
341+
if (state.PointOfViewControllers != null && state.PointOfViewControllers.Length > 0)
342+
{
343+
int pov = state.PointOfViewControllers[0];
344+
if (pov == 0) pressedKeys.Add("UP");
345+
else if (pov == 9000) pressedKeys.Add("RIGHT");
346+
else if (pov == 18000) pressedKeys.Add("DOWN");
347+
else if (pov == 27000) pressedKeys.Add("LEFT");
348+
else if (pov == 4500) { pressedKeys.Add("UP"); pressedKeys.Add("RIGHT"); }
349+
else if (pov == 13500) { pressedKeys.Add("DOWN"); pressedKeys.Add("RIGHT"); }
350+
else if (pov == 22500) { pressedKeys.Add("DOWN"); pressedKeys.Add("LEFT"); }
351+
else if (pov == 31500) { pressedKeys.Add("UP"); pressedKeys.Add("LEFT"); }
352+
}
353+
354+
355+
// TRIGGER判定
356+
var triggerdMacros = new List<string>();
357+
foreach (var mt in triggerMacros)
358+
{
359+
if (mt.triggers.All(t => pressedKeys.Contains(t)))
360+
{
361+
triggerdMacros.Add(mt.macroName);
362+
}
363+
}
364+
365+
if (triggerdMacros.Count > 0)
366+
{
367+
controllerService.AllOff();
368+
System.Diagnostics.Debug.WriteLine("[MacroPlayer] PlayAsync(ジョイスティック/設定付き) 実行");
369+
await PlayAsync(
370+
triggerdMacros,
371+
frameMs, 0, false, isRandom, xAxisReverse, frame, token
372+
);
373+
triggered = true;
374+
}
375+
await Task.Delay(10, token);
376+
}
377+
}
378+
return;
379+
}
380+
171381
// MacroKeyStateを内包
172382
private class MacroKeyState
173383
{

MainForm.cs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,12 @@ public partial class MainForm : Form
3737
private MacroPlayer macroPlayer;
3838
private SharpDX.DirectInput.DirectInput directInput;
3939
private SharpDX.DirectInput.Joystick currentJoystick;
40+
private RecordSettingsForm.RecordSettingsConfig recordConfig;
4041

4142
// MainForm クラス内フィールド追加
4243
private bool isRecording = false;
4344
private List<Dictionary<string, string>> recordedFrames = new List<Dictionary<string, string>>();
44-
private System.Windows.Forms.Timer recordTimer;
4545
private DateTime recordStartTime;
46-
private RecordSettingsForm.RecordSettingsConfig recordConfig;
4746

4847
/// <summary>
4948
/// 必要なデザイナー変数です。
@@ -77,12 +76,14 @@ public MainForm()
7776
LoadMacroList();
7877
}
7978

79+
// --- 1. 起動時(Form1_Load)で設定ファイルを読み込む ---
8080
private void Form1_Load(object sender, EventArgs e)
8181
{
8282
// --- Form1_Loadでコントローラ操作ボタンを有効化 ---
8383
this.SetControllerButtonsEnabled(true); // ← 常に有効化
8484
PlayMacroButton.Text = "再生";
8585
LoadMacroSettings();
86+
recordConfig = LoadRecordSettingsConfig(); // ← 追加
8687
if (IsRecordSettingsValid())
8788
{
8889
ConnectRecordController();
@@ -134,6 +135,7 @@ private void PlayMacroButton_Click(object sender, EventArgs e)
134135
OverwriteMacro();
135136
}
136137

138+
137139
// UI制御
138140
PlayMacroButton.Enabled = false;
139141
PlayMacroButton.Text = "再生中...";
@@ -174,7 +176,9 @@ await macroPlayer.PlayAsync(
174176
isRandom,
175177
XAxisReverseCheckBox.Checked,
176178
frame,
177-
token
179+
token,
180+
currentJoystick,
181+
recordConfig
178182
);
179183
}
180184
finally
@@ -898,6 +902,7 @@ private void RecSettingButton_Click(object sender, EventArgs e)
898902
var result = dlg.ShowDialog(this);
899903
if (result == DialogResult.OK)
900904
{
905+
recordConfig = LoadRecordSettingsConfig(); // ← 追加
901906
if (IsRecordSettingsValid())
902907
{
903908
ConnectRecordController();
@@ -995,18 +1000,7 @@ private async void RecButton_Click(object sender, EventArgs e)
9951000
MessageBox.Show("記録設定が不正です。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
9961001
return;
9971002
}
998-
999-
// 設定ファイル読み込み
1000-
var configPath = Path.Combine(Application.StartupPath, "RecordSettingsConfig.json");
1001-
using (var fs = new FileStream(configPath, FileMode.Open))
1002-
{
1003-
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(
1004-
typeof(RecordSettingsForm.RecordSettingsConfig),
1005-
new System.Runtime.Serialization.Json.DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true }
1006-
);
1007-
recordConfig = (RecordSettingsForm.RecordSettingsConfig)serializer.ReadObject(fs);
1008-
}
1009-
1003+
// recordConfig = LoadRecordSettingsConfig(); ← 削除
10101004
recordedFrames.Clear();
10111005
recordStartTime = DateTime.Now;
10121006
int frameMs = 16;
@@ -1244,5 +1238,20 @@ private void SaveRecordedMacro(bool overwrite)
12441238
}
12451239
}
12461240
}
1241+
1242+
// --- 1. 設定ファイル読み込み関数を追加 ---
1243+
private RecordSettingsForm.RecordSettingsConfig LoadRecordSettingsConfig()
1244+
{
1245+
var configPath = Path.Combine(Application.StartupPath, "RecordSettingsConfig.json");
1246+
if (!File.Exists(configPath)) return null;
1247+
using (var fs = new FileStream(configPath, FileMode.Open))
1248+
{
1249+
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(
1250+
typeof(RecordSettingsForm.RecordSettingsConfig),
1251+
new System.Runtime.Serialization.Json.DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true }
1252+
);
1253+
return (RecordSettingsForm.RecordSettingsConfig)serializer.ReadObject(fs);
1254+
}
1255+
}
12471256
}
12481257
}

0 commit comments

Comments
 (0)