добавил инициализатор , режима подсеветки из инишника

This commit is contained in:
yastreb 2026-03-30 08:29:09 +03:00
parent 0576b481b5
commit d7571d771d
2 changed files with 304 additions and 123 deletions

View File

@ -1,15 +1,15 @@
using System.Collections;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class BlinkController
{
// Интервал мигания по умолчанию (в секундах)
// Интервал мигания по умолчанию (в секундах)
public static float DefaultInterval = 0.5f;
// Внутренний раннер для запуска корутин (динамически создаётся при первом использовании)
// Внутренний раннер для запуска корутин (динамически создаётся при первом использовании)
private class Runner : MonoBehaviour {
// При выходе из приложения выключаем все подсветки
// При выходе из приложения выключаем все подсветки
private void OnApplicationQuit()
{
BlinkController.TurnAllOff();
@ -17,10 +17,10 @@ private void OnApplicationQuit()
}
private static Runner _runner;
// Хранилище запущенных корутин: ключ формируем как "A_1" (тип_игрок)
// Хранилище запущенных корутин: ключ формируем как "A_1" (тип_игрок)
private static readonly Dictionary<string, Coroutine> _coroutines = new Dictionary<string, Coroutine>();
// Убедимся, что раннер существует и живёт на сцене
// Убедимся, что раннер существует и живёт на сцене
private static void EnsureRunner()
{
if (_runner != null) return;
@ -30,92 +30,92 @@ private static void EnsureRunner()
go.hideFlags = HideFlags.HideAndDontSave;
}
// ---- Адресные команды для подсветок A и B (по игроку) ----
// ---- Адресные команды для подсветок A и B (по игроку) ----
public static void LightAOn(int playerId) => ComWrapper.Send("2171", playerId);
public static void LightAOff(int playerId) => ComWrapper.Send("2170", playerId);
public static void LightBOn(int playerId) => ComWrapper.Send("2131", playerId);
public static void LightBOff(int playerId) => ComWrapper.Send("2130", playerId);
// ---- Глобальная подсветка C (broadcast) ----
// ---- Глобальная подсветка C (broadcast) ----
public static void LightCOn() => ComWrapper.Send("401");
public static void LightCOff() => ComWrapper.Send("400");
// ---- Адресные LED диоды (команды 8xxx) ----
// 81хх - канал 1, 82хх - канал 2, 83хх - канал 3, 84хх - канал 4
// 80хх - все каналы сразу
// Программы: 0-None, 1-Repeat, 2-Off, 3-Red, 4-Green, 5-Blue, 6-Gray, 7-White, 9-Rainbow, 10+-Custom
// ---- Адресные LED диоды (команды 8xxx) ----
// 81хх - канал 1, 82хх - канал 2, 83хх - канал 3, 84хх - канал 4
// 80хх - все каналы сразу
// Программы: 0-None, 1-Repeat, 2-Off, 3-Red, 4-Green, 5-Blue, 6-Gray, 7-White, 9-Rainbow, 10+-Custom
/// <summary>Установить программу на канале LED (1-4) для конкретного игрока</summary>
/// <summary>Установить программу на канале LED (1-4) для конкретного игрока</summary>
public static void SetLEDChannel(int channel, int program, int playerId)
{
if (channel < 1 || channel > 4)
{
Debug.LogWarning($"BlinkController: Неверный канал LED {channel}. Допустимо 1-4");
Debug.LogWarning($"BlinkController: Неверный канал LED {channel}. Допустимо 1-4");
return;
}
if (program < 0 || program > 99)
{
Debug.LogWarning($"BlinkController: Неверная программа LED {program}. Допустимо 0-99");
Debug.LogWarning($"BlinkController: Неверная программа LED {program}. Допустимо 0-99");
return;
}
string cmd = $"{80 + channel}{program:D2}";
ComWrapper.Send(cmd, playerId);
Debug.Log($"BlinkController: LED канал {channel} -> программа {program} для игрока {playerId} (cmd: {cmd})");
Debug.Log($"BlinkController: LED канал {channel} -> программа {program} для игрока {playerId} (cmd: {cmd})");
}
/// <summary>Установить программу на всех LED каналах для конкретного игрока</summary>
/// <summary>Установить программу на всех LED каналах для конкретного игрока</summary>
public static void SetLEDAll(int program, int playerId)
{
if (program < 0 || program > 99)
{
Debug.LogWarning($"BlinkController: Неверная программа LED {program}. Допустимо 0-99");
Debug.LogWarning($"BlinkController: Неверная программа LED {program}. Допустимо 0-99");
return;
}
string cmd = $"80{program:D2}";
ComWrapper.Send(cmd, playerId);
Debug.Log($"BlinkController: LED все каналы -> программа {program} для игрока {playerId} (cmd: {cmd})");
Debug.Log($"BlinkController: LED все каналы -> программа {program} для игрока {playerId} (cmd: {cmd})");
}
/// <summary>Установить программу на всех LED каналах глобально (broadcast)</summary>
/// <summary>Установить программу на всех LED каналах глобально (broadcast)</summary>
public static void SetLEDAllGlobal(int program)
{
if (program < 0 || program > 99)
{
Debug.LogWarning($"BlinkController: Неверная программа LED {program}. Допустимо 0-99");
Debug.LogWarning($"BlinkController: Неверная программа LED {program}. Допустимо 0-99");
return;
}
string cmd = $"80{program:D2}";
ComWrapper.Send(cmd);
Debug.Log($"BlinkController: LED все каналы -> программа {program} глобально (cmd: {cmd})");
Debug.Log($"BlinkController: LED все каналы -> программа {program} глобально (cmd: {cmd})");
}
// Быстрые команды для LED (адресные для игрока)
public static void LEDOff(int channel, int playerId) => SetLEDChannel(channel, 2, playerId); // Погасить канал
public static void LEDRed(int channel, int playerId) => SetLEDChannel(channel, 3, playerId); // Красный
public static void LEDGreen(int channel, int playerId) => SetLEDChannel(channel, 4, playerId); // Зеленый
public static void LEDBlue(int channel, int playerId) => SetLEDChannel(channel, 5, playerId); // Синий
public static void LEDWhite(int channel, int playerId) => SetLEDChannel(channel, 7, playerId); // Белый
public static void LEDRainbow(int channel, int playerId) => SetLEDChannel(channel, 9, playerId); // Радуга
// Быстрые команды для LED (адресные для игрока)
public static void LEDOff(int channel, int playerId) => SetLEDChannel(channel, 2, playerId); // Погасить канал
public static void LEDRed(int channel, int playerId) => SetLEDChannel(channel, 3, playerId); // Красный
public static void LEDGreen(int channel, int playerId) => SetLEDChannel(channel, 4, playerId); // Зеленый
public static void LEDBlue(int channel, int playerId) => SetLEDChannel(channel, 5, playerId); // Синий
public static void LEDWhite(int channel, int playerId) => SetLEDChannel(channel, 7, playerId); // Белый
public static void LEDRainbow(int channel, int playerId) => SetLEDChannel(channel, 9, playerId); // Радуга
public static void LEDWave(int channel, int playerId) => SetLEDChannel(channel, 11, playerId); // волна
public static void LEDWave(int channel, int playerId) => SetLEDChannel(channel, 11, playerId); // волна
public static void LEDOffAll(int playerId) => SetLEDAll(2, playerId); // Погасить все для игрока
public static void LEDRedAll(int playerId) => SetLEDAll(3, playerId); // Красный на всех для игрока
public static void LEDGreenAll(int playerId) => SetLEDAll(4, playerId); // Зеленый на всех для игрока
public static void LEDBlueAll(int playerId) => SetLEDAll(5, playerId); // Синий на всех для игрока
public static void LEDWhiteAll(int playerId) => SetLEDAll(7, playerId); // Белый на всех для игрока
public static void LEDRainbowAll(int playerId) => SetLEDAll(9, playerId); // Радуга на всех для игрока
public static void LEDOffAll(int playerId) => SetLEDAll(2, playerId); // Погасить все для игрока
public static void LEDRedAll(int playerId) => SetLEDAll(3, playerId); // Красный на всех для игрока
public static void LEDGreenAll(int playerId) => SetLEDAll(4, playerId); // Зеленый на всех для игрока
public static void LEDBlueAll(int playerId) => SetLEDAll(5, playerId); // Синий на всех для игрока
public static void LEDWhiteAll(int playerId) => SetLEDAll(7, playerId); // Белый на всех для игрока
public static void LEDRainbowAll(int playerId) => SetLEDAll(9, playerId); // Радуга на всех для игрока
// Глобальные команды (broadcast для всех игроков)
public static void LEDOffAllGlobal() => SetLEDAllGlobal(2); // Погасить все глобально
public static void LEDRedAllGlobal() => SetLEDAllGlobal(3); // Красный на всех глобально
public static void LEDGreenAllGlobal() => SetLEDAllGlobal(4); // Зеленый на всех глобально
public static void LEDBlueAllGlobal() => SetLEDAllGlobal(5); // Синий на всех глобально
public static void LEDWhiteAllGlobal() => SetLEDAllGlobal(7); // Белый на всех глобально
public static void LEDRainbowAllGlobal() => SetLEDAllGlobal(9); // Радуга на всех глобально
// Глобальные команды (broadcast для всех игроков)
public static void LEDOffAllGlobal() => SetLEDAllGlobal(2); // Погасить все глобально
public static void LEDRedAllGlobal() => SetLEDAllGlobal(3); // Красный на всех глобально
public static void LEDGreenAllGlobal() => SetLEDAllGlobal(4); // Зеленый на всех глобально
public static void LEDBlueAllGlobal() => SetLEDAllGlobal(5); // Синий на всех глобально
public static void LEDWhiteAllGlobal() => SetLEDAllGlobal(7); // Белый на всех глобально
public static void LEDRainbowAllGlobal() => SetLEDAllGlobal(9); // Радуга на всех глобально
// ---- Переключение цветового чередования (команды 89x) ----
// ---- Переключение цветового чередования (команды 89x) ----
public enum ColorSequence
{
RGB = 0, // 890 - Red, Green, Blue
@ -126,7 +126,7 @@ public enum ColorSequence
GBR = 5 // 895 - Green, Blue, Red
}
/// <summary>Установить цветовое чередование. Если playerId = 0 или не указан - отправка глобально</summary>
/// <summary>Установить цветовое чередование. Если playerId = 0 или не указан - отправка глобально</summary>
public static void SetColorSequence(ColorSequence sequence, int playerId = 0)
{
string cmd = $"89{(int)sequence}";
@ -134,124 +134,124 @@ public static void SetColorSequence(ColorSequence sequence, int playerId = 0)
if (playerId > 0)
{
ComWrapper.Send(cmd, playerId);
Debug.Log($"BlinkController: Цветовое чередование {sequence} для игрока {playerId} (cmd: {cmd})");
Debug.Log($"BlinkController: Цветовое чередование {sequence} для игрока {playerId} (cmd: {cmd})");
}
else
{
ComWrapper.Send(cmd);
Debug.Log($"BlinkController: Цветовое чередование {sequence} глобально (cmd: {cmd})");
Debug.Log($"BlinkController: Цветовое чередование {sequence} глобально (cmd: {cmd})");
}
}
// ---- Произвольный RGB цвет (команда 08RRRGGGBBB) ----
// ---- Произвольный RGB цвет (команда 08RRRGGGBBB) ----
/// <summary>Установить произвольный RGB цвет для LED. Если playerId = 0 - отправка глобально</summary>
/// <param name="r">Красный канал (0-255)</param>
/// <param name="g">Зеленый канал (0-255)</param>
/// <param name="b">Синий канал (0-255)</param>
/// <param name="playerId">ID игрока (0 = глобально)</param>
/// <summary>Установить произвольный RGB цвет на конкретный канал (81-84)</summary>
/// <summary>Установить произвольный RGB цвет для LED. Если playerId = 0 - отправка глобально</summary>
/// <param name="r">Красный канал (0-255)</param>
/// <param name="g">Зеленый канал (0-255)</param>
/// <param name="b">Синий канал (0-255)</param>
/// <param name="playerId">ID игрока (0 = глобально)</param>
/// <summary>Установить произвольный RGB цвет на конкретный канал (81-84)</summary>
public static void SetLEDChannelCustomColor(int channel, int r, int g, int b, int playerId = 0)
{
// Ограничиваем значения
// Ограничиваем значения
channel = Mathf.Clamp(channel, 81, 84);
r = Mathf.Clamp(r, 0, 255);
g = Mathf.Clamp(g, 0, 255);
b = Mathf.Clamp(b, 0, 255);
// Формат: 8X (канал) + 08 (программа произвольный цвет) + RRRGGGBBB
// Формат: 8X (канал) + 08 (программа произвольный цвет) + RRRGGGBBB
string cmd = $"{channel}08{r:D3}{g:D3}{b:D3}";
if (playerId > 0)
{
ComWrapper.Send(cmd, playerId);
Debug.Log($"BlinkController: LED канал {channel} произвольный цвет RGB({r},{g},{b}) для игрока {playerId} (cmd: {cmd})");
Debug.Log($"BlinkController: LED канал {channel} произвольный цвет RGB({r},{g},{b}) для игрока {playerId} (cmd: {cmd})");
}
else
{
ComWrapper.Send(cmd);
Debug.Log($"BlinkController: LED канал {channel} произвольный цвет RGB({r},{g},{b}) глобально (cmd: {cmd})");
Debug.Log($"BlinkController: LED канал {channel} произвольный цвет RGB({r},{g},{b}) глобально (cmd: {cmd})");
}
}
/// <summary>Установить произвольный RGB цвет на все каналы (80)</summary>
/// <summary>Установить произвольный RGB цвет на все каналы (80)</summary>
public static void SetLEDCustomColor(int r, int g, int b, int playerId = 0)
{
// Ограничиваем значения 0-255
// Ограничиваем значения 0-255
r = Mathf.Clamp(r, 0, 255);
g = Mathf.Clamp(g, 0, 255);
b = Mathf.Clamp(b, 0, 255);
// Формат: 80 (все каналы) + 08 (программа произвольный цвет) + RRRGGGBBB
// Формат: 80 (все каналы) + 08 (программа произвольный цвет) + RRRGGGBBB
string cmd = $"8008{r:D3}{g:D3}{b:D3}";
if (playerId > 0)
{
ComWrapper.Send(cmd, playerId);
Debug.Log($"BlinkController: LED произвольный цвет RGB({r},{g},{b}) для игрока {playerId} (cmd: {cmd})");
Debug.Log($"BlinkController: LED произвольный цвет RGB({r},{g},{b}) для игрока {playerId} (cmd: {cmd})");
}
else
{
ComWrapper.Send(cmd);
Debug.Log($"BlinkController: LED произвольный цвет RGB({r},{g},{b}) глобально (cmd: {cmd})");
Debug.Log($"BlinkController: LED произвольный цвет RGB({r},{g},{b}) глобально (cmd: {cmd})");
}
}
// Предустановленные цвета
public static void LEDGold(int playerId = 0) => SetLEDCustomColor(255, 215, 0, playerId); // Золотой
public static void LEDOrange(int playerId = 0) => SetLEDCustomColor(255, 165, 0, playerId); // Оранжевый
public static void LEDPurple(int playerId = 0) => SetLEDCustomColor(128, 0, 128, playerId); // Фиолетовый
public static void LEDPink(int playerId = 0) => SetLEDCustomColor(255, 192, 203, playerId); // Розовый
public static void LEDCyan(int playerId = 0) => SetLEDCustomColor(0, 255, 255, playerId); // Голубой
public static void LEDYellow(int playerId = 0) => SetLEDCustomColor(255, 255, 0, playerId); // Желтый
// Предустановленные цвета
public static void LEDGold(int playerId = 0) => SetLEDCustomColor(255, 215, 0, playerId); // Золотой
public static void LEDOrange(int playerId = 0) => SetLEDCustomColor(255, 165, 0, playerId); // Оранжевый
public static void LEDPurple(int playerId = 0) => SetLEDCustomColor(128, 0, 128, playerId); // Фиолетовый
public static void LEDPink(int playerId = 0) => SetLEDCustomColor(255, 192, 203, playerId); // Розовый
public static void LEDCyan(int playerId = 0) => SetLEDCustomColor(0, 255, 255, playerId); // Голубой
public static void LEDYellow(int playerId = 0) => SetLEDCustomColor(255, 255, 0, playerId); // Желтый
// ---- Мигание LED с возвратом к базовому цвету ----
// ---- Мигание LED с возвратом к базовому цвету ----
private static readonly Dictionary<int, int> _playerBaseLEDColor = new Dictionary<int, int>();
// Храним кастомные RGB цвета для каждого игрока (если установлен)
// Храним кастомные RGB цвета для каждого игрока (если установлен)
private static readonly Dictionary<int, Vector3Int> _playerCustomLEDColor = new Dictionary<int, Vector3Int>();
/// <summary>Установить базовый цвет LED для игрока (к которому возвращаемся после мигания)</summary>
/// <summary>Установить базовый цвет LED для игрока (к которому возвращаемся после мигания)</summary>
public static void SetLEDBaseColor(int playerId, int program)
{
_playerBaseLEDColor[playerId] = program;
_playerCustomLEDColor.Remove(playerId); // Убираем кастомный цвет
_playerCustomLEDColor.Remove(playerId); // Убираем кастомный цвет
SetLEDAll(program, playerId);
Debug.Log($"BlinkController: Базовый LED цвет для игрока {playerId} установлен: {program}");
Debug.Log($"BlinkController: Базовый LED цвет для игрока {playerId} установлен: {program}");
}
/// <summary>Установить базовый кастомный RGB цвет LED для игрока</summary>
/// <summary>Установить базовый кастомный RGB цвет LED для игрока</summary>
public static void SetLEDBaseCustomColor(int playerId, int r, int g, int b)
{
_playerBaseLEDColor[playerId] = -1; // Маркер кастомного цвета
_playerBaseLEDColor[playerId] = -1; // Маркер кастомного цвета
_playerCustomLEDColor[playerId] = new Vector3Int(r, g, b);
SetLEDCustomColor(r, g, b, playerId);
Debug.Log($"BlinkController: Базовый кастомный LED цвет для игрока {playerId} установлен: RGB({r},{g},{b})");
Debug.Log($"BlinkController: Базовый кастомный LED цвет для игрока {playerId} установлен: RGB({r},{g},{b})");
}
/// <summary>Получить базовый цвет LED для игрока</summary>
/// <summary>Получить базовый цвет LED для игрока</summary>
public static int GetLEDBaseColor(int playerId)
{
return _playerBaseLEDColor.TryGetValue(playerId, out int color) ? color : 5; // По умолчанию синий (5)
return _playerBaseLEDColor.TryGetValue(playerId, out int color) ? color : 5; // По умолчанию синий (5)
}
/// <summary>Восстановить базовый цвет LED для игрока (включая кастомные RGB)</summary>
/// <summary>Восстановить базовый цвет LED для игрока (включая кастомные RGB)</summary>
public static void RestoreLEDBaseColor(int playerId)
{
if (_playerCustomLEDColor.TryGetValue(playerId, out Vector3Int rgb))
{
// Восстанавливаем кастомный цвет
// Восстанавливаем кастомный цвет
SetLEDCustomColor(rgb.x, rgb.y, rgb.z, playerId);
}
else
{
// Восстанавливаем обычный цвет по программе
// Восстанавливаем обычный цвет по программе
int baseColor = GetLEDBaseColor(playerId);
SetLEDAll(baseColor, playerId);
}
}
/// <summary>Мигание LED N раз цветом, затем возврат к базовому цвету</summary>
/// <summary>Мигание LED N раз цветом, затем возврат к базовому цвету</summary>
public static void BlinkLED(int playerId, int colorProgram, int times, float interval = 0.3f)
{
EnsureRunner();
@ -262,20 +262,20 @@ private static IEnumerator BlinkLEDRoutine(int playerId, int colorProgram, int t
{
for (int i = 0; i < times; i++)
{
// Включить цвет
// Включить цвет
SetLEDAll(colorProgram, playerId);
yield return new WaitForSeconds(interval);
// Вернуть базовый цвет (включая кастомные RGB)
// Вернуть базовый цвет (включая кастомные RGB)
RestoreLEDBaseColor(playerId);
// Пауза между миганиями (кроме последнего)
// Пауза между миганиями (кроме последнего)
if (i < times - 1)
yield return new WaitForSeconds(interval);
}
}
// Быстрые команды мигания
// Быстрые команды мигания
public static void BlinkLEDRed(int playerId, int times = 1, float interval = 0.3f)
=> BlinkLED(playerId, 3, times, interval);
@ -285,14 +285,14 @@ public static void BlinkLEDGreen(int playerId, int times = 1, float interval = 0
public static void BlinkLEDBlue(int playerId, int times = 1, float interval = 0.3f)
=> BlinkLED(playerId, 5, times, interval);
// ---- Start/Stop мигания ----
// ---- Start/Stop мигания ----
public static void StartBlinkA(int playerId, float interval = -1f)
{
// Оставляем обратную совместимость: бесконечное мигание
// Оставляем обратную совместимость: бесконечное мигание
StartBlinkATimes(playerId, -1, interval);
}
// Мигание N раз (N <= 0 = бесконечно)
// Мигание N раз (N <= 0 = бесконечно)
public static void StartBlinkATimes(int playerId, int times, float interval = -1f)
{
StopBlinkA(playerId);
@ -311,11 +311,11 @@ public static void StopBlinkA(int playerId)
public static void StartBlinkB(int playerId, float interval = -1f)
{
// Оставляем обратную совместимость: бесконечное мигание
// Оставляем обратную совместимость: бесконечное мигание
StartBlinkBTimes(playerId, -1, interval);
}
// Мигание N раз (N <= 0 = бесконечно)
// Мигание N раз (N <= 0 = бесконечно)
public static void StartBlinkBTimes(int playerId, int times, float interval = -1f)
{
StopBlinkB(playerId);
@ -332,14 +332,14 @@ public static void StopBlinkB(int playerId)
LightBOff(playerId);
}
// Глобальная C
// Глобальная C
public static void StartBlinkC(float interval = -1f)
{
// Оставляем обратную совместимость: бесконечное мигание
// Оставляем обратную совместимость: бесконечное мигание
StartBlinkCTimes(-1, interval);
}
// Мигание N раз глобально (N <= 0 = бесконечно)
// Мигание N раз глобально (N <= 0 = бесконечно)
public static void StartBlinkCTimes(int times, float interval = -1f)
{
StopBlinkC();
@ -369,7 +369,7 @@ private static void StopAndRemove(string key)
private static IEnumerator BlinkRoutinePlayer(string key, int playerId, string onCmd, string offCmd, float interval, int repeatCount)
{
// repeatCount <= 0 => бесконечно
// repeatCount <= 0 => бесконечно
if (repeatCount <= 0)
{
while (true)
@ -381,20 +381,20 @@ private static IEnumerator BlinkRoutinePlayer(string key, int playerId, string o
}
}
// Повторяем заданное количество раз
// Повторяем заданное количество раз
for (int i = 0; i < repeatCount; i++)
{
ComWrapper.Send(onCmd, playerId);
yield return new WaitForSeconds(interval);
ComWrapper.Send(offCmd, playerId);
// Между итерациями делаем паузу, как в обычном мигании, кроме последней
// Между итерациями делаем паузу, как в обычном мигании, кроме последней
if (i < repeatCount - 1) yield return new WaitForSeconds(interval);
}
// Гарантируем, что команда выключения послана
// Гарантируем, что команда выключения послана
ComWrapper.Send(offCmd, playerId);
// Удаляем запись о корутине
// Удаляем запись о корутине
try { _coroutines.Remove(key); } catch { }
}
@ -423,84 +423,84 @@ private static IEnumerator BlinkRoutineGlobal(string key, string onCmd, string o
try { _coroutines.Remove(key); } catch { }
}
// Вспомогательные: мгновенный вкл/выкл всех
// Вспомогательные: мгновенный вкл/выкл всех
public static void StopAll()
{
var keys = new List<string>(_coroutines.Keys);
foreach (var k in keys) StopAndRemove(k);
}
// Включить все подсветки (A и B — для обоих игроков, C — глобально)
// Включить все подсветки (A и B — для обоих игроков, C — глобально)
public static void TurnAllOn()
{
Debug.Log("BlinkController: TurnAllOn");
// A и B адресные — для игроков 1 и 2
// A и B адресные — для игроков 1 и 2
LightAOn(1);
LightAOn(2);
LightBOn(1);
LightBOn(2);
// C — глобально
// C — глобально
LightCOn();
// LED - при старте: канал 1 волна, канал 2 радуга для обоих игроков
LEDWave(1, 1); // Игрок 1: канал 1 -> волна
LEDRainbow(2, 1); // Игрок 1: канал 2 -> радуга
LEDWave(1, 2); // Игрок 2: канал 1 -> волна
LEDRainbow(2, 2); // Игрок 2: канал 2 -> радуга
// LED - при старте: канал 1 волна, канал 2 радуга для обоих игроков
LEDWave(1, 1); // Игрок 1: канал 1 -> волна
LEDRainbow(2, 1); // Игрок 1: канал 2 -> радуга
LEDWave(1, 2); // Игрок 2: канал 1 -> волна
LEDRainbow(2, 2); // Игрок 2: канал 2 -> радуга
// Устанавливаем базовый цвет - радуга (для мигания будет возврат к ней)
// Устанавливаем базовый цвет - радуга (для мигания будет возврат к ней)
_playerBaseLEDColor[1] = 9;
_playerBaseLEDColor[2] = 9;
}
// Выключить все подсветки (и остановить корутины)
// Выключить все подсветки (и остановить корутины)
public static void TurnAllOff()
{
Debug.Log("BlinkController: TurnAllOff");
// Остановим все мигания
// Остановим все мигания
StopAll();
// Отправим команды выключения адресно для игроков 1 и 2
// Отправим команды выключения адресно для игроков 1 и 2
try
{
LightAOff(1);
LightAOff(2);
LightBOff(1);
LightBOff(2);
// C — глобально
// C — глобально
LightCOff();
// LED - выключить все каналы глобально
// LED - выключить все каналы глобально
LEDOffAllGlobal();
}
catch (System.Exception e)
{
Debug.LogWarning($"BlinkController: ошибка при TurnAllOff: {e.Message}");
Debug.LogWarning($"BlinkController: ошибка при TurnAllOff: {e.Message}");
}
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
private static void OnRuntimeInitialized()
{
// Подписываемся на событие инициализации ComWrapper — включим подсветки, когда COM будет готов
// Подписываемся на событие инициализации ComWrapper — включим подсветки, когда COM будет готов
try
{
ComWrapper.OnInitialize += TurnAllOn;
// Подписываемся, чтобы выключить подсветки ДО закрытия портов
// Подписываемся, чтобы выключить подсветки ДО закрытия портов
ComWrapper.OnBeforeClose += TurnAllOff;
}
catch
{
// Если ComWrapper ещё не существует или не определён, проигнорируем — вызов произойдёт при инициализации
// Если ComWrapper ещё не существует или не определён, проигнорируем — вызов произойдёт при инициализации
}
// Создаём раннер заранее, чтобы он был доступен и гарантированно существовал
// Создаём раннер заранее, чтобы он был доступен и гарантированно существовал
EnsureRunner();
// Подпишемся на событие выхода приложения — гарантированно выключит подсветки и почистит подписки
// Подпишемся на событие выхода приложения — гарантированно выключит подсветки и почистит подписки
Application.quitting += OnApplicationQuitting;
}
// Обработчик выхода приложения: отписываемся от событий ComWrapper
// Обработчик выхода приложения: отписываемся от событий ComWrapper
private static void OnApplicationQuitting()
{
try { ComWrapper.OnInitialize -= TurnAllOn; } catch { }
@ -513,3 +513,4 @@ private static void OnApplicationQuitting()
}
}
}

View File

@ -0,0 +1,180 @@
using System;
using System.IO;
using UnityEngine;
public static class BlinkStartupInitializer
{
private const string ConfigFileName = "led_startup_config.ini";
private static bool subscribed;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Register()
{
if (subscribed)
return;
subscribed = true;
ComWrapper.OnInitialize += ApplyStartupCommands;
Application.quitting += Unregister;
}
private static void Unregister()
{
ComWrapper.OnInitialize -= ApplyStartupCommands;
Application.quitting -= Unregister;
subscribed = false;
}
private static void ApplyStartupCommands()
{
string configPath = Path.Combine(Application.streamingAssetsPath, ConfigFileName);
try
{
if (!File.Exists(configPath))
{
Directory.CreateDirectory(Application.streamingAssetsPath);
File.WriteAllText(configPath, GetDefaultConfig());
Debug.Log($"BlinkStartupInitializer: создан файл конфигурации {configPath}");
}
string[] lines = File.ReadAllLines(configPath);
for (int i = 0; i < lines.Length; i++)
ProcessLine(lines[i], i + 1);
}
catch (Exception ex)
{
Debug.LogWarning($"BlinkStartupInitializer: ошибка чтения {configPath}: {ex.Message}");
}
}
private static void ProcessLine(string rawLine, int lineNumber)
{
if (string.IsNullOrWhiteSpace(rawLine))
return;
string line = StripComments(rawLine).Trim();
if (string.IsNullOrWhiteSpace(line))
return;
int separatorIndex = line.IndexOf('=');
if (separatorIndex < 0)
{
Debug.LogWarning($"BlinkStartupInitializer: строка {lineNumber} должна быть в формате player1=004 003");
return;
}
string playerToken = line.Substring(0, separatorIndex).Trim();
string commandsToken = line.Substring(separatorIndex + 1).Trim();
if (!TryParsePlayerId(playerToken, out int playerId))
{
Debug.LogWarning($"BlinkStartupInitializer: строка {lineNumber}, неизвестный идентификатор '{playerToken}'");
return;
}
if (string.IsNullOrWhiteSpace(commandsToken))
{
Debug.LogWarning($"BlinkStartupInitializer: строка {lineNumber} не содержит команд");
return;
}
string[] commands = commandsToken.Split(new[] { ' ', '\t', ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string command in commands)
SendValidatedCommand(command, playerId, lineNumber);
}
private static void SendValidatedCommand(string rawCommand, int playerId, int lineNumber)
{
if (!TryNormalizeCommand(rawCommand, out string command))
{
Debug.LogWarning($"BlinkStartupInitializer: строка {lineNumber}, команда '{rawCommand}' некорректна");
return;
}
ComWrapper.Send(command, playerId);
Debug.Log($"BlinkStartupInitializer: отправлена команда {command} для playerId={playerId}");
}
private static bool TryNormalizeCommand(string rawCommand, out string command)
{
command = null;
if (string.IsNullOrWhiteSpace(rawCommand))
return false;
string value = rawCommand.Trim();
if (value.StartsWith("89", StringComparison.Ordinal))
value = value.Substring(2);
if (value.Length != 3)
return false;
if (!char.IsDigit(value[0]) || !char.IsDigit(value[1]) || !char.IsDigit(value[2]))
return false;
int channel = value[0] - '0';
int mode = value[1] - '0';
int sequence = value[2] - '0';
if (channel < 0 || channel > 4)
return false;
if (mode != 0)
return false;
if (sequence < 0 || sequence > 5)
return false;
command = $"89{value}";
return true;
}
private static bool TryParsePlayerId(string token, out int playerId)
{
switch (token.Trim().ToLowerInvariant())
{
case "1":
case "player1":
case "plate1":
playerId = 1;
return true;
case "2":
case "player2":
case "plate2":
playerId = 2;
return true;
default:
playerId = 0;
return false;
}
}
private static string StripComments(string line)
{
int hashIndex = line.IndexOf('#');
int slashIndex = line.IndexOf("//", StringComparison.Ordinal);
int commentIndex = -1;
if (hashIndex >= 0)
commentIndex = hashIndex;
if (slashIndex >= 0 && (commentIndex < 0 || slashIndex < commentIndex))
commentIndex = slashIndex;
return commentIndex >= 0 ? line.Substring(0, commentIndex) : line;
}
private static string GetDefaultConfig()
{
return string.Join(Environment.NewLine, new[]
{
"# Команды инициализации LED-лент.",
"# Формат: player1=004 003",
"# player1/player2 = номер платы = playerId",
"# Команда: X0Z или 89X0Z",
"# X: 0 - все каналы, 1-4 - конкретный канал",
"# Z: 0-RGB, 1-RBG, 2-BRG, 3-BGR, 4-GRB, 5-GBR",
"player1=004",
"player2=004"
});
}
}