#if UNITY_EDITOR using Sirenix.OdinInspector; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using TMPro; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.UI; using UguiToolkit.Editor.Windows; namespace UguiToolkit.Editor { [ExecuteAlways] public class EntityManager : MonoBehaviour, IManager { private PanelCache m_panelCache; private Transform m_entityRoot; private Transform m_background; private GameObject m_lastSelectionGo; private IEntity m_lastSelectionEntity; private GameObject m_curSelectionGo; private List m_imageEntities; private List m_textEntities; private List m_prefabEntities; private List m_selectionEntities; [LabelText("脱离选择控制"), ShowInInspector, SerializeField] private bool m_noSelection; private StageManager m_stageManager; private bool m_useTMP; private EditWindow editWindow; private string m_runningImgDirPath = null; private List m_preCheckImgDirPaths = new (); public Transform Background => m_background; private void OnEnable() { var globalMng = GlobalManager.Instance; m_useTMP = globalMng.setting.useTMP; Selection.selectionChanged += OnSelectionChanged; m_stageManager = StageManager.Instance; editWindow = EditWindow.Window; if (editWindow != null) { editWindow.showHierarchyOfEntityChanged += OnUpdateHierarchyOfEntityAllEntity; editWindow.showBackgroundChanged += OnUpdateBackgroundShow; editWindow.createAllTextEntity += CreateAllTextEntity; } } private void OnDisable() { Selection.selectionChanged -= OnSelectionChanged; if (editWindow != null) { editWindow.showHierarchyOfEntityChanged -= OnUpdateHierarchyOfEntityAllEntity; editWindow.showBackgroundChanged -= OnUpdateBackgroundShow; editWindow.createAllTextEntity -= CreateAllTextEntity; } } private void Update() { // 检测是否到达可选实例矩形内部 if (m_selectionEntities != null && m_curSelectionGo) { if (m_lastSelectionGo && m_lastSelectionGo == m_curSelectionGo) { if (m_lastSelectionEntity != null && !m_lastSelectionEntity.IsInside(m_lastSelectionGo.transform)) { m_lastSelectionGo = null; m_lastSelectionEntity = null; } return; } foreach (var entity in m_selectionEntities) { var tf = m_curSelectionGo.transform; if (entity.IsInside(tf)) { entity.ApplyTransform(tf); if (PrefabEntity.IsPrefab(tf.gameObject)) { entity.ApplyData(tf); } else if (tf.TryGetComponent(out var image)) { entity.ApplyData(image); } else if (tf.TryGetComponent(out var text)) { entity.ApplyData(text); } else if (tf.TryGetComponent(out var temp)) { entity.ApplyData(temp); } if (editWindow) editWindow.SetLastApplyEntity(entity); m_lastSelectionGo = m_curSelectionGo; m_lastSelectionEntity = entity; Selection.activeGameObject = null; break; } } } // 及时更新PanelCache CheckPanelCache(); } public void AddCheckImgDirPath(string dirPath) { if (string.IsNullOrEmpty(dirPath)) return; dirPath = dirPath.Replace("\\", "/"); if (m_runningImgDirPath != null && m_runningImgDirPath == dirPath) return; if (m_panelCache.IsValidOfImgDirPath(dirPath)) { return; } if (Directory.Exists(dirPath)) { if (m_preCheckImgDirPaths.Contains(dirPath)) { m_preCheckImgDirPaths.Remove(dirPath); } Debug.Log($"[I] AddCheckImgDirPath {dirPath}"); m_preCheckImgDirPaths.Insert(0, dirPath); } } private string GetCheckImgDirPath() { if (m_preCheckImgDirPaths.Count > 0) { string dirPath = m_preCheckImgDirPaths[0]; m_preCheckImgDirPaths.RemoveAt(0); if (Directory.Exists(dirPath)) { return dirPath; } } return null; } private void CheckPanelCache() { if (m_runningImgDirPath == null) { var srcImgDirPath = GetCheckImgDirPath(); if (srcImgDirPath != null) { UpdatePanelCache(srcImgDirPath, m_panelCache.TargetImgDirPath); } } } private void CreateAllTextEntity() { var root = m_stageManager.PrefabContentsRoot; var textsTf = root.transform.Find("__texts__"); if (textsTf) DestroyImmediate(textsTf.gameObject); if (m_textEntities == null) return; var textsGo = new GameObject("__texts__", typeof(RectTransform)); textsGo.transform.parent = root.transform; Type textType = m_useTMP ? typeof(TextMeshProUGUI) : typeof(Text); foreach (var textEntity in m_textEntities) { var newText = new GameObject(textEntity.gameObject.name, typeof(RectTransform), textType); newText.transform.parent = textsGo.transform; textEntity.ApplyData(newText.GetComponent(textType)); textEntity.ApplyTransform(newText.transform); } } private void InitBackground() { if (m_background) DestroyImmediate(m_background.gameObject); var go = new GameObject("__background__", typeof(RectTransform)); UpdateHierarchyOfEntity(false, go); m_background = go.transform; m_background.SetParent(transform); m_background.localPosition = Vector3.zero; m_background.localRotation = Quaternion.identity; m_background.localScale = Vector3.one; var canvas = m_background.gameObject.AddComponent(); canvas.pixelPerfect = true; canvas.overrideSorting = true; canvas.sortingOrder = -100; var imgGo = new GameObject("_", typeof(RectTransform)); var imgTf = imgGo.transform; imgTf.SetParent(m_background); imgTf.localPosition = Vector3.zero; imgTf.localRotation = Quaternion.identity; imgTf.localScale = Vector3.one; var img = imgGo.AddComponent(); var imgPath = System.IO.Path.Join(m_panelCache.TargetImgDirPath, "__background__.png"); if (System.IO.File.Exists(imgPath)) { byte[] fileData = System.IO.File.ReadAllBytes(imgPath); Texture2D texture = new Texture2D(2, 2); texture.LoadImage(fileData); // 加载图片数据到Texture2D Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)); img.sprite = sprite; img.color = new Color(1, 1, 1, 0.2f); img.SetNativeSize(); } UpdateHierarchyOfEntity(false, imgGo); } public void UpdatePanelCache(string srcImgDirPath, string targetImgDirPath) { float distanceDifference = GlobalManager.Instance.setting.distanceDifference; m_runningImgDirPath = srcImgDirPath; CacheScriptObject.CalcRotScaleInfos(srcImgDirPath, targetImgDirPath, distanceDifference,(rotScaleInfoMap) => { m_runningImgDirPath = null; if (!m_stageManager) return; m_panelCache.AddImgDirPathTimestamp(srcImgDirPath); m_panelCache.ClearRotScaleInfoItem(srcImgDirPath); // 拷贝数据 if (m_panelCache.rotScaleInfos != null) { foreach (var kv in rotScaleInfoMap) { if (!m_panelCache.rotScaleInfos.TryGetValue(kv.Key, out var rotScaleInfos)) { m_panelCache.rotScaleInfos[kv.Key] = kv.Value; } } } else { m_panelCache.rotScaleInfos = rotScaleInfoMap; } // 保存缓存 GlobalManager.Instance.SaveCache(m_stageManager.PrefabAsset, m_panelCache); }); } private void OnSelectionChanged() { if (m_noSelection || !Selection.activeGameObject || Selection.gameObjects.Length > 1) return; if (Selection.activeGameObject == m_curSelectionGo || !Selection.activeGameObject.activeSelf) return; var activeGameObject = Selection.activeGameObject; if (activeGameObject.transform.parent == m_entityRoot || activeGameObject.transform.parent == m_background) return; m_curSelectionGo = null; m_selectionEntities.Clear(); m_entityRoot.gameObject.SetActive(false); if (Selection.activeGameObject != null && m_panelCache != null) { if (PrefabEntity.IsCommonPrefab(activeGameObject)) { bool IsInside = false; m_entityRoot.gameObject.SetActive(true); foreach (var prefabEntity in m_prefabEntities) { prefabEntity.ShowSelectionImg(true); prefabEntity.gameObject.SetActive(true); m_selectionEntities.Add(prefabEntity); if (!IsInside && prefabEntity.IsInside(activeGameObject.transform)) IsInside = true; } if (IsInside) { if (m_lastSelectionGo && m_lastSelectionGo == activeGameObject) { m_curSelectionGo = activeGameObject; } } else { m_curSelectionGo = activeGameObject; } foreach (var imgEntity in m_imageEntities) { imgEntity.gameObject.SetActive(false); } foreach (var textEntity in m_textEntities) { textEntity.gameObject.SetActive(false); } } else if (activeGameObject.TryGetComponent(out var image)) { var rotScaleInfos = m_panelCache.rotScaleInfos; var srcImgPath = AssetDatabase.GetAssetPath(image.sprite); if (rotScaleInfos != null && image.sprite != null && rotScaleInfos.TryGetValue(srcImgPath, out var rotScaleInfoItems)) { m_entityRoot.gameObject.SetActive(true); bool isFind; bool IsInside = false; foreach (var imgEntity in m_imageEntities) { isFind = false; foreach (var rotScale in rotScaleInfoItems) { var imgInfo = imgEntity.ElementInfo; if ((imgInfo.HaveSlice && imgInfo.imgSlicePath == rotScale.imgPath) || imgInfo.imgPath == rotScale.imgPath) { if (rotScale.similarityCalc) { imgEntity.SetTransform(0, new Unity.Mathematics.float2(1, 1), true); } else { imgEntity.SetTransform(rotScale.rotiation, rotScale.scale, false); } imgEntity.ApplyTransform(imgEntity.transform); imgEntity.ShowSelectionImg(true); m_selectionEntities.Add(imgEntity); if (!IsInside && imgEntity.IsInside(activeGameObject.transform)) IsInside = true; isFind = true; break; } } imgEntity.gameObject.SetActive(isFind); } if (IsInside) { if (m_lastSelectionGo && m_lastSelectionGo == activeGameObject) { m_curSelectionGo = activeGameObject; } } else { m_curSelectionGo = activeGameObject; } foreach (var textEntity in m_textEntities) { textEntity.gameObject.SetActive(false); } foreach (var prefabEntity in m_prefabEntities) { prefabEntity.gameObject.SetActive(false); } } } else if (activeGameObject.TryGetComponent(out var _) || activeGameObject.TryGetComponent(out var _)) { bool IsInside = false; m_entityRoot.gameObject.SetActive(true); foreach (var textEntity in m_textEntities) { textEntity.ShowSelectionImg(true); textEntity.gameObject.SetActive(true); m_selectionEntities.Add(textEntity); if (!IsInside && textEntity.IsInside(activeGameObject.transform)) IsInside = true; } if (IsInside) { if (m_lastSelectionGo && m_lastSelectionGo == activeGameObject) { m_curSelectionGo = activeGameObject; } } else { m_curSelectionGo = activeGameObject; } foreach (var imgEntity in m_imageEntities) { imgEntity.gameObject.SetActive(false); } foreach (var prefabEntity in m_prefabEntities) { prefabEntity.gameObject.SetActive(false); } } } if (activeGameObject.transform.parent != m_entityRoot && activeGameObject.transform.parent != m_background) { if (activeGameObject.TryGetComponent(out var image) && image.IsActive() && image.sprite) { var srcImgPath = AssetDatabase.GetAssetPath(image.sprite); if (!string.IsNullOrEmpty(srcImgPath)) { var srcImgDirPath = System.IO.Path.GetDirectoryName(srcImgPath); AddCheckImgDirPath(srcImgDirPath); } } } } public void InitAllEntity(PanelCache panelCache) { this.m_panelCache = panelCache; this.m_stageManager = StageManager.Instance; // 创建所有实例 CreateAllEntity(); InitBackground(); } private void OnUpdateBackgroundShow(bool show) { if (m_background) { m_background.gameObject.SetActive(show); } } private void OnUpdateHierarchyOfEntityAllEntity(bool show) { UpdateHierarchyOfEntity(show, m_entityRoot.gameObject); UpdateHierarchyOfEntity(show, m_background.gameObject); foreach (var entity in m_imageEntities) UpdateHierarchyOfEntity(show, entity.gameObject); foreach (var entity in m_textEntities) UpdateHierarchyOfEntity(show, entity.gameObject); } private void UpdateHierarchyOfEntity(in bool show, in GameObject entity) { EntityHelper.UpdateHierarchyAndSceneVisibilityOfEntity(show, entity.gameObject); } private void CreateAllEntity() { if (this.m_panelCache == null) return; var go = new GameObject("__entityRoot__", typeof(RectTransform)); UpdateHierarchyOfEntity(false, go); m_entityRoot = go.transform; m_entityRoot.SetParent(transform); m_entityRoot.localPosition = Vector3.zero; m_entityRoot.localRotation = Quaternion.identity; m_entityRoot.localScale = Vector3.one; var canvas = m_entityRoot.gameObject.AddComponent(); canvas.pixelPerfect = true; canvas.overrideSorting = true; canvas.sortingOrder = 200; m_imageEntities = new(m_panelCache.layoutInfo.Count); m_textEntities = new(m_panelCache.layoutInfo.Count); m_selectionEntities = new(m_panelCache.layoutInfo.Count); m_prefabEntities = new(m_panelCache.layoutInfo.Count); foreach (var elementInfo in m_panelCache.GetLayoutElementInfos()) { var imgInfo = elementInfo as LayoutInfo.ImageInfo; if (imgInfo != null) // Image { go = new GameObject(imgInfo.name, typeof(RectTransform)); var entity = go.AddComponent(); entity.transform.SetParent(m_entityRoot); entity.transform.SetSiblingIndex(0); entity.SetData(imgInfo); entity.InitPreview(); m_imageEntities.Add(entity); UpdateHierarchyOfEntity(false, entity.gameObject); continue; } var prefabInfo = elementInfo as LayoutInfo.PrefabInfo; if (prefabInfo != null) // 预制体 { go = new GameObject(prefabInfo.name, typeof(RectTransform)); var entity = go.AddComponent(); entity.transform.SetParent(m_entityRoot); entity.transform.SetSiblingIndex(0); entity.SetData(prefabInfo); entity.InitPreview(); m_prefabEntities.Add(entity); UpdateHierarchyOfEntity(false, entity.gameObject); continue; } var textInfo = elementInfo as LayoutInfo.TextInfo; if (textInfo != null) // Text { if (m_useTMP) { go = new GameObject(textInfo.text, typeof(RectTransform)); var entity = go.AddComponent(); entity.transform.SetParent(m_entityRoot); entity.transform.SetSiblingIndex(0); entity.SetData(textInfo); entity.InitPreview(); m_textEntities.Add(entity); UpdateHierarchyOfEntity(false, entity.gameObject); continue; } else { go = new GameObject(textInfo.text, typeof(RectTransform)); var entity = go.AddComponent(); entity.transform.SetParent(m_entityRoot); entity.transform.SetSiblingIndex(0); entity.SetData(textInfo); entity.InitPreview(); m_textEntities.Add(entity); UpdateHierarchyOfEntity(false, entity.gameObject); continue; } } } m_entityRoot.gameObject.SetActive(false); } } } #endif