#if UNITY_EDITOR using System; using System.Collections; using System.Collections.Generic; using Unity.Mathematics; using UnityEngine; using Sirenix.OdinInspector; using static UguiToolkit.Editor.LayoutInfo; using System.IO; using UnityEditor; using Sirenix.Utilities; namespace UguiToolkit.Editor { [Serializable] public class CacheScriptObject : SerializedScriptableObject { [SerializeField] public Dictionary panelCaches = new(); public static LayoutInfo PaserLayout(string layoutInfoFilePath, string targetImgDirPath) { if (string.IsNullOrEmpty(layoutInfoFilePath)) { Debug.LogError("layoutInfoFilePath 为空"); return null; } ILayoutParser layoutParser = new DefaultLayoutParser(); using (StreamReader reader = File.OpenText(layoutInfoFilePath)) { var jsonData = reader.ReadToEnd(); 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(targetImgDirPath, imgInfo.imgPath) + ".png"; imgInfo.imgPath = Path.GetRelativePath(projectPath, imgInfo.imgPath).Replace("\\", "/"); if (imgInfo.HaveSlice) { imgInfo.imgSlicePath = System.IO.Path.Join(targetImgDirPath, imgInfo.imgSlicePath) + ".png"; imgInfo.imgSlicePath = Path.GetRelativePath(projectPath, imgInfo.imgSlicePath).Replace("\\", "/"); } } } return layoutInfo; } } public static void CalcRotScaleInfos(string srcImgDirPath, string targetImgDirPath, float distanceDifference, Action>> callback) { // 执行cmd CommandHelper.CalcRotScale(srcImgDirPath, targetImgDirPath, distanceDifference,(jsonData) => { if (jsonData == null || jsonData.data == null) return; Dictionary> rotScaleInfos = new(); string projectPath = Directory.GetParent(Application.dataPath).FullName; foreach (var kv in jsonData.data) { List rotScaleItemList = new(); rotScaleInfos[Path.GetRelativePath(projectPath, kv.Key).Replace("\\", "/")] = rotScaleItemList; foreach (var jsonItemData in kv.Value) { rotScaleItemList.Add(new() { imgPath = Path.GetRelativePath(projectPath, jsonItemData.targetPath).Replace("\\", "/"), rotiation = jsonItemData.rot, scale = new float2(jsonItemData.scale[0], jsonItemData.scale[1]), similarityCalc = jsonItemData.similarityCalc }); } } callback(rotScaleInfos); }); } } [Serializable] public class AllDirectionPanelCache { public PanelCache panelCacheOfVertical; public PanelCache panelCacheOfHorizontal; } [Serializable] public class PanelCache { [LabelText("项目内导出图片文件夹"), FolderPath] public string srcImgDirPath; [LabelText("目标图片信息文件(psd导出)"), Sirenix.OdinInspector.FilePath(AbsolutePath = true, Extensions = "layout.txt")] public string layoutInfoFilePath; // Sample.layout.txt [LabelText("目标图片文件夹路径")] public string TargetImgDirPath => m_targetImgDirPath; [LabelText("是否竖版")] public bool isVertical; // 通过ElementInfo创建所有Actor // 1. 鼠标选中img或者text,1s 后触发助手 // img // 2. 通过img的图片路径,查找rotScaleInfos,获得匹配的旋转缩放信息. 如果没有查找到则return // 3. 通过img的图片路径, 查找ActorManager, 获得所有和图片路径匹配的Actor,并显示所有匹配的Actor // 4. 每帧刷新,如果鼠标进入Actor的rect中,则播放scale动效。鼠标松开,则apply 该actor的 trasform // text // 2. 每帧刷新,查找圆形范围内,所有text Actor,并显示所有匹配的Actor // 3. 每帧刷新,如果鼠标进入Actor的rect中,则播放scale动效。鼠标松开,则apply 该actor的 trasform // 通过cmd计算获得 图片路径(源图) -> 旋转缩放信息(效果图) [SerializeField] public Dictionary> rotScaleInfos = new(); [SerializeField] public LayoutInfo layoutInfo; [SerializeField, HideInInspector] private string m_targetImgDirPath; [SerializeField] public Dictionary imgDirPathTimestamp = new(); private PanelCache() { } // public PanelCache(string srcImgDirPath, string layoutInfoFilePath) public PanelCache(string layoutInfoFilePath, string srcImgDirPath, bool isVertical = false) { this.srcImgDirPath = srcImgDirPath; this.layoutInfoFilePath = layoutInfoFilePath; this.isVertical = isVertical; this.m_targetImgDirPath = GetTargetImgDirPath(layoutInfoFilePath); } public bool IsValidOfImgDirPath(string imgDirPath) { if (imgDirPathTimestamp.TryGetValue(imgDirPath, out var timestamp)) { var curTimestamp = GetTimestampByDirPath(imgDirPath); return curTimestamp == timestamp; } return false; } public void ClearRotScaleInfoItem(string imgDirPath) { List indeces = new(); foreach (var rotScaleInfo in rotScaleInfos.Values) { indeces.Clear(); for (var i = 0; i < rotScaleInfo.Count; i++) { var item = rotScaleInfo[i]; if (item.imgPath.StartsWith(imgDirPath)) { indeces.Add(i); } } indeces.Sort(); indeces.Reverse(); foreach (var index in indeces) { rotScaleInfo.RemoveAt(index); } } } public void AddImgDirPathTimestamp(string imgDirPath) { var curTimestamp = GetTimestampByDirPath(imgDirPath); imgDirPathTimestamp[imgDirPath] = curTimestamp; } public void InitRotScaleInfos() { foreach(var dirPath in imgDirPathTimestamp.Keys) { if (!IsValidOfImgDirPath(dirPath)) { ClearRotScaleInfoItem(dirPath); } } } public void ClearRotScaleInfos() { rotScaleInfos.Clear(); imgDirPathTimestamp.Clear(); } public IEnumerable GetLayoutElementInfos() where T : LayoutInfo.ElementInfo { if (layoutInfo == null) yield break; foreach (var e in layoutInfo) { if (e is T) { yield return e as T; } } } public static string GetTargetImgDirPath(in string layoutInfoFilePath) { if (string.IsNullOrWhiteSpace(layoutInfoFilePath)) return ""; var dirName = System.IO.Path.GetDirectoryName(layoutInfoFilePath); var fileName = System.IO.Path.GetFileName(layoutInfoFilePath); var split = fileName.Split("."); if (split.Length == 0) return ""; return System.IO.Path.Join(dirName, split[0]); } public static long GetTimestampByDirPath(string dirPath) { DirectoryInfo directoryInfo = new DirectoryInfo(dirPath); // 获取文件夹的最后修改时间 DateTime lastModified = directoryInfo.LastWriteTime; return new DateTimeOffset(lastModified).ToUnixTimeSeconds(); } } [Serializable] public class LayoutInfo: IEnumerable { [SerializeField] private List m_elementInfos; [SerializeField] private float m_w; [SerializeField] private float m_h; public float W => m_w; public float H => m_h; public int Count => m_elementInfos == null ? 0 : m_elementInfos.Count; public LayoutInfo(List elementInfos, float w, float h) { this.m_elementInfos = elementInfos; this.m_w = w; this.m_h = h; } public IEnumerator GetEnumerator() { return ((IEnumerable)m_elementInfos).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)m_elementInfos).GetEnumerator(); } [Serializable] public class ElementInfo { public string name; public float x; public float y; public float w; public float h; public LayoutInfo layoutInfo; public float2 Position { get { float x = (layoutInfo.W / 2f) * -1 + this.x + this.w / 2f; float y = layoutInfo.H / 2f - this.y - this.h / 2f; return new float2(x, y); } } public Rect Rect { get { var pos = Position - new float2(this.w / 2f, this.h / 2f); return new(pos.x, pos.y, this.w, this.h); } } } [Serializable] public class ImageInfo : ElementInfo { public string imgPath; public string imgSlicePath; // 九宫格图片路径 public bool HaveSlice => imgSlicePath != null; // 是否有九宫格 } [Serializable] public class PrefabInfo : ElementInfo { public string prefabName; } [Serializable] public class TextInfo : ElementInfo { public string text; public float size; public Color color; public string align; public string font; public float strokeSize; public Color strokeColor; public bool IsStroke => strokeSize != 0; } } [Serializable] public struct TargetImageTransformInfo { public float3 position; public RotScaleInfoItem rotScaleInfo; public string ImgPath => rotScaleInfo.imgPath; } [Serializable] public struct RotScaleInfoItem { public string imgPath; //(效果图) public float rotiation; public float2 scale; public bool similarityCalc; } } #endif