图片自动吸附

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 #if UNITY_EDITOR
using Sirenix.OdinInspector;
using Unity.Mathematics; using Unity.Mathematics;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements;
namespace UguiToolkit.Editor namespace UguiToolkit.Editor
{ {
public interface IEntity public interface IEntity
{ {
void SetTransform(float rotiation, float2 scale); 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 public abstract class BaseEntity<T1,T2> : MonoBehaviour, IEntity where T1 : MonoBehaviour where T2 : LayoutInfo.ElementInfo
@ -15,21 +18,40 @@ namespace UguiToolkit.Editor
// ElementInfo // ElementInfo
private T2 m_elementInfo; private T2 m_elementInfo;
[ShowInInspector]
private float rotiation; private float rotiation;
[ShowInInspector]
private float2 scale; private float2 scale;
[ShowInInspector]
private bool needFillTransform; 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) if (needFillTransform)
{ {
transform.rotation = Quaternion.Euler(0, 0, rotiation); tf.rotation = Quaternion.Euler(0, 0, rotiation);
transform.localScale = new Vector3(scale.x, scale.y, 0); tf.localScale = new Vector3(scale.x, scale.y, 1);
} }
var position = m_elementInfo.Position; 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) public void SetData(T2 elementInfo)
{ {
this.m_elementInfo = elementInfo; this.m_elementInfo = elementInfo;
CreateSelectionImg();
} }
public void ApplyData(T1 ui) public void ApplyData(T1 ui)
@ -55,6 +78,23 @@ namespace UguiToolkit.Editor
OnApplyData(ui); 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) { } 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)); 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.sprite = sprite;
m_previewImage.color = new Color(1, 1, 1, 0.7f);
m_previewImage.SetNativeSize(); m_previewImage.SetNativeSize();
} }
else else

View File

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

View File

@ -21,4 +21,10 @@ public static class EntityHelper
SceneVisibilityManager.instance.DisablePicking(entity, true); 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 #if UNITY_EDITOR
using Sirenix.OdinInspector;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEditor;
using UnityEngine; using UnityEngine;
using static UnityEngine.EventSystems.EventTrigger;
namespace UguiToolkit.Editor namespace UguiToolkit.Editor
{ {
@ -9,18 +12,117 @@ namespace UguiToolkit.Editor
{ {
private PanelCache m_panelCache; private PanelCache m_panelCache;
private Transform entityRoot; private Transform entityRoot;
private GameObject lastSelectionGo;
private IEntity lastSelectionEntity;
private List<ImageEntity> imageEntities; private List<ImageEntity> imageEntities;
private List<TextEntity> textEntities; 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) public void InitAllEntity(PanelCache panelCache)
@ -31,7 +133,7 @@ namespace UguiToolkit.Editor
CreateAllEntity(); CreateAllEntity();
} }
private void UpdateHierarchyOfEntityAllEntity(bool show) private void OnUpdateHierarchyOfEntityAllEntity(bool show)
{ {
UpdateHierarchyOfEntity(show, entityRoot.gameObject); UpdateHierarchyOfEntity(show, entityRoot.gameObject);
foreach (var entity in imageEntities) UpdateHierarchyOfEntity(show, entity.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) private void UpdateHierarchyOfEntity(in bool show, in GameObject entity)
{ {
EntityHelper.UpdateHierarchyOfEntity(show, entity.gameObject); EntityHelper.UpdateHierarchyAndSceneVisibilityOfEntity(show, entity.gameObject);
EntityHelper.UpdateSceneVisibilityOfEntity(show, entity.gameObject);
} }
private void CreateAllEntity() private void CreateAllEntity()
{ {
if (this.m_panelCache == null) return; if (this.m_panelCache == null) return;
var go = new GameObject(); var go = new GameObject("_entityRoot_", typeof(RectTransform));
UpdateHierarchyOfEntity(false, go); UpdateHierarchyOfEntity(false, go);
entityRoot = go.transform; entityRoot = go.transform;
entityRoot.SetParent(transform); entityRoot.SetParent(transform);
@ -57,13 +158,14 @@ namespace UguiToolkit.Editor
imageEntities = new(m_panelCache.layoutInfo.Count); imageEntities = new(m_panelCache.layoutInfo.Count);
textEntities = 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>()) foreach (var elementInfo in m_panelCache.GetLayoutElementInfos<LayoutInfo.ElementInfo>())
{ {
var imgInfo = elementInfo as LayoutInfo.ImageInfo; var imgInfo = elementInfo as LayoutInfo.ImageInfo;
if (imgInfo != null) // Image if (imgInfo != null) // Image
{ {
go = new GameObject(); go = new GameObject("",typeof(RectTransform));
var entity = go.AddComponent<ImageEntity>(); var entity = go.AddComponent<ImageEntity>();
entity.transform.SetParent(entityRoot); entity.transform.SetParent(entityRoot);
entity.transform.SetSiblingIndex(0); entity.transform.SetSiblingIndex(0);
@ -78,7 +180,7 @@ namespace UguiToolkit.Editor
var textInfo = elementInfo as LayoutInfo.TextInfo; var textInfo = elementInfo as LayoutInfo.TextInfo;
if (textInfo != null) // Text if (textInfo != null) // Text
{ {
go = new GameObject(); go = new GameObject("", typeof(RectTransform));
var entity = go.AddComponent<TextEntity>(); var entity = go.AddComponent<TextEntity>();
entity.transform.SetParent(entityRoot); entity.transform.SetParent(entityRoot);
entity.transform.SetSiblingIndex(0); 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>
/// 当是否显示预览实例发生改变时 /// 当是否显示预览实例发生改变时
/// </summary> /// </summary>
public Action<bool> OnShowHierarchyOfEntityChange; public Action<bool> showHierarchyOfEntityChanged;
public void SaveCache() public void SaveCache()

View File

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

View File

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

View File

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