using UnityEngine; using UnityEngine.UIElements; namespace EasyChart.UIToolKit { [RequireComponent(typeof(UIDocument))] [AddComponentMenu("EasyChart/UI Toolkit Runtime JSON Injection")] public class UIToolKitRuntimeJsonInjection : MonoBehaviour { [Header("Target")] [Tooltip("Optional. If set, finds the ChartElement by name from UIDocument.rootVisualElement.")] [SerializeField] private string _chartElementName = ""; [Header("JSON Generation Settings")] [Tooltip("The format mode for generating example JSON")] [SerializeField] private ChartJsonExampleMode _exampleMode = ChartJsonExampleMode.Standard; [Tooltip("The data format mode for series data")] [SerializeField] private ChartJsonDatasMode _datasMode = ChartJsonDatasMode.Standard; [Tooltip("Wrap JSON in API response envelope")] [SerializeField] private bool _useApiEnvelope = false; [Tooltip("Automatically regenerate JSON when ExampleMode or DatasMode changes")] [SerializeField] private bool _autoGenerateJson = false; [Header("JSON Content")] [Tooltip("The JSON string to inject into the chart")] [TextArea(10, 30)] [SerializeField] private string _jsonContent = ""; private UIDocument _uiDocument; private ChartProfile _runtimeProfile; private bool _profileCloned; public string ChartElementName { get => _chartElementName; set => _chartElementName = value; } public string JsonContent { get => _jsonContent; set => _jsonContent = value; } public ChartJsonExampleMode ExampleMode { get => _exampleMode; set => _exampleMode = value; } public ChartJsonDatasMode DatasMode { get => _datasMode; set => _datasMode = value; } public bool UseApiEnvelope { get => _useApiEnvelope; set => _useApiEnvelope = value; } public bool AutoGenerateJson { get => _autoGenerateJson; set => _autoGenerateJson = value; } private void Awake() { _uiDocument = GetComponent(); } public bool TryGetChartElement(out EasyChart.ChartElement chartElement) { chartElement = null; if (_uiDocument == null) { _uiDocument = GetComponent(); } if (_uiDocument == null) { Debug.LogWarning("[UIToolKitRuntimeJsonInjection] No UIDocument found."); return false; } var root = _uiDocument.rootVisualElement; if (root == null) { Debug.LogWarning("[UIToolKitRuntimeJsonInjection] UIDocument.rootVisualElement is null."); return false; } if (!string.IsNullOrEmpty(_chartElementName)) { chartElement = root.Q(_chartElementName); } if (chartElement == null) { chartElement = root.Q(); } if (chartElement == null) { Debug.LogWarning("[UIToolKitRuntimeJsonInjection] No ChartElement found in UIDocument."); return false; } return true; } public void ApplyJsonToChart() { if (!TryGetChartElement(out var chartElement) || chartElement.Profile == null) { Debug.LogWarning("[UIToolKitRuntimeJsonInjection] No ChartElement or ChartProfile found."); return; } if (string.IsNullOrWhiteSpace(_jsonContent)) { Debug.LogWarning("[UIToolKitRuntimeJsonInjection] JSON content is empty."); return; } string json = _jsonContent; if (ChartJsonUtils.TryExtractWrappedDataJson(json, out var dataJson) && !string.IsNullOrEmpty(dataJson)) { json = dataJson; } if (!ChartJsonUtils.TryDeserializeFeed(json, out var feed)) { Debug.LogError("[UIToolKitRuntimeJsonInjection] Failed to parse JSON."); return; } // Clone profile on first injection to avoid modifying the original asset EnsureRuntimeProfile(chartElement); ChartJsonUtils.ApplyFeedToProfile(_runtimeProfile, feed); chartElement.ForceRefreshProfile(); Debug.Log("[UIToolKitRuntimeJsonInjection] JSON applied to chart."); } /// /// Ensures we have a runtime copy of the profile to avoid modifying the original asset. /// private void EnsureRuntimeProfile(ChartElement chartElement) { if (_profileCloned) return; var originalProfile = chartElement.Profile; if (originalProfile == null) return; // Create a runtime copy _runtimeProfile = Object.Instantiate(originalProfile); _runtimeProfile.name = originalProfile.name + " (Runtime)"; _runtimeProfile.hideFlags = HideFlags.DontSave; // Assign the cloned profile to the chart element chartElement.Profile = _runtimeProfile; _profileCloned = true; Debug.Log($"[UIToolKitRuntimeJsonInjection] Created runtime copy of profile: {_runtimeProfile.name}"); } public void GenerateExampleJson() { if (!TryGetChartElement(out var chartElement) || chartElement.Profile == null) { Debug.LogWarning("[UIToolKitRuntimeJsonInjection] No ChartElement or ChartProfile found."); return; } var profile = chartElement.Profile; profile.EnsureRuntimeData(); string json = ChartJsonUtils.BuildInjectionJson(profile, profile.chartId, _exampleMode, _datasMode); _jsonContent = _useApiEnvelope ? ChartJsonUtils.WrapAsApiResponse(json) : json; } } }