当前位置: 首页 > article >正文

Unity editor文件数UI(支持勾选框)

unity editor文件数(支持勾选框)

使用的时候new一个box即可

using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[Serializable]
public class TGFileTreeViewBox<T> where T : OdinMenuEditorWindow
{public TGFileTreeView fileTreeView;private Vector2 scrollPosition;public TGFileTreeViewBox(bool ShowCheckboxes = true){fileTreeView = new TGFileTreeView(new List<string>(), ThisRepaint);fileTreeView.ShowCheckboxes = ShowCheckboxes;//fileTreeView = new TGFileTreeView(GetFilePathsTest(), ThisRepaint);fileTreeView.SelectAll();}public TGFileTreeViewBox(List<string> paths, bool ShowCheckboxes = true){//for (int i = 0; i < paths.Count; i++)//{//    Logger.Log($"文件夹树视图:{paths[i]}");//}fileTreeView = new TGFileTreeView(paths, ThisRepaint);fileTreeView.ShowCheckboxes = ShowCheckboxes;//fileTreeView = new TGFileTreeView(GetFilePathsTest(), ThisRepaint);//fileTreeView.ToggleExpandAll(true);fileTreeView.SelectAll();}[OnInspectorGUI]private void DrawCustomInspector(){float contentHeight = fileTreeView.GetHeight();float maxHeight = Mathf.Min(contentHeight, 250f);scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(maxHeight));fileTreeView.DrawTreeView();//if (GUILayout.Button("打印选中路径"))//{//    foreach (var path in fileTreeView.CheckedPaths)//    {//        Logger.Log($"选中了--{path}");//    }//}//if (GUILayout.Button("打印未选中路径"))//{//    foreach (var path in fileTreeView.UncheckedPaths)//    {//        Logger.Log($"未选中--{path}");//    }//}//if (GUILayout.Button("打印选中文件路径"))//{//    foreach (var path in fileTreeView.CheckedFilePaths)//    {//        Logger.Log($"选中文件了--{path}");//    }//}GUILayout.EndScrollView();}// 刷新界面的方法public static void ThisRepaint(){var window = UnityEditor.EditorWindow.GetWindow<T>();window?.Repaint();}private static List<string> GetFilePathsTest(){// 直接定义路径数据return new List<string>{"Assets/_Test/sedan.prefab","Assets/_Test/mat/New Material.mat","Assets/_Test/mat/New Material 1.mat","Assets/_Test/mat/New Material 2.mat","Assets/_Test/mat/New Material 3.mat","Assets/_Test/New Material 1.mat","Assets/_Test/New Material 2.mat","Assets/_Test/New Material 3.mat","Assets/_Test/New Material 4.mat","Assets/_Test/New Material.mat","Assets/_Test/source/sedan.fbx","Assets/_Test/source/sedan 1.fbx","Assets/_Test/TestNull","Assets/_Test/textures/internal_ground_ao_texture.jpeg","Assets/_Test/textures/internal_ground_ao_texture 1.jpeg","Assets/_Test/textures/internal_ground_ao_texture 2.jpeg","Assets/_Test/textures/internal_ground_ao_texture 3.jpeg","Assets/_Test/textures/internal_ground_ao_texture 4.jpeg","Assets/_Test/textures/internal_ground_ao_texture 5.jpeg","Assets/_Test/textures/internal_ground_ao_texture 6.jpeg","Assets/_Test/textures/internal_ground_ao_texture 7.jpeg","Assets/_Test/textures/internal_ground_ao_texture 8.jpeg","Assets/_Test/textures/internal_ground_ao_texture 9.jpeg","Assets/_Test/textures/internal_ground_ao_texture 10.jpeg","Assets/_Test/textures/internal_ground_ao_texture.tga"};}
}
using Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;public class TGFileTreeView
{private List<string> allfilePaths = new List<string>(); // 传入的路径private List<string> filePaths = new List<string>(); // 当前有效路径,经过过滤private List<string> checkedPaths = new List<string>(); // 勾选的路径private List<string> uncheckedPaths = new List<string>(); // 未勾选的路径private List<string> checkedFilePaths = new List<string>(); // 选中的文件路径列表private Dictionary<string, bool> foldoutStates = new Dictionary<string, bool>();private Dictionary<string, bool> checkboxStates = new Dictionary<string, bool>();private string selectedFilePath = "";private Action repaintAction;private int treeHeight;private bool isExpandAll = true;public List<string> CheckedPaths => checkedPaths;public List<string> UncheckedPaths => uncheckedPaths;public List<string> AllPaths => allfilePaths; // 传入的路径列表public List<string> CurrentValidPaths => filePaths; // 当前有效路径public List<string> CheckedFilePaths //选中的文件路径列表{get{checkedFilePaths.Clear();foreach (var item in checkedPaths){if (Path.HasExtension(item)){checkedFilePaths.Add(item);}}return checkedFilePaths;}}public Action<string, bool> OnCheckStateChanged; // path 和状态public bool ShowCheckboxes = true; // 全局控制是否显示勾选框public TGFileTreeView(List<string> paths, System.Action repaintAction){allfilePaths = paths;this.repaintAction = repaintAction;InitializePaths();}// 初始化时计算有效路径,并根据勾选状态更新 CheckedPaths 和 UncheckedPathsprivate void InitializePaths(){// 过滤出有效路径filePaths = allfilePaths.Where(path => File.Exists(path) || Directory.Exists(path)).ToList();// 初始化勾选与取消勾选的路径checkedPaths = new List<string>();uncheckedPaths = new List<string>();foreach (var path in filePaths){checkboxStates[path] = false;uncheckedPaths.Add(path);}}public void DrawTreeView(){CheckForDeletedFiles();if (filePaths.Count == 0){EditorGUILayout.LabelField("没有可用的文件路径!!");return;}DrawFileTree(filePaths);}private void CheckForDeletedFiles(){filePaths.Clear();foreach (var path in allfilePaths){if (File.Exists(path) || Directory.Exists(path)){filePaths.Add(path);}}}private void DrawFileTree(List<string> paths){TGTreeNode root = BuildTree(paths);treeHeight = GetTotalHeight(root);DrawNode(root, 0);}private void DrawNode(TGTreeNode node, int indentLevel){EditorGUILayout.BeginHorizontal();if (!foldoutStates.ContainsKey(node.Path))foldoutStates[node.Path] = isExpandAll;if (!checkboxStates.ContainsKey(node.Path)){checkboxStates[node.Path] = false;UpdateCheckboxLists(node.Path, false);}float lineHeight = 20f;float indentX = indentLevel * 20f;float foldoutWidth = 14f;float spacingA = 20f; // 箭头和勾选框之间float toggleWidth = 18f;float spacingB = 4f; // 勾选框和图标之间float iconWidth = 20f;float spacingC = 4f; // 图标和文件名之间Rect lineRect = GUILayoutUtility.GetRect(0, lineHeight, GUILayout.ExpandWidth(true));float x = lineRect.x + indentX;// 折叠箭头if (node.IsFolder && node.Children.Count > 0){Rect foldoutRect = new Rect(x, lineRect.y + 3, foldoutWidth, 14f);foldoutStates[node.Path] = EditorGUI.Foldout(foldoutRect, foldoutStates[node.Path], GUIContent.none, false);x += foldoutWidth + spacingA;}else{x += foldoutWidth + spacingA;}// 勾选框if (ShowCheckboxes){// 勾选框Rect toggleRect = new Rect(x, lineRect.y + 1, toggleWidth, 18f);bool oldChecked = checkboxStates[node.Path];bool newChecked = GUI.Toggle(toggleRect, oldChecked, GUIContent.none);if (oldChecked != newChecked){checkboxStates[node.Path] = newChecked;UpdateCheckboxLists(node.Path, newChecked);}x += toggleWidth + spacingB;}else{x += spacingB; // 保留缩进对齐}// 图标Texture icon = GetIconForPath(node.Path, node.IsFolder);if (icon != null){Rect iconRect = new Rect(x, lineRect.y, iconWidth, 20f);GUI.DrawTexture(iconRect, icon);x += iconWidth + spacingC;}// 文件名Rect labelRect = new Rect(x, lineRect.y, lineRect.width - (x - lineRect.x), lineHeight);GUIContent labelContent = new GUIContent(GetFileName(node.Path));if (selectedFilePath == node.Path)EditorGUI.DrawRect(lineRect, new Color(0.24f, 0.49f, 0.90f, 0.3f));HandleClick(labelRect, node.Path);GUI.Label(labelRect, labelContent);EditorGUILayout.EndHorizontal();if (node.IsFolder && foldoutStates[node.Path]){foreach (var child in node.Children){DrawNode(child, indentLevel + 1);}}}private void UpdateCheckboxLists(string path, bool isChecked){checkboxStates[path] = isChecked;if (isChecked){if (!checkedPaths.Contains(path)) checkedPaths.Add(path);uncheckedPaths.Remove(path);}else{if (!uncheckedPaths.Contains(path)) uncheckedPaths.Add(path);checkedPaths.Remove(path);}// 更新子项状态var keys = checkboxStates.Keys.ToList();foreach (var kvp in keys){if (kvp != path && kvp.StartsWith(path + "/")){checkboxStates[kvp] = isChecked;if (isChecked){if (!checkedPaths.Contains(kvp)) checkedPaths.Add(kvp);uncheckedPaths.Remove(kvp);}else{if (!uncheckedPaths.Contains(kvp)) uncheckedPaths.Add(kvp);checkedPaths.Remove(kvp);}}}OnCheckStateChanged?.Invoke(path, isChecked);UpdateParentCheckboxStates(path);}private void UpdateParentCheckboxStates(string path){string parentPath = GetParentPath(path);if (string.IsNullOrEmpty(parentPath)) return;var childPaths = checkboxStates.Keys.Where(k => GetParentPath(k) == parentPath).ToList();bool anyChildChecked = childPaths.Any(k => checkboxStates.ContainsKey(k) && checkboxStates[k]);checkboxStates[parentPath] = anyChildChecked;if (anyChildChecked){if (!checkedPaths.Contains(parentPath)) checkedPaths.Add(parentPath);uncheckedPaths.Remove(parentPath);}else{if (!uncheckedPaths.Contains(parentPath)) uncheckedPaths.Add(parentPath);checkedPaths.Remove(parentPath);}UpdateParentCheckboxStates(parentPath);}private string GetParentPath(string path){if (string.IsNullOrEmpty(path)) return null;int lastSlashIndex = path.LastIndexOf('/');if (lastSlashIndex <= 0) return null;return path.Substring(0, lastSlashIndex);}private void HandleClick(Rect rect, string path){Event e = Event.current;if (e.type == EventType.MouseDown && rect.Contains(e.mousePosition)){if (e.clickCount == 1){selectedFilePath = path;repaintAction?.Invoke();}else if (e.clickCount == 2){if (File.Exists(path) || Directory.Exists(path)){EditorUtility.FocusProjectWindow();UnityEngine.Object asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path);if (asset != null){EditorGUIUtility.PingObject(asset);Selection.activeObject = asset;}}}e.Use();}}private TGTreeNode BuildTree(List<string> paths){TGTreeNode root = new TGTreeNode("Assets", true);foreach (string path in paths){string[] parts = path.Split('/');TGTreeNode current = root;for (int i = 1; i < parts.Length; i++){string part = parts[i];string fullPath = string.Join("/", parts, 0, i + 1);bool isFile = (i == parts.Length - 1) && Path.HasExtension(part);if (!current.HasChild(part)){current.Children.Add(new TGTreeNode(fullPath, !isFile));}current = current.GetChild(part);}}return root;}private string GetFileName(string path){return Path.GetFileName(path);}private int GetTotalHeight(TGTreeNode node){int totalHeight = 25;bool isFolded = !foldoutStates.ContainsKey(node.Path) || !foldoutStates[node.Path];if (node.IsFolder && !isFolded){foreach (var child in node.Children){totalHeight += GetTotalHeight(child);}}return totalHeight;}public int GetHeight(){return treeHeight;}public void ToggleExpandAll(bool _isExpandAll){isExpandAll = _isExpandAll;foldoutStates.Clear();repaintAction?.Invoke();}// 全选public void SelectAll(){foreach (var path in filePaths){if (!checkboxStates.ContainsKey(path)) continue;if (!checkboxStates[path]) // 只有未勾选的才修改{checkboxStates[path] = true;UpdateCheckboxLists(path, true);}}repaintAction?.Invoke(); // 更新界面}// 全不选public void DeselectAll(){foreach (var path in filePaths){if (!checkboxStates.ContainsKey(path)) continue;if (checkboxStates[path]) // 只有勾选的才修改{checkboxStates[path] = false;UpdateCheckboxLists(path, false);}}repaintAction?.Invoke(); // 更新界面}private Texture GetIconForPath(string path, bool isFolder){if (isFolder) return EditorGUIUtility.IconContent("Folder Icon").image;string extension = Path.GetExtension(path).ToLower();switch (extension){case ".prefab": return EditorGUIUtility.IconContent("Prefab Icon").image;case ".fbx":case ".obj":case ".blend": return EditorGUIUtility.IconContent("Mesh Icon").image;case ".mat": return EditorGUIUtility.IconContent("Material Icon").image;case ".shader":case ".compute": return EditorGUIUtility.IconContent("Shader Icon").image;case ".png":case ".jpg": return EditorGUIUtility.IconContent("Texture Icon").image;case ".anim": return EditorGUIUtility.IconContent("Animation Icon").image;case ".controller": return EditorGUIUtility.IconContent("AnimatorController Icon").image;case ".unity": return EditorGUIUtility.IconContent("SceneAsset Icon").image;case ".ttf":case ".otf": return EditorGUIUtility.IconContent("Font Icon").image;default: return EditorGUIUtility.IconContent("DefaultAsset Icon").image;}}
}public class TGTreeNode
{public string Path { get; private set; }public bool IsFolder { get; private set; }public List<TGTreeNode> Children { get; private set; }public TGTreeNode(string path, bool isFolder){Path = path;IsFolder = isFolder;Children = new List<TGTreeNode>();}public bool HasChild(string path){return Children.Exists(child => child.Path.EndsWith(path));}public TGTreeNode GetChild(string path){return Children.Find(child => child.Path.EndsWith(path));}
}
http://www.lryc.cn/news/2383415.html

相关文章:

  • 【Node.js】Web开发框架
  • 使用Vite创建一个动态网页的前端项目
  • 系统架构设计师案例分析题——web篇
  • MySQL--day5--多表查询
  • 【Redis】AOF日志的三种写回机制
  • leetcode hot100刷题日记——7.最大子数组和
  • 基于Spring Boot和Vue的在线考试系统架构设计与实现(源码+论文+部署讲解等)
  • MySQL Workbench 工具导出与导入数据库:实用指南
  • Android 绘制折线图
  • 自建srs实时视频服务器支持RTMP推流和拉流
  • ubuntu22.04 卸载ESP-IDF
  • Spring IOCDI————(2)
  • 80. Java 枚举类 - 使用枚举实现单例模式
  • 融云 uni-app IMKit 上线,1 天集成,多端畅行
  • Java中的集合详解
  • 利用 Java 爬虫根据关键词获取某手商品列表
  • Axure项目实战:智慧运输平台后台管理端-订单管理2(多级交互)
  • 篇章五 项目创建
  • Ntfs!ATTRIBUTE_RECORD_HEADER结构$INDEX_ROOT=0x90的一个例子
  • AGI大模型(30):LangChain链的基本使用
  • 代码随想录算法训练营第六十六天| 图论11—卡码网97. 小明逛公园,127. 骑士的攻击
  • [创业之路-364]:企业战略管理案例分析-5-战略制定-宇树科技的使命、愿景、价值观的演变过程
  • React--函数组件和类组件
  • Flask 路由装饰器:从 URL 到视图函数的优雅映射
  • DDoS防护实战——从基础配置到高防IP部署
  • aws平台s3存储桶夸域问题处理
  • HOT100(二叉树)
  • 【vue-text-highlight】在vue2的使用教程
  • pycharm无法正常调试问题
  • springboot3.4.5-springsecurity+session