#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; using System.Threading.Tasks; using Unity.Mathematics; 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 bool isCalcRotationScaleRunning = false; private List targetImages; private List targetPaths; 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; editWindow.createAllPrefabEntity += CreateAllPrefabEntity; editWindow.effectLastApplyTransform += EffectLastApplyTransform; } EditorApplication.hierarchyWindowItemOnGUI += HandleHierarchyWindowItemOnGUI; ImageUtils.SetDebugMode(true); } private void OnDisable() { Selection.selectionChanged -= OnSelectionChanged; if (editWindow != null) { editWindow.showHierarchyOfEntityChanged -= OnUpdateHierarchyOfEntityAllEntity; editWindow.showBackgroundChanged -= OnUpdateBackgroundShow; editWindow.createAllTextEntity -= CreateAllTextEntity; editWindow.createAllPrefabEntity -= CreateAllPrefabEntity; editWindow.effectLastApplyTransform -= EffectLastApplyTransform; } EditorApplication.hierarchyWindowItemOnGUI -= HandleHierarchyWindowItemOnGUI; ImageUtils.SetDebugMode(false); if (m_stageManager.PrefabAsset || m_panelCache != null) GlobalManager.Instance.SaveCache(m_stageManager.PrefabAsset, m_panelCache); } 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); } m_lastSelectionGo = m_curSelectionGo; m_lastSelectionEntity = entity; Selection.activeGameObject = null; break; } } } } public void EffectLastApplyTransform(Transform parent) { if (m_lastSelectionEntity != null) { m_lastSelectionEntity.ApplyTransformByParent(parent, m_lastSelectionGo ? m_lastSelectionGo.transform: null); } } private void HandleHierarchyWindowItemOnGUI(int instanceID, Rect selectionRect) { if (!m_stageManager) return; var go = EditorUtility.InstanceIDToObject(instanceID) as GameObject; if (!go) return; if (go == m_lastSelectionGo) { var goLabel = new GUIContent(go.name); var goSize = EditorStyles.linkLabel.CalcSize(goLabel) + new Vector2(20, 0); var label = new GUIContent(" <-----"); var size = EditorStyles.linkLabel.CalcSize(label) + new Vector2(10, 0); var offsetRect = new Rect(selectionRect.position + new Vector2(goSize.x, 0), size); EditorGUI.LabelField(offsetRect, label, new GUIStyle() { normal = new GUIStyleState() { textColor = Color.green }, }); } } 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 CreateAllPrefabEntity() { var root = m_stageManager.PrefabContentsRoot; var prefabsTf = root.transform.Find("__prefabs__"); if (prefabsTf) DestroyImmediate(prefabsTf.gameObject); if (m_textEntities == null) return; var prefabsGo = new GameObject("__prefabs__", typeof(RectTransform)); prefabsGo.transform.parent = root.transform; foreach (var prefabEntity in m_prefabEntities) { var asset = prefabEntity.GetPrefabAsset(PrefabEntity.GetCommonDirPath()); if (asset != null) { var go = GameObject.Instantiate(asset, prefabsGo.transform); go.name = asset.name; prefabEntity.ApplyData(go.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); } private void UpdatePanelCache(string srcImgPath) { float distanceDifference = GlobalManager.Instance.setting.distanceDifference; isCalcRotationScaleRunning = true; List rotScaleItemList = new(); Debug.Log("GetRotationScaleAsync: " + srcImgPath); _ = ImageUtils.ProcessFolderAsync(targetImages, srcImgPath, distanceDifference, (index, result) => { if (!m_stageManager) return; rotScaleItemList.Add(new() { imgPath = ImageUtils.FormatImgFilePath(targetPaths[index]), rotiation = (float)result.Item1, scale = new float2((float)result.Item2.Item1, (float)result.Item2.Item1), similarityCalc = result.Item3 }); }, () => { Debug.Log("End GetRotationScaleAsync: " + srcImgPath); isCalcRotationScaleRunning = false; if (!m_stageManager) return; m_panelCache.AddRotScaleInfo(srcImgPath, rotScaleItemList); if (rotScaleItemList.Count > 0) OnSelectionChanged(); }); } 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); prefabEntity.SetOriginalMatrix(activeGameObject.transform); 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)) { if (image.sprite) { var srcImgPath = AssetDatabase.GetAssetPath(image.sprite); if (!string.IsNullOrEmpty(srcImgPath) && m_panelCache.HaveRotScaleInfo(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.InternalApplyTransform(imgEntity.transform); imgEntity.ShowSelectionImg(true); imgEntity.SetOriginalMatrix(activeGameObject.transform); 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); textEntity.SetOriginalMatrix(activeGameObject.transform); 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) && !m_panelCache.HaveRotScaleInfo(srcImgPath) && !isCalcRotationScaleRunning) { UpdatePanelCache(srcImgPath); //var srcImgDirPath = System.IO.Path.GetDirectoryName(srcImgPath); //AddCheckImgDirPath(srcImgDirPath); } } } } public void Init(PanelCache panelCache) { this.m_panelCache = panelCache; this.m_stageManager = StageManager.Instance; // 创建所有实例 CreateAllEntity(); InitBackground(); targetImages = new (); targetPaths = new (); ImageUtils.LoadPngImagesFromFolder(panelCache.TargetImgDirPath, targetImages, targetPaths); } 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 (Transform entity in m_background.transform) UpdateHierarchyOfEntity(show, entity.gameObject); foreach (var entity in m_imageEntities) UpdateHierarchyOfEntity(show, entity.gameObject); foreach (var entity in m_textEntities) UpdateHierarchyOfEntity(show, entity.gameObject); foreach (var entity in m_prefabEntities) 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