using System; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; /// /// Controller for ProgrammedMovements view: timeline banner at bottom. /// 3 tracks, 0-10 seconds, movement blocks, Run button. /// public class ProgrammedMovementsController : MonoBehaviour { public const int TracksCount = 4; public const int TimelineDurationSeconds = 10; public static readonly Color HighlightBlue = new Color(0.2f, 0.5f, 1f, 1f); [Header("References")] public Camera mainCamera; public RectTransform timelineRoot; public Button runButton; public Button saveButton; public Button loadButton; public GameObject filePickerPanel; public RectTransform filePickerContent; private RectTransform _bannerRoot; private Transform _timelineView; private Transform _configView; private readonly List _blocks = new List(); private readonly Dictionary> _blocksBySecond = new Dictionary>(); private bool _isRunning; private float _runStartTime; private int _lastExecutedSecond = -1; private float _lastRewireTime = -1f; private ModuleBase _highlightedModule; private readonly Dictionary _originalMaterialsByRenderer = new Dictionary(); private MovementBlock _pickModeBlock; private MovementBlock _editingBlock; private ModuleBase _pendingModule; void OnEnable() { ResolveReferences(); if (_bannerRoot == null) { Debug.LogError("[ProgrammedMovements] timelineRoot not set. Assign it in the Inspector."); return; } EnsureTimelineViewShown(); WireUpButtons(); WireSaveLoadButtons(); RefreshRunButton(); // Force layout rebuild so block positions align with timeline after view switch Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate(_bannerRoot); } void EnsureTimelineViewShown() { if (_timelineView != null) _timelineView.gameObject.SetActive(true); if (_configView != null) _configView.gameObject.SetActive(false); } void ResolveReferences() { if (timelineRoot != null) { _bannerRoot = timelineRoot; } else { var pmView = transform.parent; if (pmView == null) return; var canvas = pmView.Find("ProgrammedMovementsCanvas"); if (canvas == null) return; var banner = canvas.Find("TimelineBanner"); if (banner != null) { _bannerRoot = banner.GetComponent(); if (timelineRoot == null) timelineRoot = _bannerRoot; } } if (_bannerRoot != null) { _timelineView = _bannerRoot.Find("TimelineView"); _configView = _bannerRoot.Find("ConfigView"); if (_timelineView == null) { _timelineView = _bannerRoot; } } if (runButton == null && _bannerRoot != null) { var canvas = _bannerRoot.parent; if (canvas != null) { var runGO = canvas.Find("RunButton"); if (runGO != null) runButton = runGO.GetComponent