优化查询效率,完善文档
@ -107,6 +107,13 @@ function s2t(t) { return stringIDToTypeID(t) }
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断文件名是否有中文
|
||||||
|
if (Util.haveChinese(app.activeDocument.name))
|
||||||
|
{
|
||||||
|
alert("\"" + app.activeDocument.name + "\" 名字不合法,出现中文")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.documentName = app.activeDocument.name.slice(0, -4);
|
this.documentName = app.activeDocument.name.slice(0, -4);
|
||||||
|
|
||||||
var i, j, k, len, ref1, removeFiles;
|
var i, j, k, len, ref1, removeFiles;
|
||||||
@ -445,12 +452,6 @@ function s2t(t) { return stringIDToTypeID(t) }
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
function isChinese(temp) {
|
|
||||||
var re = /[^\u4E00-\u9FA5]/;
|
|
||||||
if (re.test(temp)) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNumber(val) {
|
function isNumber(val) {
|
||||||
var regPos = /^\d+(\.\d+)?$/; //非负浮点数
|
var regPos = /^\d+(\.\d+)?$/; //非负浮点数
|
||||||
var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; //负浮点数
|
var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; //负浮点数
|
||||||
@ -1221,6 +1222,12 @@ function s2t(t) { return stringIDToTypeID(t) }
|
|||||||
return imageName + layer.name.split("@")[0].replace('_', '').replace(' ', '-').toLowerCase();
|
return imageName + layer.name.split("@")[0].replace('_', '').replace(' ', '-').toLowerCase();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Util.haveChinese = function (temp) {
|
||||||
|
var re = /[\u4E00-\u9FA5]/;
|
||||||
|
if (re.test(temp)) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Util.getLastSnapshotID = function (doc) {
|
Util.getLastSnapshotID = function (doc) {
|
||||||
var hsLength, hsObj, i, j, ref1;
|
var hsLength, hsObj, i, j, ref1;
|
||||||
hsObj = doc.historyStates;
|
hsObj = doc.historyStates;
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
cd /d %~dp0
|
cd /d %~dp0
|
||||||
start step2.exe -src C:\Users\biaosong\Desktop\c2main_panel -dst C:\Users\biaosong\Desktop\c2main_panel_output
|
start step2.exe -src C:\Users\biaosong\Desktop\shijiezhishi -dst C:\Users\biaosong\Desktop\shijiezhishi_output
|
||||||
|
BIN
.res/创建text.png
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 529 KiB After Width: | Height: | Size: 274 KiB |
BIN
.res/创建预制体.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
.res/吸附展示.gif
Before Width: | Height: | Size: 337 KiB After Width: | Height: | Size: 667 KiB |
BIN
.res/复原子节点位置.gif
Normal file
After Width: | Height: | Size: 1005 KiB |
BIN
.res/展示.gif
Normal file
After Width: | Height: | Size: 656 KiB |
BIN
.res/开启助手.png
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 14 KiB |
BIN
.res/父节点应用子节点变换.gif
Normal file
After Width: | Height: | Size: 413 KiB |
@ -2,6 +2,7 @@
|
|||||||
using Sirenix.OdinInspector;
|
using Sirenix.OdinInspector;
|
||||||
using System;
|
using System;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
@ -44,19 +45,27 @@ namespace UguiToolkit.Editor
|
|||||||
|
|
||||||
public virtual void ApplyTransformByParent(Transform parentTf, Transform tf)
|
public virtual void ApplyTransformByParent(Transform parentTf, Transform tf)
|
||||||
{
|
{
|
||||||
var position = lastMoveMatrix.GetColumn(3); // 提取位置
|
Undo.RecordObject(parentTf, "ApplyTransformByParent");
|
||||||
var rotation = Quaternion.LookRotation(lastMoveMatrix.GetColumn(2), lastMoveMatrix.GetColumn(1)); // 提取旋转
|
var resultMatrix = lastMoveMatrix * parentTf.localToWorldMatrix;
|
||||||
Debug.Log($"[I] ApplyTransformByParent {position}, {rotation.eulerAngles}");
|
parentTf.position = resultMatrix.GetColumn(3);
|
||||||
parentTf.position += new Vector3(position.x, position.y, position.z);
|
parentTf.rotation = Quaternion.LookRotation(resultMatrix.GetColumn(2), resultMatrix.GetColumn(1));
|
||||||
parentTf.rotation *= rotation;
|
parentTf.localScale = new Vector3(
|
||||||
|
resultMatrix.GetColumn(0).magnitude,
|
||||||
|
resultMatrix.GetColumn(1).magnitude,
|
||||||
|
resultMatrix.GetColumn(2).magnitude
|
||||||
|
);
|
||||||
|
|
||||||
if (tf)
|
if (tf)
|
||||||
{
|
{
|
||||||
var lastTransformMatrixInverse = lastMoveMatrix.inverse;
|
Undo.RecordObject(tf, "ApplyTransformByParent");
|
||||||
position = lastTransformMatrixInverse.GetColumn(3); // 提取位置
|
resultMatrix = lastMoveMatrix.inverse * tf.localToWorldMatrix;
|
||||||
rotation = Quaternion.LookRotation(lastTransformMatrixInverse.GetColumn(2), lastTransformMatrixInverse.GetColumn(1)); // 提取旋转
|
tf.position = resultMatrix.GetColumn(3);
|
||||||
tf.position += new Vector3(position.x, position.y, position.z);
|
tf.rotation = Quaternion.LookRotation(resultMatrix.GetColumn(2), resultMatrix.GetColumn(1));
|
||||||
tf.rotation *= rotation;
|
tf.localScale = new Vector3(
|
||||||
|
resultMatrix.GetColumn(0).magnitude,
|
||||||
|
resultMatrix.GetColumn(1).magnitude,
|
||||||
|
resultMatrix.GetColumn(2).magnitude
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +81,9 @@ namespace UguiToolkit.Editor
|
|||||||
|
|
||||||
public void ApplyTransform(Transform tf)
|
public void ApplyTransform(Transform tf)
|
||||||
{
|
{
|
||||||
Debug.Log($"[I] ApplyTransform {tf.name}");
|
Undo.RecordObject(tf, "ApplyTransform");
|
||||||
OnApplyTransform(tf);
|
OnApplyTransform(tf);
|
||||||
|
|
||||||
Matrix4x4 newTransformMatrix = Matrix4x4.TRS(tf.position, tf.rotation, tf.localScale);
|
Matrix4x4 newTransformMatrix = Matrix4x4.TRS(tf.position, tf.rotation, tf.localScale);
|
||||||
lastMoveMatrix = newTransformMatrix * oldTransformMatrix.inverse;
|
lastMoveMatrix = newTransformMatrix * oldTransformMatrix.inverse;
|
||||||
}
|
}
|
||||||
@ -94,6 +104,7 @@ namespace UguiToolkit.Editor
|
|||||||
|
|
||||||
public void ApplyData<T>(T ui) where T : Component
|
public void ApplyData<T>(T ui) where T : Component
|
||||||
{
|
{
|
||||||
|
Undo.RecordObject(ui, "ApplyData");
|
||||||
OnApplyData(ui as T1);
|
OnApplyData(ui as T1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ namespace UguiToolkit.Editor
|
|||||||
if (!TryGetComponent<Image>(out m_previewImage))
|
if (!TryGetComponent<Image>(out m_previewImage))
|
||||||
{
|
{
|
||||||
m_previewImage = gameObject.AddComponent<Image>();
|
m_previewImage = gameObject.AddComponent<Image>();
|
||||||
|
m_previewImage.type = Image.Type.Simple;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadImageFromFile(ElementInfo.imgPath);
|
LoadImageFromFile(ElementInfo.imgPath);
|
||||||
@ -83,13 +84,11 @@ namespace UguiToolkit.Editor
|
|||||||
{
|
{
|
||||||
var pos = ElementInfo.Position;
|
var pos = ElementInfo.Position;
|
||||||
var worldPos = StageManager.Instance.PrefabContentsRoot.transform.TransformPoint(new Vector3(pos.x, pos.y, 0));
|
var worldPos = StageManager.Instance.PrefabContentsRoot.transform.TransformPoint(new Vector3(pos.x, pos.y, 0));
|
||||||
var anchorMin = rt.anchorMin;
|
|
||||||
var anchorMax = rt.anchorMax;
|
|
||||||
|
|
||||||
var oldPiovt = rt.pivot;
|
var oldPiovt = rt.pivot;
|
||||||
rt.pivot = new Vector2(0.5f, 0.5f);
|
rt.pivot = new Vector2(0.5f, 0.5f);
|
||||||
|
|
||||||
Vector2 size = new Vector2(ElementInfo.w, ElementInfo.h); ;
|
Vector2 size = new Vector2(ElementInfo.w, ElementInfo.h);
|
||||||
Quaternion rotation = Quaternion.identity;
|
Quaternion rotation = Quaternion.identity;
|
||||||
|
|
||||||
if (!similarityCalc)
|
if (!similarityCalc)
|
||||||
@ -106,12 +105,8 @@ namespace UguiToolkit.Editor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 调整大小
|
// 调整大小
|
||||||
rt.anchorMin = rt.pivot;
|
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size.x);
|
||||||
rt.anchorMax = rt.pivot;
|
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y);
|
||||||
var oldSizeDelta = rt.sizeDelta;
|
|
||||||
rt.sizeDelta = new Vector2(size.x, size.y);
|
|
||||||
rt.anchorMin = anchorMin;
|
|
||||||
rt.anchorMax = anchorMax;
|
|
||||||
|
|
||||||
// 设置世界坐标
|
// 设置世界坐标
|
||||||
rt.position = worldPos;
|
rt.position = worldPos;
|
||||||
@ -119,7 +114,9 @@ namespace UguiToolkit.Editor
|
|||||||
|
|
||||||
//修正中心点
|
//修正中心点
|
||||||
var oldRect = rt.rect;
|
var oldRect = rt.rect;
|
||||||
|
var oldLocalPosition = rt.localPosition;
|
||||||
rt.pivot = oldPiovt;
|
rt.pivot = oldPiovt;
|
||||||
|
rt.localPosition = oldLocalPosition;
|
||||||
var offsetRectPos = oldRect.position - rt.rect.position;
|
var offsetRectPos = oldRect.position - rt.rect.position;
|
||||||
rt.Translate(offsetRectPos);
|
rt.Translate(offsetRectPos);
|
||||||
}
|
}
|
||||||
|
@ -16,23 +16,28 @@ namespace UguiToolkit.Editor
|
|||||||
protected override void OnApplyTransform(Transform tf)
|
protected override void OnApplyTransform(Transform tf)
|
||||||
{
|
{
|
||||||
var rt = tf as RectTransform;
|
var rt = tf as RectTransform;
|
||||||
|
|
||||||
var pos = ElementInfo.Position;
|
var pos = ElementInfo.Position;
|
||||||
|
Vector2 size = new Vector2(ElementInfo.w, ElementInfo.h);
|
||||||
var worldPos = StageManager.Instance.PrefabContentsRoot.transform.TransformPoint(new Vector3(pos.x, pos.y, 0));
|
var worldPos = StageManager.Instance.PrefabContentsRoot.transform.TransformPoint(new Vector3(pos.x, pos.y, 0));
|
||||||
Quaternion rotation = Quaternion.identity;
|
Quaternion rotation = Quaternion.identity;
|
||||||
var oldPiovt = rt.pivot;
|
var oldPiovt = rt.pivot;
|
||||||
rt.pivot = new Vector2(0.5f, 0.5f);
|
rt.pivot = new Vector2(0.5f, 0.5f);
|
||||||
|
|
||||||
|
// 调整大小
|
||||||
|
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size.x);
|
||||||
|
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y);
|
||||||
|
|
||||||
// 设置世界坐标
|
// 设置世界坐标
|
||||||
rt.position = worldPos;
|
rt.position = worldPos;
|
||||||
rt.rotation = rotation;
|
rt.rotation = rotation;
|
||||||
|
|
||||||
//修正中心点
|
//修正中心点
|
||||||
var oldRect = rt.rect;
|
var oldRect = rt.rect;
|
||||||
|
var oldLocalPosition = rt.localPosition;
|
||||||
rt.pivot = oldPiovt;
|
rt.pivot = oldPiovt;
|
||||||
|
rt.localPosition = oldLocalPosition;
|
||||||
var offsetRectPos = oldRect.position - rt.rect.position;
|
var offsetRectPos = oldRect.position - rt.rect.position;
|
||||||
rt.Translate(offsetRectPos);
|
rt.Translate(offsetRectPos);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnApplyData(TextMeshProUGUI ui)
|
protected override void OnApplyData(TextMeshProUGUI ui)
|
||||||
@ -47,22 +52,45 @@ namespace UguiToolkit.Editor
|
|||||||
if (!TryGetComponent<TextMeshProUGUI>(out m_previewText))
|
if (!TryGetComponent<TextMeshProUGUI>(out m_previewText))
|
||||||
{
|
{
|
||||||
m_previewText = gameObject.AddComponent<TextMeshProUGUI>();
|
m_previewText = gameObject.AddComponent<TextMeshProUGUI>();
|
||||||
|
m_previewText.alignment = TextAlignmentOptions.Center;
|
||||||
}
|
}
|
||||||
OnApplyData(m_previewText);
|
OnApplyData(m_previewText);
|
||||||
|
|
||||||
ApplyTransform(transform);
|
ApplyTransform(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 在保证文本坐标不变的情况下设置 对齐方式
|
||||||
|
private static void SetAlignment(TextMeshProUGUI textMeshPro, TextAlignmentOptions newAlignment)
|
||||||
|
{
|
||||||
|
textMeshPro.ForceMeshUpdate();
|
||||||
|
|
||||||
|
// 获取当前文本的边界框
|
||||||
|
Bounds originalBounds = textMeshPro.textBounds;
|
||||||
|
// 设置新的对齐方式
|
||||||
|
textMeshPro.alignment = newAlignment;
|
||||||
|
// 更新布局
|
||||||
|
textMeshPro.ForceMeshUpdate();
|
||||||
|
// 获取新的边界框
|
||||||
|
Bounds newBounds = textMeshPro.textBounds;
|
||||||
|
// 计算偏移量
|
||||||
|
Vector3 offset = originalBounds.center - newBounds.center;
|
||||||
|
// 调整TextMeshPro的位置
|
||||||
|
textMeshPro.transform.position += offset;
|
||||||
|
}
|
||||||
|
|
||||||
private static void SetTMPByTextInfo(TextMeshProUGUI ui, LayoutInfo.TextInfo textInfo)
|
private static void SetTMPByTextInfo(TextMeshProUGUI ui, LayoutInfo.TextInfo textInfo)
|
||||||
{
|
{
|
||||||
// TODO: 自行扩展
|
// TODO: 自行扩展
|
||||||
|
|
||||||
|
// 保存当前的对齐方式
|
||||||
|
TextAlignmentOptions originalAlignment = ui.alignment;
|
||||||
float2 sizeOffset = float2.zero;
|
float2 sizeOffset = float2.zero;
|
||||||
|
|
||||||
|
ui.alignment = TextAlignmentOptions.Center;
|
||||||
|
|
||||||
if (!ui.hasStringID) ui.text = textInfo.text;
|
if (!ui.hasStringID) ui.text = textInfo.text;
|
||||||
ui.fontSize = (int)textInfo.size;
|
ui.fontSize = (int)textInfo.size;
|
||||||
ui.color = textInfo.color;
|
ui.color = textInfo.color;
|
||||||
ui.alignment = TextAlignmentOptions.Center;
|
|
||||||
|
|
||||||
if (GetTextFontPreset(textInfo, out var textFontPreset))
|
if (GetTextFontPreset(textInfo, out var textFontPreset))
|
||||||
{
|
{
|
||||||
@ -86,21 +114,15 @@ namespace UguiToolkit.Editor
|
|||||||
sizeOffset = textFontPreset.sizeOffset;
|
sizeOffset = textFontPreset.sizeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rt = ui.rectTransform;
|
|
||||||
var anchorMin = rt.anchorMin;
|
|
||||||
var anchorMax = rt.anchorMax;
|
|
||||||
// µ÷Õû´óС
|
|
||||||
rt.anchorMin = new Vector2(0.5f, 0.5f);
|
|
||||||
rt.anchorMax = anchorMin;
|
|
||||||
rt.sizeDelta = new Vector2(textInfo.w + sizeOffset.x, textInfo.h + sizeOffset.y);
|
|
||||||
rt.anchorMin = anchorMin;
|
|
||||||
rt.anchorMax = anchorMax;
|
|
||||||
|
|
||||||
// 调整margins
|
// 调整margins
|
||||||
ui.margin = Vector4.zero;
|
ui.margin = Vector4.zero;
|
||||||
|
|
||||||
// 设置字间距
|
// 设置字间距
|
||||||
ui.characterSpacing = 0f;
|
ui.characterSpacing = 0f;
|
||||||
|
|
||||||
|
// 设置对齐方式
|
||||||
|
if (originalAlignment != TextAlignmentOptions.Center)
|
||||||
|
SetAlignment(ui, originalAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool GetTextFontPreset(LayoutInfo.TextInfo textInfo, out TextFontPresetOfUnity textFontPreset)
|
private static bool GetTextFontPreset(LayoutInfo.TextInfo textInfo, out TextFontPresetOfUnity textFontPreset)
|
||||||
|
@ -28,30 +28,163 @@ public static class ImageUtils
|
|||||||
return Path.GetRelativePath(projectPath, imgFilePath).Replace("\\", "/");
|
return Path.GetRelativePath(projectPath, imgFilePath).Replace("\\", "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LoadPngImagesFromFolder(string folderPath, List<Mat> images, List<string> imagePaths)
|
public static void LoadPngImagesFromFolder(string folderPath, List<Mat> images, List<string> imagePaths, Func<string, bool> filterCallback)
|
||||||
{
|
{
|
||||||
foreach (string file in Directory.GetFiles(folderPath, "*.png"))
|
foreach (string filePath in Directory.GetFiles(folderPath, "*.png"))
|
||||||
{
|
{
|
||||||
Mat img = Imgcodecs.imread(file);
|
if (filterCallback(filePath)) continue;
|
||||||
|
|
||||||
|
Mat img = Imgcodecs.imread(filePath, Imgcodecs.IMREAD_UNCHANGED);
|
||||||
if (!img.empty())
|
if (!img.empty())
|
||||||
{
|
{
|
||||||
images.Add(img);
|
images.Add(img);
|
||||||
imagePaths.Add(FormatImgFilePath(file));
|
imagePaths.Add(FormatImgFilePath(filePath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region SliceTexture
|
||||||
|
|
||||||
|
static List<int> hashListOfSlice;
|
||||||
|
|
||||||
|
static int ToHashCode(in Color color)
|
||||||
|
{
|
||||||
|
int a = Mathf.RoundToInt(color.a * 255);
|
||||||
|
if (a == 0) return 0;
|
||||||
|
|
||||||
|
int r = Mathf.RoundToInt(color.r * 255);
|
||||||
|
int g = Mathf.RoundToInt(color.g * 255);
|
||||||
|
int b = Mathf.RoundToInt(color.b * 255);
|
||||||
|
|
||||||
|
return (a << 24) + (r << 16) + (g << 8) + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static (int, int) CalcLine(List<int> hashList)
|
||||||
|
{
|
||||||
|
int start = 0, end = 0;
|
||||||
|
int tmpStart = 0, tmpEnd = 0;
|
||||||
|
int tmpHash = hashList[0];
|
||||||
|
|
||||||
|
for (int i = 0; i < hashList.Count; i++)
|
||||||
|
{
|
||||||
|
if (tmpHash == hashList[i])
|
||||||
|
{
|
||||||
|
tmpEnd = i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (end - start < tmpEnd - tmpStart)
|
||||||
|
{
|
||||||
|
start = tmpStart;
|
||||||
|
end = tmpEnd;
|
||||||
|
}
|
||||||
|
tmpStart = i;
|
||||||
|
tmpEnd = i;
|
||||||
|
tmpHash = hashList[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end - start < tmpEnd - tmpStart)
|
||||||
|
{
|
||||||
|
start = tmpStart;
|
||||||
|
end = tmpEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<int> CreateHashList(Mat image, in char axis)
|
||||||
|
{
|
||||||
|
if (hashListOfSlice == null) hashListOfSlice = new ();
|
||||||
|
var hashList = hashListOfSlice;
|
||||||
|
hashList.Clear();
|
||||||
|
|
||||||
|
if (axis == 'x')
|
||||||
|
{
|
||||||
|
for (int i = 0; i < image.cols(); i++)
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
for (int j = 0; j < image.rows(); j++)
|
||||||
|
{
|
||||||
|
double[] color = image.get(j, i);
|
||||||
|
hash += ToHashCode(new Color((float)color[2] / 255, (float)color[1] / 255, (float)color[0] / 255, (float)color[3] / 255));
|
||||||
|
}
|
||||||
|
hashList.Add(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int j = 0; j < image.rows(); j++)
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
for (int i = 0; i < image.cols(); i++)
|
||||||
|
{
|
||||||
|
double[] color = image.get(j, i);
|
||||||
|
hash += ToHashCode(new Color((float)color[2] / 255, (float)color[1] / 255, (float)color[0] / 255, (float)color[3] / 255));
|
||||||
|
}
|
||||||
|
hashList.Add(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SliceTexture(string imagePath, string outputPath)
|
||||||
|
{
|
||||||
|
var mat = SliceTexture(imagePath);
|
||||||
|
Imgcodecs.imwrite(outputPath, mat, new MatOfInt(Imgcodecs.IMWRITE_PNG_COMPRESSION, 9));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Mat SliceTexture(string imagePath)
|
||||||
|
{
|
||||||
|
Mat image = Imgcodecs.imread(imagePath, Imgcodecs.IMREAD_UNCHANGED); // ʹÓÃOpenCV¼ÓÔØÍ¼Ïñ
|
||||||
|
|
||||||
|
int width = image.cols();
|
||||||
|
int height = image.rows();
|
||||||
|
|
||||||
|
List<int> hashListX = CreateHashList(image, 'x');
|
||||||
|
(int xStart, int xEnd) = CalcLine(hashListX);
|
||||||
|
|
||||||
|
List<int> hashListY = CreateHashList(image, 'y');
|
||||||
|
(int yStart, int yEnd) = CalcLine(hashListY);
|
||||||
|
|
||||||
|
int outputWidth = width - (xEnd - xStart);
|
||||||
|
int outputHeight = height - (yEnd - yStart);
|
||||||
|
|
||||||
|
var outputMat = new Mat(outputHeight, outputWidth, CvType.CV_8UC4);
|
||||||
|
for (int x = 0; x < outputWidth; x++)
|
||||||
|
{
|
||||||
|
int originalX = x < xStart ? x : x + (xEnd - xStart);
|
||||||
|
for (int y = 0; y < outputHeight; y++)
|
||||||
|
{
|
||||||
|
int originalY = y < yStart ? y : y + (yEnd - yStart);
|
||||||
|
double[] color = image.get(originalY, originalX);
|
||||||
|
outputMat.put(y, x, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputMat;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
static List<Task<(double?, (double, double)?)>> tasks;
|
static List<Task<(double?, (double, double)?)>> tasks;
|
||||||
static ObjectPool<RotationScaleDetector> detectorPool;
|
static ObjectPool<RotationScaleDetector> detectorPool;
|
||||||
|
|
||||||
public static async Task ProcessFolderAsync(List<Mat> images, string targetFilePath,
|
public static async Task ProcessFolderAsync(List<Mat> images, string targetFilePath,
|
||||||
double distanceDifference, Action<int, (double, (double, double), bool)> callback,
|
double distanceDifference, Action<int, (double, (double, double), bool)> callback,
|
||||||
Action endCallback)
|
Action endCallback, bool isSliceTexture = false)
|
||||||
{
|
{
|
||||||
if (tasks == null) tasks = new (images.Count);
|
if (tasks == null) tasks = new (images.Count);
|
||||||
if (detectorPool == null) detectorPool = new (images.Count);
|
if (detectorPool == null) detectorPool = new (images.Count);
|
||||||
|
|
||||||
Mat targetImage = Imgcodecs.imread(targetFilePath);
|
Mat targetImage = null;
|
||||||
|
if (isSliceTexture)
|
||||||
|
{
|
||||||
|
targetImage = SliceTexture(targetFilePath);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
targetImage = Imgcodecs.imread(targetFilePath, Imgcodecs.IMREAD_UNCHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
List<RotationScaleDetector> detectors = new(images.Count);
|
List<RotationScaleDetector> detectors = new(images.Count);
|
||||||
tasks.Clear();
|
tasks.Clear();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using Sirenix.OdinInspector.Editor;
|
using Sirenix.OdinInspector.Editor;
|
||||||
|
using System;
|
||||||
using UguiToolkit.Editor.Windows;
|
using UguiToolkit.Editor.Windows;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.SceneManagement;
|
using UnityEditor.SceneManagement;
|
||||||
@ -9,6 +10,9 @@ namespace UguiToolkit.Editor
|
|||||||
{
|
{
|
||||||
public static class PanelHelper
|
public static class PanelHelper
|
||||||
{
|
{
|
||||||
|
public static event Action<Transform> jumpOfGameCameraByCurPos;
|
||||||
|
public static event Action<Transform> recoverDataSelectionObjCache;
|
||||||
|
|
||||||
[InitializeOnLoadMethod]
|
[InitializeOnLoadMethod]
|
||||||
public static void AddListener()
|
public static void AddListener()
|
||||||
{
|
{
|
||||||
@ -45,11 +49,26 @@ namespace UguiToolkit.Editor
|
|||||||
{
|
{
|
||||||
if (StageManager.Instance)
|
if (StageManager.Instance)
|
||||||
{
|
{
|
||||||
var entityMng = StageManager.Instance.GetManager<EntityManager>();
|
if (Selection.activeGameObject)
|
||||||
if (entityMng && Selection.activeGameObject)
|
jumpOfGameCameraByCurPos.Invoke(Selection.activeGameObject.transform);
|
||||||
{
|
|
||||||
entityMng.EffectLastApplyTransform(Selection.activeGameObject.transform);
|
Debug.Log("JumpOfGameCameraByCurPos");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建热键 CTRL SPACE
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="menuCommand"></param>
|
||||||
|
[MenuItem("GameObject/拼接助手/恢复子节点位置 %SPACE", false, 6)]
|
||||||
|
public static void RecoverDataSelectionObjCache(MenuCommand menuCommand)
|
||||||
|
{
|
||||||
|
if (StageManager.Instance)
|
||||||
|
{
|
||||||
|
if (Selection.activeGameObject)
|
||||||
|
recoverDataSelectionObjCache.Invoke(Selection.activeGameObject.transform);
|
||||||
|
|
||||||
|
Debug.Log("RecoverDataSelectionObjCache");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,18 +12,25 @@ using UnityEngine.UI;
|
|||||||
using UguiToolkit.Editor.Windows;
|
using UguiToolkit.Editor.Windows;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
using Securify.ShellLink.Flags;
|
||||||
|
|
||||||
namespace UguiToolkit.Editor
|
namespace UguiToolkit.Editor
|
||||||
{
|
{
|
||||||
[ExecuteAlways]
|
[ExecuteAlways]
|
||||||
public class EntityManager : MonoBehaviour, IManager
|
public class EntityManager : MonoBehaviour, IManager
|
||||||
{
|
{
|
||||||
|
private const string m_backgroundFileName= "__background__";
|
||||||
|
private string m_BackgroundFileAllName= m_backgroundFileName + ".png";
|
||||||
|
|
||||||
private PanelCache m_panelCache;
|
private PanelCache m_panelCache;
|
||||||
private Transform m_entityRoot;
|
private Transform m_entityRoot;
|
||||||
private Transform m_background;
|
private Transform m_background;
|
||||||
private GameObject m_lastSelectionGo;
|
private GameObject m_lastApplyDataGo; // 上一次应用的游戏对象
|
||||||
private IEntity m_lastSelectionEntity;
|
private IEntity m_lastApplyDataEntity; // 上一次应用的entity
|
||||||
private GameObject m_curSelectionGo;
|
private GameObject m_curSelectionEntityGo; // 当前选中的entity游戏对象
|
||||||
|
private GameObject m_curSelectionGo; // 当前选中的游戏对象
|
||||||
|
private SelectionObjCache m_curSelectionObjCache = new (); // 当前选中的游戏对象的缓存数据
|
||||||
|
private Color m_curSelectionObjLabelColor = Color.yellow;
|
||||||
|
|
||||||
private List<ImageEntity> m_imageEntities;
|
private List<ImageEntity> m_imageEntities;
|
||||||
private List<IEntity> m_textEntities;
|
private List<IEntity> m_textEntities;
|
||||||
@ -60,9 +67,12 @@ namespace UguiToolkit.Editor
|
|||||||
editWindow.createAllTextEntity += CreateAllTextEntity;
|
editWindow.createAllTextEntity += CreateAllTextEntity;
|
||||||
editWindow.createAllPrefabEntity += CreateAllPrefabEntity;
|
editWindow.createAllPrefabEntity += CreateAllPrefabEntity;
|
||||||
editWindow.effectLastApplyTransform += EffectLastApplyTransform;
|
editWindow.effectLastApplyTransform += EffectLastApplyTransform;
|
||||||
|
editWindow.recoverDataSelectionObjCache += OnRecoverDataSelectionObjCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorApplication.hierarchyWindowItemOnGUI += HandleHierarchyWindowItemOnGUI;
|
EditorApplication.hierarchyWindowItemOnGUI += HandleHierarchyWindowItemOnGUI;
|
||||||
|
PanelHelper.jumpOfGameCameraByCurPos += EffectLastApplyTransform;
|
||||||
|
PanelHelper.recoverDataSelectionObjCache += RecoverDataSelectionObjCache;
|
||||||
|
|
||||||
ImageUtils.SetDebugMode(true);
|
ImageUtils.SetDebugMode(true);
|
||||||
}
|
}
|
||||||
@ -78,9 +88,12 @@ namespace UguiToolkit.Editor
|
|||||||
editWindow.createAllTextEntity -= CreateAllTextEntity;
|
editWindow.createAllTextEntity -= CreateAllTextEntity;
|
||||||
editWindow.createAllPrefabEntity -= CreateAllPrefabEntity;
|
editWindow.createAllPrefabEntity -= CreateAllPrefabEntity;
|
||||||
editWindow.effectLastApplyTransform -= EffectLastApplyTransform;
|
editWindow.effectLastApplyTransform -= EffectLastApplyTransform;
|
||||||
|
editWindow.recoverDataSelectionObjCache -= OnRecoverDataSelectionObjCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorApplication.hierarchyWindowItemOnGUI -= HandleHierarchyWindowItemOnGUI;
|
EditorApplication.hierarchyWindowItemOnGUI -= HandleHierarchyWindowItemOnGUI;
|
||||||
|
PanelHelper.jumpOfGameCameraByCurPos -= EffectLastApplyTransform;
|
||||||
|
PanelHelper.recoverDataSelectionObjCache -= RecoverDataSelectionObjCache;
|
||||||
|
|
||||||
ImageUtils.SetDebugMode(false);
|
ImageUtils.SetDebugMode(false);
|
||||||
if (m_stageManager.PrefabAsset || m_panelCache != null)
|
if (m_stageManager.PrefabAsset || m_panelCache != null)
|
||||||
@ -90,21 +103,21 @@ namespace UguiToolkit.Editor
|
|||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
// 检测是否到达可选实例矩形内部
|
// 检测是否到达可选实例矩形内部
|
||||||
if (m_selectionEntities != null && m_curSelectionGo)
|
if (m_selectionEntities != null && m_curSelectionEntityGo)
|
||||||
{
|
{
|
||||||
if (m_lastSelectionGo && m_lastSelectionGo == m_curSelectionGo)
|
if (m_lastApplyDataGo && m_lastApplyDataGo == m_curSelectionEntityGo)
|
||||||
{
|
{
|
||||||
if (m_lastSelectionEntity != null && !m_lastSelectionEntity.IsInside(m_lastSelectionGo.transform))
|
if (m_lastApplyDataEntity != null && !m_lastApplyDataEntity.IsInside(m_lastApplyDataGo.transform))
|
||||||
{
|
{
|
||||||
m_lastSelectionGo = null;
|
m_lastApplyDataGo = null;
|
||||||
m_lastSelectionEntity = null;
|
m_lastApplyDataEntity = null;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var entity in m_selectionEntities)
|
foreach (var entity in m_selectionEntities)
|
||||||
{
|
{
|
||||||
var tf = m_curSelectionGo.transform;
|
var tf = m_curSelectionEntityGo.transform;
|
||||||
if (entity.IsInside(tf))
|
if (entity.IsInside(tf))
|
||||||
{
|
{
|
||||||
entity.ApplyTransform(tf);
|
entity.ApplyTransform(tf);
|
||||||
@ -125,8 +138,8 @@ namespace UguiToolkit.Editor
|
|||||||
entity.ApplyData(temp);
|
entity.ApplyData(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastSelectionGo = m_curSelectionGo;
|
m_lastApplyDataGo = m_curSelectionEntityGo;
|
||||||
m_lastSelectionEntity = entity;
|
m_lastApplyDataEntity = entity;
|
||||||
|
|
||||||
Selection.activeGameObject = null;
|
Selection.activeGameObject = null;
|
||||||
break;
|
break;
|
||||||
@ -135,11 +148,36 @@ namespace UguiToolkit.Editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateSelectionObjLabelColor()
|
||||||
|
{
|
||||||
|
m_curSelectionObjLabelColor = m_curSelectionObjLabelColor == Color.yellow ? Color.blue : Color.yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRecoverDataSelectionObjCache()
|
||||||
|
{
|
||||||
|
if (m_curSelectionObjCache.Transform)
|
||||||
|
m_curSelectionObjCache.RecoverData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecoverDataSelectionObjCache(Transform parent)
|
||||||
|
{
|
||||||
|
if (m_curSelectionObjCache.Transform && m_curSelectionObjCache.Transform == parent)
|
||||||
|
{
|
||||||
|
m_curSelectionObjCache.RecoverData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void EffectLastApplyTransform(Transform parent)
|
public void EffectLastApplyTransform(Transform parent)
|
||||||
{
|
{
|
||||||
if (m_lastSelectionEntity != null)
|
if (m_lastApplyDataEntity != null)
|
||||||
{
|
{
|
||||||
m_lastSelectionEntity.ApplyTransformByParent(parent, m_lastSelectionGo ? m_lastSelectionGo.transform: null);
|
m_lastApplyDataEntity.ApplyTransformByParent(parent, m_lastApplyDataGo ? m_lastApplyDataGo.transform: null);
|
||||||
|
|
||||||
|
if (m_curSelectionObjCache.Transform)
|
||||||
|
{
|
||||||
|
m_curSelectionObjCache.SetData(m_curSelectionObjCache.Transform);
|
||||||
|
UpdateSelectionObjLabelColor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,11 +186,12 @@ namespace UguiToolkit.Editor
|
|||||||
if (!m_stageManager) return;
|
if (!m_stageManager) return;
|
||||||
var go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
|
var go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
|
||||||
if (!go) return;
|
if (!go) return;
|
||||||
if (go == m_lastSelectionGo)
|
var goLabel = new GUIContent(go.name);
|
||||||
|
var goSize = EditorStyles.linkLabel.CalcSize(goLabel) + new Vector2(20, 0);
|
||||||
|
|
||||||
|
if (go == m_lastApplyDataGo)
|
||||||
{
|
{
|
||||||
var goLabel = new GUIContent(go.name);
|
var label = new GUIContent(" <---------锚点");
|
||||||
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 size = EditorStyles.linkLabel.CalcSize(label) + new Vector2(10, 0);
|
||||||
var offsetRect =
|
var offsetRect =
|
||||||
new Rect(selectionRect.position + new Vector2(goSize.x, 0), size);
|
new Rect(selectionRect.position + new Vector2(goSize.x, 0), size);
|
||||||
@ -161,6 +200,24 @@ namespace UguiToolkit.Editor
|
|||||||
normal = new GUIStyleState() { textColor = Color.green },
|
normal = new GUIStyleState() { textColor = Color.green },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (go.transform == m_curSelectionObjCache.Transform)
|
||||||
|
{
|
||||||
|
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 = m_curSelectionObjLabelColor },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Button("TestSliceTexture")]
|
||||||
|
private void TestSliceTexture(string imagePath, string outputPath)
|
||||||
|
{
|
||||||
|
ImageUtils.SliceTexture(imagePath, outputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateAllTextEntity()
|
private void CreateAllTextEntity()
|
||||||
@ -208,7 +265,7 @@ namespace UguiToolkit.Editor
|
|||||||
{
|
{
|
||||||
if (m_background) DestroyImmediate(m_background.gameObject);
|
if (m_background) DestroyImmediate(m_background.gameObject);
|
||||||
|
|
||||||
var go = new GameObject("__background__", typeof(RectTransform));
|
var go = new GameObject(m_backgroundFileName, typeof(RectTransform));
|
||||||
UpdateHierarchyOfEntity(false, go);
|
UpdateHierarchyOfEntity(false, go);
|
||||||
m_background = go.transform;
|
m_background = go.transform;
|
||||||
m_background.SetParent(transform);
|
m_background.SetParent(transform);
|
||||||
@ -228,7 +285,7 @@ namespace UguiToolkit.Editor
|
|||||||
imgTf.localRotation = Quaternion.identity;
|
imgTf.localRotation = Quaternion.identity;
|
||||||
imgTf.localScale = Vector3.one;
|
imgTf.localScale = Vector3.one;
|
||||||
var img = imgGo.AddComponent<Image>();
|
var img = imgGo.AddComponent<Image>();
|
||||||
var imgPath = System.IO.Path.Join(m_panelCache.TargetImgDirPath, "__background__.png");
|
var imgPath = System.IO.Path.Join(m_panelCache.TargetImgDirPath, m_BackgroundFileAllName);
|
||||||
if (System.IO.File.Exists(imgPath))
|
if (System.IO.File.Exists(imgPath))
|
||||||
{
|
{
|
||||||
byte[] fileData = System.IO.File.ReadAllBytes(imgPath);
|
byte[] fileData = System.IO.File.ReadAllBytes(imgPath);
|
||||||
@ -244,7 +301,7 @@ namespace UguiToolkit.Editor
|
|||||||
UpdateHierarchyOfEntity(false, imgGo);
|
UpdateHierarchyOfEntity(false, imgGo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatePanelCache(string srcImgPath)
|
private void UpdatePanelCache(string srcImgPath, bool isSliceTexture = false)
|
||||||
{
|
{
|
||||||
float distanceDifference = GlobalManager.Instance.setting.distanceDifference;
|
float distanceDifference = GlobalManager.Instance.setting.distanceDifference;
|
||||||
isCalcRotationScaleRunning = true;
|
isCalcRotationScaleRunning = true;
|
||||||
@ -269,18 +326,22 @@ namespace UguiToolkit.Editor
|
|||||||
m_panelCache.AddRotScaleInfo(srcImgPath, rotScaleItemList);
|
m_panelCache.AddRotScaleInfo(srcImgPath, rotScaleItemList);
|
||||||
if (rotScaleItemList.Count > 0)
|
if (rotScaleItemList.Count > 0)
|
||||||
OnSelectionChanged();
|
OnSelectionChanged();
|
||||||
});
|
}, isSliceTexture: isSliceTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSelectionChanged()
|
private void OnSelectionChanged()
|
||||||
{
|
{
|
||||||
if (m_noSelection || !Selection.activeGameObject || Selection.gameObjects.Length > 1) return;
|
if (m_noSelection || !Selection.activeGameObject || Selection.gameObjects.Length > 1) return;
|
||||||
if (Selection.activeGameObject == m_curSelectionGo || !Selection.activeGameObject.activeSelf) return;
|
if (Selection.activeGameObject == m_curSelectionEntityGo || !Selection.activeGameObject.activeSelf) return;
|
||||||
|
|
||||||
var activeGameObject = Selection.activeGameObject;
|
var activeGameObject = Selection.activeGameObject;
|
||||||
if (activeGameObject.transform.parent == m_entityRoot || activeGameObject.transform.parent == m_background)
|
if (activeGameObject.transform.parent == m_entityRoot || activeGameObject.transform.parent == m_background)
|
||||||
return;
|
return;
|
||||||
m_curSelectionGo = null;
|
m_curSelectionGo = activeGameObject;
|
||||||
|
m_curSelectionObjCache.SetData(activeGameObject.transform);
|
||||||
|
UpdateSelectionObjLabelColor();
|
||||||
|
|
||||||
|
m_curSelectionEntityGo = null;
|
||||||
m_selectionEntities.Clear();
|
m_selectionEntities.Clear();
|
||||||
m_entityRoot.gameObject.SetActive(false);
|
m_entityRoot.gameObject.SetActive(false);
|
||||||
|
|
||||||
@ -304,14 +365,14 @@ namespace UguiToolkit.Editor
|
|||||||
|
|
||||||
if (IsInside)
|
if (IsInside)
|
||||||
{
|
{
|
||||||
if (m_lastSelectionGo && m_lastSelectionGo == activeGameObject)
|
if (m_lastApplyDataGo && m_lastApplyDataGo == activeGameObject)
|
||||||
{
|
{
|
||||||
m_curSelectionGo = activeGameObject;
|
m_curSelectionEntityGo = activeGameObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_curSelectionGo = activeGameObject;
|
m_curSelectionEntityGo = activeGameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var imgEntity in m_imageEntities)
|
foreach (var imgEntity in m_imageEntities)
|
||||||
@ -367,14 +428,14 @@ namespace UguiToolkit.Editor
|
|||||||
|
|
||||||
if (IsInside)
|
if (IsInside)
|
||||||
{
|
{
|
||||||
if (m_lastSelectionGo && m_lastSelectionGo == activeGameObject)
|
if (m_lastApplyDataGo && m_lastApplyDataGo == activeGameObject)
|
||||||
{
|
{
|
||||||
m_curSelectionGo = activeGameObject;
|
m_curSelectionEntityGo = activeGameObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_curSelectionGo = activeGameObject;
|
m_curSelectionEntityGo = activeGameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var textEntity in m_textEntities)
|
foreach (var textEntity in m_textEntities)
|
||||||
@ -406,14 +467,14 @@ namespace UguiToolkit.Editor
|
|||||||
|
|
||||||
if (IsInside)
|
if (IsInside)
|
||||||
{
|
{
|
||||||
if (m_lastSelectionGo && m_lastSelectionGo == activeGameObject)
|
if (m_lastApplyDataGo && m_lastApplyDataGo == activeGameObject)
|
||||||
{
|
{
|
||||||
m_curSelectionGo = activeGameObject;
|
m_curSelectionEntityGo = activeGameObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_curSelectionGo = activeGameObject;
|
m_curSelectionEntityGo = activeGameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var imgEntity in m_imageEntities)
|
foreach (var imgEntity in m_imageEntities)
|
||||||
@ -431,11 +492,12 @@ namespace UguiToolkit.Editor
|
|||||||
{
|
{
|
||||||
if (activeGameObject.TryGetComponent<Image>(out var image) && image.IsActive() && image.sprite)
|
if (activeGameObject.TryGetComponent<Image>(out var image) && image.IsActive() && image.sprite)
|
||||||
{
|
{
|
||||||
var srcImgPath = AssetDatabase.GetAssetPath(image.sprite);
|
var sprite = image.sprite;
|
||||||
|
var srcImgPath = AssetDatabase.GetAssetPath(sprite);
|
||||||
if (!string.IsNullOrEmpty(srcImgPath) && !m_panelCache.HaveRotScaleInfo(srcImgPath) &&
|
if (!string.IsNullOrEmpty(srcImgPath) && !m_panelCache.HaveRotScaleInfo(srcImgPath) &&
|
||||||
!isCalcRotationScaleRunning)
|
!isCalcRotationScaleRunning)
|
||||||
{
|
{
|
||||||
UpdatePanelCache(srcImgPath);
|
UpdatePanelCache(srcImgPath, sprite.border != Vector4.zero);
|
||||||
|
|
||||||
//var srcImgDirPath = System.IO.Path.GetDirectoryName(srcImgPath);
|
//var srcImgDirPath = System.IO.Path.GetDirectoryName(srcImgPath);
|
||||||
//AddCheckImgDirPath(srcImgDirPath);
|
//AddCheckImgDirPath(srcImgDirPath);
|
||||||
@ -453,9 +515,28 @@ namespace UguiToolkit.Editor
|
|||||||
CreateAllEntity();
|
CreateAllEntity();
|
||||||
InitBackground();
|
InitBackground();
|
||||||
|
|
||||||
|
|
||||||
|
HashSet<string> slicePaths = new HashSet<string>();
|
||||||
|
foreach (var entity in m_imageEntities)
|
||||||
|
{
|
||||||
|
var elementInfo = entity.ElementInfo;
|
||||||
|
if (elementInfo.HaveSlice)
|
||||||
|
{
|
||||||
|
var imageName = Path.GetFileName(elementInfo.imgPath);
|
||||||
|
slicePaths.Add(imageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
targetImages = new ();
|
targetImages = new ();
|
||||||
targetPaths = new ();
|
targetPaths = new ();
|
||||||
ImageUtils.LoadPngImagesFromFolder(panelCache.TargetImgDirPath, targetImages, targetPaths);
|
ImageUtils.LoadPngImagesFromFolder(panelCache.TargetImgDirPath, targetImages, targetPaths,
|
||||||
|
(imagePath) => {
|
||||||
|
var imageName = Path.GetFileName(imagePath);
|
||||||
|
if (m_BackgroundFileAllName == imageName) return true;
|
||||||
|
if (slicePaths.Contains(imageName)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUpdateBackgroundShow(bool show)
|
private void OnUpdateBackgroundShow(bool show)
|
||||||
@ -574,6 +655,48 @@ namespace UguiToolkit.Editor
|
|||||||
m_entityRoot.gameObject.SetActive(false);
|
m_entityRoot.gameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class SelectionObjCache
|
||||||
|
{
|
||||||
|
Transform m_transform;
|
||||||
|
|
||||||
|
List<RectTransform> childrens = new ();
|
||||||
|
List<Vector3> originalPositions = new();
|
||||||
|
|
||||||
|
public Transform Transform => m_transform;
|
||||||
|
|
||||||
|
public void SetData(Transform tf)
|
||||||
|
{
|
||||||
|
ClearData();
|
||||||
|
m_transform = tf;
|
||||||
|
|
||||||
|
for (int i = 0; i < tf.childCount; i++)
|
||||||
|
{
|
||||||
|
var rt = tf.GetChild(i) as RectTransform;
|
||||||
|
childrens.Add(rt);
|
||||||
|
originalPositions.Add(rt.position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearData()
|
||||||
|
{
|
||||||
|
childrens.Clear();
|
||||||
|
originalPositions.Clear();
|
||||||
|
originalPositions.Clear();
|
||||||
|
|
||||||
|
m_transform = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecoverData()
|
||||||
|
{
|
||||||
|
// 恢复子节点的全局位置和大小
|
||||||
|
for (int i = 0; i < childrens.Count; i++)
|
||||||
|
{
|
||||||
|
Undo.RecordObject(childrens[i], "RecoverData");
|
||||||
|
childrens[i].position = originalPositions[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -34,6 +34,11 @@ namespace UguiToolkit.Editor.Windows
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<Transform> effectLastApplyTransform;
|
public event Action<Transform> effectLastApplyTransform;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用上次变换
|
||||||
|
/// </summary>
|
||||||
|
public event Action recoverDataSelectionObjCache;
|
||||||
|
|
||||||
|
|
||||||
[SerializeField, HideInInspector]
|
[SerializeField, HideInInspector]
|
||||||
private bool m_showHierarchyOfEntityChange = false;
|
private bool m_showHierarchyOfEntityChange = false;
|
||||||
@ -80,7 +85,7 @@ namespace UguiToolkit.Editor.Windows
|
|||||||
[LabelText("需要应用变换的对象"), SerializeField]
|
[LabelText("需要应用变换的对象"), SerializeField]
|
||||||
private Transform m_targetTransform;
|
private Transform m_targetTransform;
|
||||||
|
|
||||||
[Button("应用上次变换 (SPACE)")]
|
[Button("应用上次变换 (SPACE)")]
|
||||||
private void EffectLastApplyTransform()
|
private void EffectLastApplyTransform()
|
||||||
{
|
{
|
||||||
if (m_targetTransform)
|
if (m_targetTransform)
|
||||||
@ -89,6 +94,12 @@ namespace UguiToolkit.Editor.Windows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Button("恢复子节点位置 (CTRL + SPACE)")]
|
||||||
|
private void RecoverDataSelectionObjCache()
|
||||||
|
{
|
||||||
|
recoverDataSelectionObjCache?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
public override string GettitleContent()
|
public override string GettitleContent()
|
||||||
{
|
{
|
||||||
return "助手编辑界面";
|
return "助手编辑界面";
|
||||||
|
46
README.md
@ -1,32 +1,34 @@
|
|||||||
# C1 Ugui拼接助手
|
# C1 Ugui拼接助手
|
||||||
|
|
||||||
## 简介
|
## 简介
|
||||||
> 该工具主要作用是优化工作流,提高重复劳动的工作效率,以下是当前版本已经实现的功能:
|
|
||||||
> 1. psd 导出自动切图,并处理九宫格
|
> 该工具主要作用是提高效果图还原度和提高拼接效率,以下是当前版本已经实现的功能:
|
||||||
|
> 1. psd 端自动切图,并处理九宫格
|
||||||
> 2. unity拼接时,对psd上所标记的像素图层进行吸附,设置位置和旋转、缩放
|
> 2. unity拼接时,对psd上所标记的像素图层进行吸附,设置位置和旋转、缩放
|
||||||
> 3. unity拼接时,对psd上所标记的文本图层进行吸附,设置位置和旋转、缩放,并设置字体、字体大小、字体颜色、描边等
|
> 3. unity拼接时,对psd上所标记的文本图层进行吸附,设置位置和旋转、缩放,并设置字体、字体大小、字体颜色、描边等
|
||||||
> 4. unity拼接时,对公共组件预制体进行设置位置和旋转、缩放
|
> 4. unity拼接时,对公共组件预制体进行设置位置和旋转、缩放
|
||||||
|
|
||||||
|
## 展示
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## 工作流
|
## 工作流
|
||||||
|
|
||||||

|

|
||||||
## 如何操作
|
## 如何操作
|
||||||
### psd数据导出
|
### psd数据导出
|
||||||
#### 对图层名使用关键字标记
|
#### 对图层名使用关键字标记
|
||||||
1. `$<图层名>` : 图片切图导出 例如:$img_tools
|
1. `$<图层名>` : 图片切图导出并吸附 例如:$img_tools ,参数:九宫格:`<图层名>@九宫格`
|
||||||
2. `%<图层名>` : 图片吸附用 例如:%img_tools
|
2. `%<图层名>` : 仅图片吸附用 例如:%img_tools,参数:九宫格:`<图层名>@九宫格`
|
||||||
3. `%<文本图层名>` : 文本吸附用 例如:%text_tools
|
3. `%<文本图层名>` : 仅文本吸附用 例如:%text_tools
|
||||||
4. `<图层名>@九宫格` : 九宫格切图 例如:$img_tools@九宫格
|
|
||||||
4. `<图层名>@透明度=100` : 透明度属性 例如:$img_tools@透明度=50
|
|
||||||
5. `<图层名>@预制体=<资源唯一名称>` : 引用通用组件预制体 例如:领取龙币@预制体=btn_common_yellow_large
|
5. `<图层名>@预制体=<资源唯一名称>` : 引用通用组件预制体 例如:领取龙币@预制体=btn_common_yellow_large
|
||||||
|
|
||||||
#### 导出数据
|
#### 导出数据
|
||||||
> psd文件名不支持中文
|
|
||||||
|
|
||||||
运行指定脚本进行导出
|
运行指定脚本进行导出
|
||||||

|

|
||||||
|
|
||||||
选中项目中脚本
|
选中项目中脚本
|
||||||
`client\PackagesSource\com.txcombo.c1.ugui-toolkit\.PhotoshopScript\JSZXPsd2Unity\PSD导出Unity.js`
|
`client\toolchains\c1_ugui_toolkit\.PhotoshopScript\JSZXPsd2Unity\PSD导出Unity.js`
|
||||||
执行完毕后会自动弹出目录
|
执行完毕后会自动弹出目录
|
||||||

|

|
||||||
|
|
||||||
@ -39,13 +41,25 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### 如何吸附
|
#### 选中image和text、预制体后,自动吸附
|
||||||
##### 图片
|
##### 图片
|
||||||
|
|
||||||

|

|
||||||
##### 文本
|
##### 一键创建所有文本
|
||||||

|

|
||||||

|

|
||||||
##### 预制体
|
|
||||||
1. 选中预制体节点后,会显示界面所有可供创建的预制体预览
|
##### 一键创建所有预制体
|
||||||
2. 将鼠标光标放入预制体预览框,会自动创建预制体
|

|
||||||
|
|
||||||
|
#### 进阶操作
|
||||||
|
##### 父节点应用子节点变换
|
||||||
|
|
||||||
|
吸附完成后,选中父节点按下“空格”
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
##### 修改父节点边框后复原子节点位置
|
||||||
|
|
||||||
|
对父节点边框进行调整后,按下“Ctrl + 空格”
|
||||||
|
|
||||||
|

|
||||||
|