图片自动吸附

This commit is contained in:
Soviby 2024-10-30 01:51:06 +08:00
parent 285bd5511d
commit 5fca083eb7
9 changed files with 185 additions and 29 deletions

View File

@ -1,13 +1,16 @@
#if UNITY_EDITOR
using Sirenix.OdinInspector;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.UIElements;
namespace UguiToolkit.Editor
{
public interface IEntity
{
void SetTransform(float rotiation, float2 scale);
void ApplyTransform(Transform transform);
void ApplyTransform(Transform tf);
bool IsInside(Transform tf);
}
public abstract class BaseEntity<T1,T2> : MonoBehaviour, IEntity where T1 : MonoBehaviour where T2 : LayoutInfo.ElementInfo
@ -15,21 +18,40 @@ namespace UguiToolkit.Editor
// ElementInfo
private T2 m_elementInfo;
[ShowInInspector]
private float rotiation;
[ShowInInspector]
private float2 scale;
[ShowInInspector]
private bool needFillTransform;
private UnityEngine.UI.Image m_selectionImg;
protected T2 ElementInfo => m_elementInfo;
public T2 ElementInfo => m_elementInfo;
public void ApplyTransform(Transform transform)
public void ShowSelectionImg(bool show)
{
if (m_selectionImg)
{
m_selectionImg.gameObject.SetActive(show);
}
}
public bool IsInside(Transform tf)
{
var rect = ElementInfo.Rect;
var pos = StageManager.Instance.PrefabContentsRoot.transform.InverseTransformPoint(new Vector3(tf.position.x, tf.position.y, 0));
return rect.Contains(pos);
}
public void ApplyTransform(Transform tf)
{
if (needFillTransform)
{
transform.rotation = Quaternion.Euler(0, 0, rotiation);
transform.localScale = new Vector3(scale.x, scale.y, 0);
tf.rotation = Quaternion.Euler(0, 0, rotiation);
tf.localScale = new Vector3(scale.x, scale.y, 1);
}
var position = m_elementInfo.Position;
transform.localPosition = new Vector3(position.x, position.y, 0);
tf.position = StageManager.Instance.PrefabContentsRoot.transform.TransformPoint(new Vector3(position.x, position.y, 0));
}
// 查找时调用
@ -48,6 +70,7 @@ namespace UguiToolkit.Editor
public void SetData(T2 elementInfo)
{
this.m_elementInfo = elementInfo;
CreateSelectionImg();
}
public void ApplyData(T1 ui)
@ -55,6 +78,23 @@ namespace UguiToolkit.Editor
OnApplyData(ui);
}
private void CreateSelectionImg()
{
var go = new GameObject("_selectionImg_", typeof(RectTransform));
EntityHelper.UpdateHierarchyAndSceneVisibilityOfEntity(false, go);
var tf = go.transform;
tf.SetParent(transform);
tf.localPosition = Vector3.zero;
tf.localRotation = Quaternion.identity;
tf.localScale = Vector3.one;
var rtf = go.GetComponent<RectTransform>();
rtf.sizeDelta = new Vector2(m_elementInfo.w, m_elementInfo.h);
m_selectionImg = go.AddComponent<UnityEngine.UI.Image>();
m_selectionImg.color = new Color(0, 1, 0, 0.3f);
}
protected virtual void OnApplyData(T1 ui) { }
}
}

View File

@ -35,6 +35,7 @@ public class ImageEntity : BaseEntity<Image, LayoutInfo.ImageInfo>
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
m_previewImage.sprite = sprite;
m_previewImage.color = new Color(1, 1, 1, 0.7f);
m_previewImage.SetNativeSize();
}
else

View File

@ -9,7 +9,7 @@ namespace UguiToolkit.Editor
{
public static class CommandHelper
{
public static RotScaleJsonData CalcRotScale(in string srcImgDirPath, in string targetImgDirPath, Dictionary<string, List<RotScaleInfoItem>> rotScaleInfos)
public static RotScaleJsonData CalcRotScale(in string srcImgDirPath, in string targetImgDirPath)
{
var rotScaleInfoFilePath = Path.GetFullPath(EditorConst.RotScaleInfoFilePath);
var rotScaleInfoToolFilePath = Path.GetFullPath(EditorConst.RotScaleInfoToolFilePath);
@ -41,6 +41,7 @@ namespace UguiToolkit.Editor
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c " + cmd; // 使用 /c 参数执行命令并关闭 cmd 窗口
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;

View File

@ -21,4 +21,10 @@ public static class EntityHelper
SceneVisibilityManager.instance.DisablePicking(entity, true);
}
}
public static void UpdateHierarchyAndSceneVisibilityOfEntity(in bool show, in GameObject entity)
{
UpdateHierarchyOfEntity(show, entity.gameObject);
UpdateSceneVisibilityOfEntity(show, entity.gameObject);
}
}

View File

@ -1,6 +1,9 @@
#if UNITY_EDITOR
using Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using static UnityEngine.EventSystems.EventTrigger;
namespace UguiToolkit.Editor
{
@ -9,18 +12,117 @@ namespace UguiToolkit.Editor
{
private PanelCache m_panelCache;
private Transform entityRoot;
private GameObject lastSelectionGo;
private IEntity lastSelectionEntity;
private List<ImageEntity> imageEntities;
private List<TextEntity> textEntities;
private List<IEntity> selectionEntities;
private void Start()
[LabelText("脱离选择控制"), ShowInInspector]
private bool noSelection;
private void OnEnable()
{
GlobalManager.Instance.OnShowHierarchyOfEntityChange += UpdateHierarchyOfEntityAllEntity;
GlobalManager.Instance.showHierarchyOfEntityChanged += OnUpdateHierarchyOfEntityAllEntity;
Selection.selectionChanged += OnSelectionChanged;
}
private void OnDestroy()
private void OnDisable()
{
GlobalManager.Instance.OnShowHierarchyOfEntityChange -= UpdateHierarchyOfEntityAllEntity;
GlobalManager.Instance.showHierarchyOfEntityChanged -= OnUpdateHierarchyOfEntityAllEntity;
Selection.selectionChanged -= OnSelectionChanged;
}
private void Update()
{
// 检测是否到达可选实例矩形内部
if (selectionEntities != null && Selection.activeGameObject != null)
{
if (lastSelectionGo && lastSelectionGo == Selection.activeGameObject)
{
if (lastSelectionEntity != null && !lastSelectionEntity.IsInside(lastSelectionGo.transform))
{
lastSelectionGo = null;
lastSelectionEntity = null;
}
return;
}
bool isApplyTransform = false;
foreach (var entity in selectionEntities)
{
var tf = Selection.activeGameObject.transform;
if (entity.IsInside(tf))
{
entity.ApplyTransform(tf);
lastSelectionGo = Selection.activeGameObject;
lastSelectionEntity = entity;
Selection.activeGameObject = null;
isApplyTransform = true;
break;
}
}
if (isApplyTransform) selectionEntities.Clear();
}
}
private void OnSelectionChanged()
{
if (noSelection) return;
entityRoot.gameObject.SetActive(false);
selectionEntities.Clear();
if (Selection.activeGameObject != null && m_panelCache != null)
{
var activeGameObject = Selection.activeGameObject;
if (activeGameObject.transform.parent == 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;
entityRoot.gameObject.SetActive(true);
bool isFind;
foreach (var imgEntity in imageEntities)
{
isFind = false;
foreach (var rotScale in rotScaleInfoItems)
{
var imgInfo = imgEntity.ElementInfo;
if (imgInfo.imgPath == rotScale.imgPath)
{
imgEntity.SetTransform(rotScale.rotiation, rotScale.scale);
imgEntity.ShowSelectionImg(true);
selectionEntities.Add(imgEntity);
isFind = true;
break;
}
}
imgEntity.gameObject.SetActive(isFind);
}
foreach (var textEntity in textEntities)
{
textEntity.gameObject.SetActive(false);
}
}
else if (activeGameObject.TryGetComponent<UnityEngine.UI.Text>(out var text))
{
}
}
}
public void InitAllEntity(PanelCache panelCache)
@ -31,7 +133,7 @@ namespace UguiToolkit.Editor
CreateAllEntity();
}
private void UpdateHierarchyOfEntityAllEntity(bool show)
private void OnUpdateHierarchyOfEntityAllEntity(bool show)
{
UpdateHierarchyOfEntity(show, entityRoot.gameObject);
foreach (var entity in imageEntities) UpdateHierarchyOfEntity(show, entity.gameObject);
@ -40,14 +142,13 @@ namespace UguiToolkit.Editor
private void UpdateHierarchyOfEntity(in bool show, in GameObject entity)
{
EntityHelper.UpdateHierarchyOfEntity(show, entity.gameObject);
EntityHelper.UpdateSceneVisibilityOfEntity(show, entity.gameObject);
EntityHelper.UpdateHierarchyAndSceneVisibilityOfEntity(show, entity.gameObject);
}
private void CreateAllEntity()
{
if (this.m_panelCache == null) return;
var go = new GameObject();
var go = new GameObject("_entityRoot_", typeof(RectTransform));
UpdateHierarchyOfEntity(false, go);
entityRoot = go.transform;
entityRoot.SetParent(transform);
@ -57,13 +158,14 @@ namespace UguiToolkit.Editor
imageEntities = new(m_panelCache.layoutInfo.Count);
textEntities = new(m_panelCache.layoutInfo.Count);
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();
go = new GameObject("",typeof(RectTransform));
var entity = go.AddComponent<ImageEntity>();
entity.transform.SetParent(entityRoot);
entity.transform.SetSiblingIndex(0);
@ -78,7 +180,7 @@ namespace UguiToolkit.Editor
var textInfo = elementInfo as LayoutInfo.TextInfo;
if (textInfo != null) // Text
{
go = new GameObject();
go = new GameObject("", typeof(RectTransform));
var entity = go.AddComponent<TextEntity>();
entity.transform.SetParent(entityRoot);
entity.transform.SetSiblingIndex(0);
@ -92,6 +194,8 @@ namespace UguiToolkit.Editor
}
}
entityRoot.gameObject.SetActive(false);
}
}

View File

@ -28,7 +28,7 @@ namespace UguiToolkit
/// <summary>
/// 当是否显示预览实例发生改变时
/// </summary>
public Action<bool> OnShowHierarchyOfEntityChange;
public Action<bool> showHierarchyOfEntityChanged;
public void SaveCache()

View File

@ -33,23 +33,22 @@ namespace UguiToolkit
private void Start()
{
GlobalManager.Instance.OnShowHierarchyOfEntityChange += UpdateHierarchy;
GlobalManager.Instance.showHierarchyOfEntityChanged += OnUpdateHierarchy;
}
private void OnDestroy()
{
GlobalManager.Instance.OnShowHierarchyOfEntityChange -= UpdateHierarchy;
GlobalManager.Instance.showHierarchyOfEntityChanged -= OnUpdateHierarchy;
}
private void UpdateHierarchy(bool show)
private void OnUpdateHierarchy(bool show)
{
EntityHelper.UpdateHierarchyOfEntity(show, m_instance.gameObject);
}
public static StageManager CreateStageManager(Scene scene, GameObject prefabContentsRoot)
{
var go = new GameObject();
go.name = "StageManager";
var go = new GameObject("_StageManager_", typeof(RectTransform));
go.transform.parent = prefabContentsRoot.transform;
go.transform.localPosition = Vector3.zero;
go.transform.localRotation= Quaternion.identity;
@ -61,7 +60,7 @@ namespace UguiToolkit
go.hideFlags = HideFlags.DontSave;
m_instance.UpdateHierarchy(false);
m_instance.OnUpdateHierarchy(false);
return m_instance;
}

View File

@ -17,7 +17,7 @@ namespace UguiToolkit.Editor.Windows
{
m_showHierarchyOfEntityChange = value;
GlobalManager.Instance.OnShowHierarchyOfEntityChange?.Invoke(m_showHierarchyOfEntityChange);
GlobalManager.Instance.showHierarchyOfEntityChanged?.Invoke(m_showHierarchyOfEntityChange);
}
}

View File

@ -63,12 +63,15 @@ namespace UguiToolkit.Editor.Windows
var layoutInfo = layoutParser.Parser(jsonData);
// 对img路径进行修正
string projectPath = Directory.GetParent(Application.dataPath).FullName;
foreach (var elementInfo in layoutInfo)
{
var imgInfo = elementInfo as LayoutInfo.ImageInfo;
if (imgInfo != null)
{
imgInfo.imgPath = System.IO.Path.Join(panelCache.TargetImgDirPath, imgInfo.imgPath) + ".png";
imgInfo.imgPath = Path.GetRelativePath(projectPath, imgInfo.imgPath).Replace("\\", "/");
}
}
@ -80,19 +83,21 @@ namespace UguiToolkit.Editor.Windows
private void CalcRotScaleInfos()
{
// 执行cmd
var jsonData = CommandHelper.CalcRotScale(panelCache.srcImgDirPath, panelCache.TargetImgDirPath, panelCache.rotScaleInfos);
var jsonData = CommandHelper.CalcRotScale(panelCache.srcImgDirPath, panelCache.TargetImgDirPath);
if (jsonData == null || jsonData.data == null) return;
var rotScaleInfos = panelCache.rotScaleInfos;
rotScaleInfos.Clear();
string projectPath = Directory.GetParent(Application.dataPath).FullName;
foreach (var kv in jsonData.data)
{
List<RotScaleInfoItem> rotScaleItemList = new();
rotScaleInfos[kv.Key] = rotScaleItemList;
rotScaleInfos[Path.GetRelativePath(projectPath, kv.Key).Replace("\\", "/")] = rotScaleItemList;
foreach (var jsonItemData in kv.Value)
{
rotScaleItemList.Add(new ()
{
imgPath = Path.GetRelativePath(Application.dataPath, jsonItemData.targetPath),
imgPath = Path.GetRelativePath(projectPath, jsonItemData.targetPath).Replace("\\", "/"),
rotiation = jsonItemData.rot,
scale = new float2(jsonItemData.scale[0], jsonItemData.scale[1])
});