using System; using System.Collections.Generic; using System.IO; using UnityEngine; public class ComInput : AbstractInputSource { private const int PIN_COUNT = 26; private const char POSITIVE = '0'; private bool[] buttonState = new bool[PIN_COUNT]; private bool[] buttonDown = new bool[PIN_COUNT]; private bool[] buttonUp = new bool[PIN_COUNT]; private Dictionary pinMappings = new(); public override bool Initialize() { LoadPinMappingConfiguration(); ComPortController.InputRecieved += UpdateInputState; return true; } // Обновляет состояния инпута когда приходит новый ввод с платы. Дергается событием. private void UpdateInputState(string input) { for (int i = 0; i < input.Length; i++) { // Получаем новое состояние пина bool newState = input[i] == POSITIVE; // Состояние пина изменилось => пишем в буферы if (newState != buttonState[i]) { if (newState) // Пин был зажат { buttonDown[i] = true; buttonUp[i] = false; } else // Пин был отжат { buttonDown[i] = false; buttonUp[i] = true; } } buttonState[i] = newState; } } public override bool AnyButton() { return false; } public override bool GetButton(InSignal button) => buttonState[GetPhysicalPin(button)]; public override bool GetButtonDown(InSignal button) => buttonDown[GetPhysicalPin(button)]; public override bool GetButtonUp(InSignal button) => buttonUp[GetPhysicalPin(button)]; private int GetPhysicalPin(InSignal button) { if (pinMappings.TryGetValue(button, out int pin)) return pin; // Возвращаем значение по умолчанию (для обратной совместимости) return (int)button; } public override void ResetFrameStates() { for (int i = 0; i < PIN_COUNT; i++) { buttonDown[i] = false; buttonUp[i] = false; } } //private bool ConsumeButtonEvent(bool[] buffer, int pinIndex) //{ // bool result = buffer[pinIndex]; // buffer[pinIndex] = false; // return result; //} /// /// Загружает конфигурацию маппинга пинов из файла elektro_version.rr /// private void LoadPinMappingConfiguration() { ComInputConfig inputConfig = LoadConfigOrDefault(); pinMappings[InSignal.UpLeft] = inputConfig.UpLeft; pinMappings[InSignal.UpRight] = inputConfig.UpRight; pinMappings[InSignal.DownLeft] = inputConfig.DownLeft; pinMappings[InSignal.DownRight] = inputConfig.DownRight; pinMappings[InSignal.CenterSensor] = inputConfig.CenterSensor; pinMappings[InSignal.Service] = inputConfig.Service; } private static ComInputConfig LoadConfigOrDefault() { string fp = Path.Combine(Application.streamingAssetsPath, "Configs", "ComInput.json"); ComInputConfig config; try { if (File.Exists(fp)) { string jsonContent = File.ReadAllText(fp); config = JsonUtility.FromJson(jsonContent); if (config != null) { return config; } } config = new ComInputConfig(); SaveToFile(config, fp); } catch { config = new ComInputConfig(); } return config; } private static void SaveToFile(ComInputConfig device, string filePath) { try { string directory = Path.GetDirectoryName(filePath); if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) { Directory.CreateDirectory(directory); } string jsonContent = JsonUtility.ToJson(device, true); // true для форматирования File.WriteAllText(filePath, jsonContent); } catch (Exception ex) { Debug.LogError($"Ошибка при сохранении ControllerDevice: {ex.Message}"); } } [Serializable] public class ComInputConfig { public int DownLeft = 2; public int DownRight = 1; public int UpLeft = 3; public int UpRight = 0; public int CenterSensor = 25; public int Service = 4; } }