com.soviby.unity.ui.ugui-to.../Assets/Editor/Manager/EntityManager.cs
2024-12-03 13:05:13 +08:00

455 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
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<ImageEntity> m_imageEntities;
private List<IEntity> m_textEntities;
private List<IEntity> m_selectionEntities;
[LabelText("脱离选择控制"), ShowInInspector]
private bool m_noSelection;
[SerializeField, HideInInspector]
private StageManager m_stageManager;
private HashSet<string> m_checkImgPaths;
private float m_lastCheckTime = 0f;
private bool m_useTMP;
private const float m_checkInterval = 3f;
private void OnEnable()
{
var globalMng = GlobalManager.Instance;
globalMng.showHierarchyOfEntityChanged += OnUpdateHierarchyOfEntityAllEntity;
globalMng.showBackgroundChanged += OnUpdateBackgroundShow;
globalMng.createAllTextEntity += CreateAllTextEntity;
m_useTMP = globalMng.setting.useTMP;
Selection.selectionChanged += OnSelectionChanged;
m_stageManager = StageManager.Instance;
}
private void OnDisable()
{
var globalMng = GlobalManager.Instance;
globalMng.showHierarchyOfEntityChanged -= OnUpdateHierarchyOfEntityAllEntity;
globalMng.showBackgroundChanged -= OnUpdateBackgroundShow;
globalMng.createAllTextEntity -= CreateAllTextEntity;
Selection.selectionChanged -= OnSelectionChanged;
}
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 (tf.TryGetComponent<UnityEngine.UI.Image>(out var image))
{
entity.ApplyData(image);
}
else if (tf.TryGetComponent<UnityEngine.UI.Text>(out var text))
{
entity.ApplyData(text);
}
else if (tf.TryGetComponent<TMPro.TextMeshProUGUI>(out var temp))
{
entity.ApplyData(temp);
}
m_lastSelectionGo = m_curSelectionGo;
m_lastSelectionEntity = entity;
Selection.activeGameObject = null;
break;
}
}
}
// 检测是否有image变更及时更新PanelCache
m_lastCheckTime -= Time.deltaTime;
CheckPanelCache();
}
private void CheckPanelCache()
{
if (m_lastCheckTime <= 0)
{
m_lastCheckTime = m_checkInterval;
if (m_checkImgPaths != null)
{
var images = m_stageManager.PrefabContentsRoot.GetComponentsInChildren<UnityEngine.UI.Image>();
foreach (var image in images)
{
if (image.transform.parent == m_entityRoot || image.transform.parent == m_background || image.sprite == null) continue;
var srcImgPath = AssetDatabase.GetAssetPath(image.sprite);
if (!string.IsNullOrEmpty(srcImgPath) && !m_checkImgPaths.Contains(srcImgPath))
{
var srcImgDirPath = System.IO.Path.GetDirectoryName(srcImgPath);
string projectPath = Directory.GetParent(Application.dataPath).FullName;
foreach (var filePath in System.IO.Directory.GetFiles(srcImgDirPath))
{
var _filePath = Path.GetRelativePath(projectPath, filePath).Replace("\\", "/");
m_checkImgPaths.Add(_filePath);
}
UpdatePanelCache(srcImgDirPath, m_panelCache.TargetImgDirPath);
break;
}
}
}
}
}
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>();
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<Image>();
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.4f);
img.SetNativeSize();
}
}
private void InitCheckImgPaths()
{
if (m_checkImgPaths == null) m_checkImgPaths = new HashSet<string>();
//var images = m_stageManager.PrefabContentsRoot.GetComponentsInChildren<UnityEngine.UI.Image>();
//foreach (var image in images)
//{
// if (image.sprite == null) continue;
// var srcImgPath = AssetDatabase.GetAssetPath(image.sprite);
// m_checkImgPaths.Add(srcImgPath);
//}
}
private void UpdatePanelCache(string srcImgDirPath, string targetImgDirPath)
{
float distanceDifference = GlobalManager.Instance.setting.distanceDifference;
CacheScriptObject.CalcRotScaleInfos(srcImgDirPath, targetImgDirPath, distanceDifference,(rotScaleInfoMap) =>
{
if (!m_stageManager) return;
// 拷贝数据
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) return;
m_curSelectionGo = null;
m_selectionEntities.Clear();
m_entityRoot.gameObject.SetActive(false);
if (Selection.activeGameObject != null && m_panelCache != null)
{
var activeGameObject = Selection.activeGameObject;
if (activeGameObject.transform.parent == m_entityRoot) return;
if (activeGameObject.TryGetComponent<UnityEngine.UI.Image>(out var image))
{
var rotScaleInfos = m_panelCache.rotScaleInfos;
if (rotScaleInfos == null) return;
if (image.sprite == null) return;
var srcImgPath = AssetDatabase.GetAssetPath(image.sprite);
if (!rotScaleInfos.TryGetValue(srcImgPath, out var rotScaleInfoItems)) return;
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);
}
}
else if (activeGameObject.TryGetComponent<UnityEngine.UI.Text>(out var _)
|| activeGameObject.TryGetComponent<TMPro.TextMeshProUGUI>(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);
}
}
}
}
public void InitAllEntity(PanelCache panelCache)
{
this.m_panelCache = panelCache;
this.m_stageManager = StageManager.Instance;
// 创建所有实例
CreateAllEntity();
InitCheckImgPaths();
InitBackground();
CheckPanelCache();
}
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>();
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);
foreach (var elementInfo in m_panelCache.GetLayoutElementInfos<LayoutInfo.ElementInfo>())
{
var imgInfo = elementInfo as LayoutInfo.ImageInfo;
if (imgInfo != null) // Image
{
go = new GameObject(imgInfo.name, typeof(RectTransform));
var entity = go.AddComponent<ImageEntity>();
entity.transform.SetParent(m_entityRoot);
entity.transform.SetSiblingIndex(0);
entity.SetData(imgInfo);
entity.InitPreview();
m_imageEntities.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<TextMeshProEntity>();
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<TextEntity>();
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