增加ChartJson导出导入

This commit is contained in:
monitor1394
2026-03-25 22:46:26 +08:00
parent dcac0f9655
commit 99e56d238a
15 changed files with 2741 additions and 0 deletions

View File

@@ -19,6 +19,8 @@ namespace XCharts.Editor
public static readonly GUIContent btnSaveAsImage = new GUIContent("Save As Image", "");
public static readonly GUIContent btnCheckWarning = new GUIContent("Check Warning", "");
public static readonly GUIContent btnHideWarning = new GUIContent("Hide Warning", "");
public static readonly GUIContent btnImportJsonData = new GUIContent("Import Json", "");
public static readonly GUIContent btnExportJsonData = new GUIContent("Export Json", "");
}
protected BaseChart m_Chart;
protected SerializedProperty m_Script;
@@ -36,6 +38,7 @@ namespace XCharts.Editor
private bool m_BaseFoldout;
private bool m_CheckWarning = false;
private bool m_ExportPending = false;
private int m_LastComponentCount = 0;
private int m_LastSerieCount = 0;
private string m_VersionString = "";
@@ -300,6 +303,14 @@ namespace XCharts.Editor
m_CheckWarning = false;
}
EditorGUILayout.EndHorizontal();
if (GUILayout.Button(Styles.btnImportJsonData))
{
ChartJsonImportWindow.ShowWindow(m_Chart);
}
if (GUILayout.Button(Styles.btnExportJsonData))
{
RequestExportJsonData();
}
sb.Length = 0;
sb.AppendFormat("v{0}", XChartsMgr.fullVersion);
if (!string.IsNullOrEmpty(m_Chart.warningInfo))
@@ -321,8 +332,47 @@ namespace XCharts.Editor
m_CheckWarning = true;
m_Chart.CheckWarning();
}
if (GUILayout.Button(Styles.btnImportJsonData))
{
ChartJsonImportWindow.ShowWindow(m_Chart);
}
if (GUILayout.Button(Styles.btnExportJsonData))
{
RequestExportJsonData();
}
}
}
private void RequestExportJsonData()
{
if (m_ExportPending) return;
m_ExportPending = true;
var chart = m_Chart;
EditorApplication.delayCall += delegate()
{
m_ExportPending = false;
ExportJsonData(chart);
};
GUIUtility.ExitGUI();
}
private static void ExportJsonData(BaseChart chart)
{
if (chart == null) return;
var json = chart.ExportToJson(true);
var defaultName = chart.gameObject.name + ".json";
var path = EditorUtility.SaveFilePanel("Save Chart JSON", "", defaultName, "json");
if (string.IsNullOrEmpty(path)) return;
try
{
System.IO.File.WriteAllText(path, json);
Debug.Log("[XCharts] JSON exported to: " + path);
}
catch (Exception ex)
{
Debug.LogError("[XCharts] Failed to save JSON: " + ex.Message);
}
}
}
}

View File

@@ -13,10 +13,13 @@ namespace XCharts.Editor
public static readonly GUIContent btnAddComponent = new GUIContent("Add Main Component", "");
public static readonly GUIContent btnRebuildChartObject = new GUIContent("Rebuild Object", "");
public static readonly GUIContent btnSaveAsImage = new GUIContent("Save As Image", "");
public static readonly GUIContent btnImportJsonData = new GUIContent("Import Json", "");
public static readonly GUIContent btnExportJsonData = new GUIContent("Export Json", "");
public static readonly GUIContent btnCheckWarning = new GUIContent("Check Warning", "");
public static readonly GUIContent btnHideWarning = new GUIContent("Hide Warning", "");
}
public UIComponent m_UIComponent;
private bool m_ExportPending;
public static T AddUIComponent<T>(string chartName) where T : UIComponent
{
@@ -56,6 +59,14 @@ namespace XCharts.Editor
{
m_UIComponent.SaveAsImage("png", "", 4f);
}
if (GUILayout.Button(Styles.btnImportJsonData))
{
UIComponentJsonImportWindow.ShowWindow(m_UIComponent);
}
if (GUILayout.Button(Styles.btnExportJsonData))
{
RequestExportJsonData();
}
OnDebugEndInspectorGUI();
}
@@ -89,6 +100,37 @@ namespace XCharts.Editor
EditorGUILayout.PropertyField(property, title);
}
private void RequestExportJsonData()
{
if (m_ExportPending) return;
m_ExportPending = true;
var target = m_UIComponent;
EditorApplication.delayCall += delegate ()
{
m_ExportPending = false;
ExportJsonData(target);
};
GUIUtility.ExitGUI();
}
private static void ExportJsonData(UIComponent target)
{
if (target == null) return;
var json = target.ExportToJson(true);
var defaultName = target.gameObject.name + ".json";
var path = EditorUtility.SaveFilePanel("Save UI Component JSON", "", defaultName, "json");
if (string.IsNullOrEmpty(path)) return;
try
{
System.IO.File.WriteAllText(path, json);
Debug.Log("[XCharts] UI JSON exported to: " + path);
}
catch (System.Exception ex)
{
Debug.LogError("[XCharts] Failed to save UI JSON: " + ex.Message);
}
}
protected void PropertyListField(string relativePropName, bool showOrder = true, params HeaderMenuInfo[] menus)
{
var m_DrawRect = GUILayoutUtility.GetRect(1f, 17f);

View File

@@ -0,0 +1,201 @@
using UnityEditor;
using UnityEngine;
using XCharts.Runtime;
namespace XCharts.Editor
{
public class ChartJsonImportWindow : EditorWindow
{
private const int TEXTAREA_SAFE_CHAR_LIMIT = 8000;
private const int LARGE_JSON_PREVIEW_CHAR_LIMIT = 4000;
private static BaseChart s_TargetChart;
private string m_JsonInput = "";
private Vector2 m_ScrollPos;
private bool m_ShowPreview = false;
private string m_PreviewText = "";
private bool m_OpenFilePending = false;
private bool m_PreviewPending = false;
private bool m_ImportPending = false;
public static void ShowWindow(BaseChart targetChart)
{
s_TargetChart = targetChart;
var window = GetWindow<ChartJsonImportWindow>("Import Chart JSON");
window.minSize = new Vector2(600, 400);
window.Show();
}
private void OnGUI()
{
if (s_TargetChart == null)
{
EditorGUILayout.HelpBox("Target chart is null. Please select a chart first.", MessageType.Error);
if (GUILayout.Button("Close")) Close();
return;
}
if (m_JsonInput == null) m_JsonInput = "";
EditorGUILayout.LabelField("Target Chart: " + s_TargetChart.gameObject.name, EditorStyles.boldLabel);
GUILayout.Space(10);
EditorGUILayout.LabelField("Paste JSON Data:", EditorStyles.boldLabel);
using (var scroll = new EditorGUILayout.ScrollViewScope(m_ScrollPos, GUILayout.Height(250)))
{
m_ScrollPos = scroll.scrollPosition;
if (m_JsonInput.Length <= TEXTAREA_SAFE_CHAR_LIMIT)
{
m_JsonInput = EditorGUILayout.TextArea(m_JsonInput, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
}
else
{
var preview = m_JsonInput.Substring(0, LARGE_JSON_PREVIEW_CHAR_LIMIT);
EditorGUILayout.HelpBox("JSON content is very large. To avoid editor text rendering limits, only a preview is shown below. Import uses full content.", MessageType.Info);
EditorGUILayout.TextArea(preview, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
}
}
EditorGUILayout.HelpBox("Paste JSON directly, or click Open Json File.", MessageType.Info);
GUILayout.Space(10);
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Open Json File", GUILayout.Width(120)))
{
RequestOpenJsonFile();
}
if (GUILayout.Button("Preview", GUILayout.Width(100)))
{
RequestPreviewJson();
}
}
if (m_ShowPreview && !string.IsNullOrEmpty(m_PreviewText))
{
EditorGUILayout.TextArea(m_PreviewText, GUILayout.Height(150));
}
GUILayout.Space(10);
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Import", GUILayout.Height(40), GUILayout.Width(150)))
{
RequestImportJson();
}
if (GUILayout.Button("Cancel", GUILayout.Height(40), GUILayout.Width(150))) Close();
}
}
private void RequestOpenJsonFile()
{
if (m_OpenFilePending) return;
m_OpenFilePending = true;
EditorApplication.delayCall += delegate ()
{
m_OpenFilePending = false;
if (this == null) return;
OpenJsonFile();
Repaint();
};
GUIUtility.ExitGUI();
}
private void RequestPreviewJson()
{
if (m_PreviewPending) return;
m_PreviewPending = true;
EditorApplication.delayCall += delegate ()
{
m_PreviewPending = false;
if (this == null) return;
PreviewJson();
Repaint();
};
GUIUtility.ExitGUI();
}
private void RequestImportJson()
{
if (m_ImportPending) return;
m_ImportPending = true;
EditorApplication.delayCall += delegate ()
{
m_ImportPending = false;
if (this == null) return;
ImportJson();
};
GUIUtility.ExitGUI();
}
private void PreviewJson()
{
if (string.IsNullOrEmpty(m_JsonInput))
{
EditorUtility.DisplayDialog("Error", "JSON input is empty.", "OK");
return;
}
try
{
var json = JsonUtility.FromJson<XCharts.Runtime.ChartJson>(m_JsonInput);
if (json == null)
{
m_PreviewText = "Invalid JSON or unsupported schema.";
}
else
{
var componentCount = json.components != null ? json.components.Count : 0;
var seriesCount = json.series != null ? json.series.Count : 0;
m_PreviewText = "Chart Type: " + json.chartType + "\nComponents: " + componentCount + "\nSeries: " + seriesCount + "\n(Full validation on import)";
}
m_ShowPreview = true;
}
catch (System.Exception ex)
{
EditorUtility.DisplayDialog("Preview Error", "Invalid JSON: " + ex.Message, "OK");
}
}
private void ImportJson()
{
if (string.IsNullOrEmpty(m_JsonInput))
{
EditorUtility.DisplayDialog("Error", "JSON input is empty. Please paste JSON data.", "OK");
return;
}
try
{
Undo.RecordObject(s_TargetChart, "Import Chart JSON");
s_TargetChart.ImportFromJson(m_JsonInput);
s_TargetChart.RebuildChartObject();
s_TargetChart.RefreshAllComponent();
s_TargetChart.RefreshChart();
EditorUtility.SetDirty(s_TargetChart);
UnityEditor.SceneView.RepaintAll();
var chart = s_TargetChart;
EditorApplication.delayCall += delegate ()
{
if (chart == null) return;
chart.RefreshAllComponent();
chart.RefreshChart();
UnityEditor.SceneView.RepaintAll();
};
EditorUtility.DisplayDialog("Success", "Chart '" + s_TargetChart.gameObject.name + "' imported successfully!", "OK");
Close();
}
catch (System.Exception ex)
{
EditorUtility.DisplayDialog("Import Error", "Failed to import JSON:\n" + ex.Message + "\n\n" + ex.StackTrace, "OK");
}
}
private void OpenJsonFile()
{
var path = EditorUtility.OpenFilePanel("Open Chart JSON", "", "json");
if (string.IsNullOrEmpty(path)) return;
try
{
m_JsonInput = System.IO.File.ReadAllText(path);
m_ShowPreview = false;
m_PreviewText = "";
}
catch (System.Exception ex)
{
EditorUtility.DisplayDialog("Open File Error", "Failed to read JSON file:\n" + ex.Message, "OK");
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 21f2eafb07ab34d4abf575784acc56a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,193 @@
using UnityEditor;
using UnityEngine;
using XCharts.Runtime;
namespace XCharts.Editor
{
public class UIComponentJsonImportWindow : EditorWindow
{
private const int TEXTAREA_SAFE_CHAR_LIMIT = 8000;
private const int LARGE_JSON_PREVIEW_CHAR_LIMIT = 4000;
private static UIComponent s_TargetComponent;
private string m_JsonInput = "";
private Vector2 m_ScrollPos;
private bool m_ShowPreview = false;
private string m_PreviewText = "";
private bool m_OpenFilePending = false;
private bool m_PreviewPending = false;
private bool m_ImportPending = false;
public static void ShowWindow(UIComponent target)
{
s_TargetComponent = target;
var window = GetWindow<UIComponentJsonImportWindow>("Import UI JSON");
window.minSize = new Vector2(600, 400);
window.Show();
}
private void OnGUI()
{
if (s_TargetComponent == null)
{
EditorGUILayout.HelpBox("Target UI component is null. Please select a component first.", MessageType.Error);
if (GUILayout.Button("Close")) Close();
return;
}
if (m_JsonInput == null) m_JsonInput = "";
EditorGUILayout.LabelField("Target: " + s_TargetComponent.gameObject.name + " (" + s_TargetComponent.GetType().Name + ")", EditorStyles.boldLabel);
GUILayout.Space(10);
EditorGUILayout.LabelField("Paste JSON Data:", EditorStyles.boldLabel);
using (var scroll = new EditorGUILayout.ScrollViewScope(m_ScrollPos, GUILayout.Height(250)))
{
m_ScrollPos = scroll.scrollPosition;
if (m_JsonInput.Length <= TEXTAREA_SAFE_CHAR_LIMIT)
{
m_JsonInput = EditorGUILayout.TextArea(m_JsonInput, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
}
else
{
var preview = m_JsonInput.Substring(0, LARGE_JSON_PREVIEW_CHAR_LIMIT);
EditorGUILayout.HelpBox("JSON content is very large. Only a preview is shown below. Import uses full content.", MessageType.Info);
EditorGUILayout.TextArea(preview, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
}
}
EditorGUILayout.HelpBox("Paste JSON directly, or click Open Json File.", MessageType.Info);
GUILayout.Space(10);
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Open Json File", GUILayout.Width(120))) RequestOpenJsonFile();
if (GUILayout.Button("Preview", GUILayout.Width(100))) RequestPreviewJson();
}
if (m_ShowPreview && !string.IsNullOrEmpty(m_PreviewText))
{
EditorGUILayout.TextArea(m_PreviewText, GUILayout.Height(120));
}
GUILayout.Space(10);
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Import", GUILayout.Height(40), GUILayout.Width(150))) RequestImportJson();
if (GUILayout.Button("Cancel", GUILayout.Height(40), GUILayout.Width(150))) Close();
}
}
private void RequestOpenJsonFile()
{
if (m_OpenFilePending) return;
m_OpenFilePending = true;
EditorApplication.delayCall += delegate ()
{
m_OpenFilePending = false;
if (this == null) return;
OpenJsonFile();
Repaint();
};
GUIUtility.ExitGUI();
}
private void RequestPreviewJson()
{
if (m_PreviewPending) return;
m_PreviewPending = true;
EditorApplication.delayCall += delegate ()
{
m_PreviewPending = false;
if (this == null) return;
PreviewJson();
Repaint();
};
GUIUtility.ExitGUI();
}
private void RequestImportJson()
{
if (m_ImportPending) return;
m_ImportPending = true;
EditorApplication.delayCall += delegate ()
{
m_ImportPending = false;
if (this == null) return;
ImportJson();
};
GUIUtility.ExitGUI();
}
private void PreviewJson()
{
if (string.IsNullOrEmpty(m_JsonInput))
{
EditorUtility.DisplayDialog("Error", "JSON input is empty.", "OK");
return;
}
try
{
var json = JsonUtility.FromJson<UIComponentJson>(m_JsonInput);
if (json == null)
m_PreviewText = "Invalid JSON or unsupported schema.";
else
m_PreviewText = "Component Type: " + json.componentType + "\nSchema: " + json.schemaVersion + "\nVersion: " + json.componentVersion;
m_ShowPreview = true;
}
catch (System.Exception ex)
{
EditorUtility.DisplayDialog("Preview Error", "Invalid JSON: " + ex.Message, "OK");
}
}
private void ImportJson()
{
if (string.IsNullOrEmpty(m_JsonInput))
{
EditorUtility.DisplayDialog("Error", "JSON input is empty. Please paste JSON data.", "OK");
return;
}
try
{
Undo.RecordObject(s_TargetComponent, "Import UI Component JSON");
s_TargetComponent.ImportFromJson(m_JsonInput);
s_TargetComponent.RebuildChartObject();
s_TargetComponent.RefreshAllComponent();
s_TargetComponent.RefreshGraph();
EditorUtility.SetDirty(s_TargetComponent);
SceneView.RepaintAll();
var target = s_TargetComponent;
EditorApplication.delayCall += delegate ()
{
if (target == null) return;
target.RefreshAllComponent();
target.RefreshGraph();
SceneView.RepaintAll();
};
EditorUtility.DisplayDialog("Success", "UI component imported successfully!", "OK");
Close();
}
catch (System.Exception ex)
{
EditorUtility.DisplayDialog("Import Error", "Failed to import JSON:\n" + ex.Message + "\n\n" + ex.StackTrace, "OK");
}
}
private void OpenJsonFile()
{
var path = EditorUtility.OpenFilePanel("Open UI Component JSON", "", "json");
if (string.IsNullOrEmpty(path)) return;
try
{
m_JsonInput = System.IO.File.ReadAllText(path);
m_ShowPreview = false;
m_PreviewText = "";
}
catch (System.Exception ex)
{
EditorUtility.DisplayDialog("Open File Error", "Failed to read JSON file:\n" + ex.Message, "OK");
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68157a6f7d4e94ccc8ccbb4913d187f3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: