ProjectExporterWindow.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using UnityEditor;
  2. using UnityEngine;
  3. using UnityEngine.UIElements;
  4. using System.Collections.Generic;
  5. namespace ProjectExporter
  6. {
  7. public class ProjectExporterWindow : EditorWindow
  8. {
  9. private ProjectExporterController _controller;
  10. private VisualElement _rootElement;
  11. private VisualElement _contentContainer;
  12. private Dictionary<string, AssetModel> _assetTrees;
  13. private string _currentTab = "Scenes";
  14. [MenuItem("Tools/Project Exporter")]
  15. public static void ShowWindow()
  16. {
  17. ProjectExporterWindow wnd = GetWindow<ProjectExporterWindow>(true, "Project Exporter");
  18. wnd.minSize = new Vector2(400, 300);
  19. }
  20. private void OnEnable()
  21. {
  22. _controller = new ProjectExporterController();
  23. _assetTrees = new Dictionary<string, AssetModel>();
  24. _rootElement = rootVisualElement;
  25. // Build the UI frame without loading asset data initially
  26. BuildUI();
  27. // Trigger the first content refresh
  28. RefreshContent(_currentTab);
  29. }
  30. private void BuildUI()
  31. {
  32. _rootElement.Clear();
  33. var tabContainer = new VisualElement { style = { flexDirection = FlexDirection.Row } };
  34. tabContainer.Add(ProjectExporterUI.CreateTab("Scenes"));
  35. tabContainer.Add(ProjectExporterUI.CreateTab("Prefabs"));
  36. tabContainer.Add(ProjectExporterUI.CreateTab("Scriptable Objects"));
  37. tabContainer.Add(ProjectExporterUI.CreateTab("Meta Files"));
  38. tabContainer.Add(ProjectExporterUI.CreateTab("Settings"));
  39. _rootElement.Add(tabContainer);
  40. // Create a scrollable container for the main content
  41. var scrollView = new ScrollView(ScrollViewMode.Vertical);
  42. _rootElement.Add(scrollView);
  43. _contentContainer = ProjectExporterUI.CreateMainContainer();
  44. scrollView.Add(_contentContainer);
  45. var generateButton = ProjectExporterUI.CreateGenerateButton();
  46. _rootElement.Add(generateButton);
  47. generateButton.clicked += () => _controller.ExportAssets(_assetTrees[_currentTab], _currentTab);
  48. var tabs = tabContainer.Query<Button>().ToList();
  49. tabs[0].clicked += () => RefreshContent("Scenes");
  50. tabs[1].clicked += () => RefreshContent("Prefabs");
  51. tabs[2].clicked += () => RefreshContent("Scriptable Objects");
  52. tabs[3].clicked += () => RefreshContent("Meta Files");
  53. tabs[4].clicked += () => RefreshContent("Settings");
  54. }
  55. private void RefreshContent(string tabName)
  56. {
  57. _currentTab = tabName;
  58. _contentContainer.Clear();
  59. // Load data on demand if it hasn't been loaded yet
  60. if (!_assetTrees.ContainsKey(tabName))
  61. {
  62. EditorUtility.DisplayProgressBar("Loading...", $"Fetching {tabName}...", 0.5f);
  63. try
  64. {
  65. switch (tabName)
  66. {
  67. case "Scenes":
  68. _assetTrees[tabName] = _controller.GetAssets("t:Scene");
  69. break;
  70. case "Prefabs":
  71. _assetTrees[tabName] = _controller.GetAssets("t:Prefab");
  72. break;
  73. case "Scriptable Objects":
  74. _assetTrees[tabName] = _controller.GetAssets("t:ScriptableObject");
  75. break;
  76. case "Meta Files":
  77. _assetTrees[tabName] = _controller.GetAllMetaFiles();
  78. break;
  79. case "Settings":
  80. _assetTrees[tabName] = _controller.GetProjectSettingsFiles();
  81. break;
  82. }
  83. }
  84. finally
  85. {
  86. EditorUtility.ClearProgressBar();
  87. }
  88. }
  89. var rootModel = _assetTrees[tabName];
  90. if (rootModel != null)
  91. {
  92. foreach (var child in rootModel.Children)
  93. {
  94. _contentContainer.Add(CreateAssetView(child, 0));
  95. }
  96. }
  97. }
  98. private VisualElement CreateAssetView(AssetModel model, int indentLevel)
  99. {
  100. const int indentWidth = 20;
  101. if (model.Children.Count > 0)
  102. {
  103. var row = new VisualElement { style = { flexDirection = FlexDirection.Row, alignItems = Align.Center, marginLeft = indentLevel * indentWidth } };
  104. var foldout = ProjectExporterUI.CreateFoldout(model.Name);
  105. foldout.style.flexGrow = 1;
  106. var toggle = new Toggle { value = model.IsSelected, text = "" };
  107. toggle.RegisterValueChangedCallback(evt => {
  108. model.IsSelected = evt.newValue;
  109. SetChildrenSelection(model, evt.newValue);
  110. UpdateChildTogglesUI(foldout, evt.newValue);
  111. });
  112. row.Add(toggle);
  113. row.Add(foldout);
  114. foreach (var child in model.Children)
  115. {
  116. foldout.Add(CreateAssetView(child, indentLevel + 1));
  117. }
  118. return row;
  119. }
  120. else
  121. {
  122. var toggle = ProjectExporterUI.CreateToggle(model.Name);
  123. toggle.style.marginLeft = (indentLevel + 1) * indentWidth;
  124. toggle.value = model.IsSelected;
  125. toggle.RegisterValueChangedCallback(evt => model.IsSelected = evt.newValue);
  126. return toggle;
  127. }
  128. }
  129. private void UpdateChildTogglesUI(VisualElement container, bool isSelected)
  130. {
  131. container.Query<Toggle>().ForEach(childToggle => {
  132. childToggle.SetValueWithoutNotify(isSelected);
  133. });
  134. }
  135. private void SetChildrenSelection(AssetModel parent, bool isSelected)
  136. {
  137. parent.IsSelected = isSelected;
  138. foreach (var child in parent.Children)
  139. {
  140. SetChildrenSelection(child, isSelected);
  141. }
  142. }
  143. }
  144. }