2025-08-22 00:33:25 +08:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections;
|
2025-08-24 08:37:56 +08:00
|
|
|
|
using System.Collections.Generic;
|
2025-08-22 00:33:25 +08:00
|
|
|
|
using System.IO;
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
using SixLabors.ImageSharp;
|
|
|
|
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
|
|
|
|
using SixLabors.ImageSharp.Formats.Png;
|
|
|
|
|
using SixLabors.ImageSharp.Processing;
|
|
|
|
|
|
|
|
|
|
namespace HK.FUJIFILM
|
|
|
|
|
{
|
|
|
|
|
public class DoubleCaptureSystem : TransparentCaptureSystem<DoubleCaptureSystem>
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 执行两次截图并裁剪,支持分别定制参数
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="onBothComplete">两次都完成后的回调(返回两次的字节数组)</param>
|
|
|
|
|
public void CaptureTwice(Action<byte[], byte[]> onBothComplete)
|
|
|
|
|
{
|
|
|
|
|
StartCoroutine(CoCaptureTwice(onBothComplete));
|
|
|
|
|
}
|
2025-08-24 08:37:56 +08:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 一开多
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="onBothComplete"></param>
|
|
|
|
|
public void CaptureTwice_ManyToMany(Action<List<byte[]>, List<byte[]>> onBothComplete)
|
|
|
|
|
{
|
|
|
|
|
StartCoroutine(CoCaptureTwice_ManyToMany(onBothComplete));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CaptureTwice_OneToMany(Action<byte[], List<byte[]>> onBothComplete)
|
|
|
|
|
{
|
|
|
|
|
StartCoroutine(CoCaptureTwice_OneToMany(onBothComplete));
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-25 15:53:01 +08:00
|
|
|
|
public void CaptureOnlyDesign(Action<byte[],string> onBothComplete)
|
2025-08-22 00:33:25 +08:00
|
|
|
|
{
|
|
|
|
|
StartCoroutine(CoCaptureOnlyDesign(onBothComplete));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
[ContextMenu("CaptureTwice")]
|
|
|
|
|
public void Test()
|
|
|
|
|
{
|
|
|
|
|
StartCoroutine(CoCaptureTwice(null));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
float ConvertMmToPixel(float mm, int dpi = 300)
|
|
|
|
|
{
|
|
|
|
|
return mm * (dpi / 25.4f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// private void Update()
|
|
|
|
|
// {
|
|
|
|
|
// if (Input.GetKeyDown(KeyCode.J))
|
|
|
|
|
// {
|
|
|
|
|
// UnityEngine.Debug.LogError($"px is {ConvertMmToPixel(85.6f)}");
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// 协程:顺序执行两次截图
|
|
|
|
|
private IEnumerator CoCaptureTwice(Action<byte[], byte[]> onBothComplete)
|
|
|
|
|
{
|
|
|
|
|
// 存储两次截图的结果
|
|
|
|
|
byte[] firstResult = null;
|
|
|
|
|
byte[] secondResult = null;
|
|
|
|
|
|
2025-08-25 15:53:01 +08:00
|
|
|
|
var tmpSaveFolder = saveFolder;
|
2025-08-22 00:33:25 +08:00
|
|
|
|
saveFolder = Path.Combine(saveFolder, DateTime.Now.ToString("yyyyMMdd_HHmmss"));
|
|
|
|
|
onlyFileName = "PreviewImage1";
|
|
|
|
|
|
|
|
|
|
var mugActualModelRenderFixed = uiRoot.GetComponent<MugActualModelRender_Fixed>();
|
|
|
|
|
var image = mugActualModelRenderFixed.designParent.GetChild(0).GetComponent<UnityEngine.UI.Image>();
|
|
|
|
|
image.enabled = true;
|
|
|
|
|
|
|
|
|
|
// 第一次截图(使用基类默认参数)
|
|
|
|
|
Debug.Log("开始第一次截图...");
|
|
|
|
|
yield return StartCoroutine(CaptureAndCrop((firstBytes) =>
|
|
|
|
|
{
|
|
|
|
|
firstResult = firstBytes;
|
|
|
|
|
Debug.Log("第一次截图完成");
|
|
|
|
|
}));
|
|
|
|
|
image.enabled = false;
|
|
|
|
|
|
|
|
|
|
// 确保第一次完成后再执行第二次
|
|
|
|
|
if (firstResult == null)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError("第一次截图失败,取消第二次");
|
|
|
|
|
onBothComplete?.Invoke(null, null);
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool tmpImageActive = image.enabled;
|
|
|
|
|
image.enabled = mugActualModelRenderFixed.productScriptableObject.isShowTemplate;
|
|
|
|
|
|
|
|
|
|
var verticalLayoutGroup = mugActualModelRenderFixed.designParent.GetComponent<VerticalLayoutGroup>();
|
|
|
|
|
verticalLayoutGroup.enabled = true;
|
|
|
|
|
|
|
|
|
|
var tmpWidth = cropWidth;
|
|
|
|
|
var tmpHeight = cropHeight;
|
|
|
|
|
var productScriptableObject = mugActualModelRenderFixed.productScriptableObject;
|
|
|
|
|
var screenshotSize = productScriptableObject.screenshotSize;
|
|
|
|
|
cropWidth = (int)screenshotSize.x;
|
|
|
|
|
cropHeight = (int)screenshotSize.y;
|
|
|
|
|
cropOffset = new Vector2(0.5f, 0.5f);
|
|
|
|
|
onlyFileName = "DesignImage1";
|
|
|
|
|
|
|
|
|
|
// 第二次截图(使用修改后的参数)
|
|
|
|
|
Debug.Log("开始第二次截图...");
|
|
|
|
|
yield return StartCoroutine(CaptureAndCrop((secondBytes) =>
|
|
|
|
|
{
|
|
|
|
|
secondResult = secondBytes;
|
|
|
|
|
Debug.Log("第二次截图完成");
|
|
|
|
|
}));
|
|
|
|
|
image.enabled = tmpImageActive;
|
2025-08-24 08:37:56 +08:00
|
|
|
|
|
2025-08-22 00:33:25 +08:00
|
|
|
|
// 1. 校验文件是否存在
|
|
|
|
|
var fileInfo = new FileInfo(fullPath);
|
|
|
|
|
if (!fileInfo.Exists)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"原始图片不存在:{fullPath}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
yield break; // 若在协程中,用 yield break 退出
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// 2. 加载图像并校验原始尺寸
|
|
|
|
|
using (var sImage = SixLabors.ImageSharp.Image.Load(fileInfo.FullName))
|
|
|
|
|
{
|
|
|
|
|
// 校验原始图片尺寸是否有效
|
|
|
|
|
if (sImage.Width <= 0 || sImage.Height <= 0)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"加载的图片尺寸无效:宽={sImage.Width}, 高={sImage.Height}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (productScriptableObject.printingSize.x != 0)
|
|
|
|
|
{
|
|
|
|
|
// 3. 校验缩放宽度是否有效
|
|
|
|
|
int targetWidth = (int)ConvertMmToPixel(productScriptableObject.printingSize.x);
|
|
|
|
|
int targetHeight = (int)ConvertMmToPixel(productScriptableObject.printingSize.y);
|
|
|
|
|
if (targetWidth <= 0)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"缩放宽度无效(必须大于 0):{targetWidth}");
|
|
|
|
|
// 可选:使用默认宽度(如 200)避免错误
|
|
|
|
|
targetWidth = 200;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 等比缩放(确保目标尺寸有效)
|
|
|
|
|
// sImage.Mutate(x => x.Resize(new ResizeOptions
|
|
|
|
|
// {
|
|
|
|
|
// Size = new Size(targetWidth, targetHeight), // 高度为0则自动计算
|
|
|
|
|
// Mode = ResizeMode.Max,
|
|
|
|
|
// Sampler = KnownResamplers.Lanczos3 // 高质量缩放算法
|
|
|
|
|
// }));
|
|
|
|
|
// 强制缩放
|
|
|
|
|
sImage.Mutate(x => x.Resize(targetWidth, targetHeight));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5. 确保保存目录存在
|
|
|
|
|
if (!Directory.Exists(saveFolder))
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(saveFolder); // 自动创建目录
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 6. 保存缩放后的图片
|
|
|
|
|
var filePath = Path.Combine(saveFolder, "Printing1.png");
|
|
|
|
|
sImage.SaveAsPng(filePath, new PngEncoder());
|
|
|
|
|
|
|
|
|
|
// 7. 校验保存结果并读取字节数组
|
|
|
|
|
if (File.Exists(filePath))
|
|
|
|
|
{
|
|
|
|
|
secondResult = File.ReadAllBytes(filePath);
|
|
|
|
|
Debug.Log($"第二次截图缩放后保存至:{filePath}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"图片保存失败,文件不存在:{filePath}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// 捕获所有异常(如图片格式错误、权限问题等)
|
|
|
|
|
Debug.LogError($"图片处理失败:{ex.Message}\n{ex.StackTrace}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 恢复原始参数(避免影响后续截图)
|
|
|
|
|
verticalLayoutGroup.enabled = false;
|
|
|
|
|
cropWidth = tmpWidth;
|
|
|
|
|
cropHeight = tmpHeight;
|
|
|
|
|
cropOffset = new Vector2(0f, 0f);
|
|
|
|
|
image.enabled = false;
|
2025-08-25 15:53:01 +08:00
|
|
|
|
saveFolder = tmpSaveFolder;
|
2025-08-22 00:33:25 +08:00
|
|
|
|
|
|
|
|
|
// 触发最终回调
|
|
|
|
|
onBothComplete?.Invoke(firstResult, secondResult);
|
|
|
|
|
}
|
2025-08-24 08:37:56 +08:00
|
|
|
|
|
|
|
|
|
private IEnumerator CoCaptureTwice_OneToMany(Action<byte[], List<byte[]>> onBothComplete)
|
|
|
|
|
{
|
|
|
|
|
byte[] firstResult = null;
|
|
|
|
|
List<byte[]> secondResults = new List<byte[]>();
|
|
|
|
|
|
2025-08-25 15:53:01 +08:00
|
|
|
|
var tmpSaveFolder = saveFolder;
|
2025-08-24 08:37:56 +08:00
|
|
|
|
var mugActualModelRenderFixed = uiRoot.GetComponent<MugActualModelRender_Fixed>();
|
|
|
|
|
saveFolder = Path.Combine(saveFolder, DateTime.Now.ToString("yyyyMMdd_HHmmss"));
|
|
|
|
|
var designParent = mugActualModelRenderFixed.designParent.GetChild(0);
|
|
|
|
|
|
|
|
|
|
onlyFileName = $"PreviewImage";
|
|
|
|
|
var tmpImageEnabled = false;
|
|
|
|
|
for (var i = 0; i < designParent.childCount; i++)
|
|
|
|
|
{
|
|
|
|
|
var image = designParent.GetChild(i).GetComponent<UnityEngine.UI.Image>();
|
|
|
|
|
tmpImageEnabled = image.enabled;
|
|
|
|
|
image.enabled = mugActualModelRenderFixed.productScriptableObject.isShowBaseMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第一次截图(使用基类默认参数)
|
|
|
|
|
Debug.Log("开始第一次截图...");
|
|
|
|
|
yield return StartCoroutine(CaptureAndCrop((firstBytes) =>
|
|
|
|
|
{
|
|
|
|
|
firstResult = firstBytes;
|
|
|
|
|
Debug.Log("第一次截图完成");
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < designParent.childCount; i++)
|
|
|
|
|
{
|
|
|
|
|
var image = designParent.GetChild(i).GetComponent<UnityEngine.UI.Image>();
|
|
|
|
|
image.enabled = tmpImageEnabled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 确保第一次完成后再执行第二次
|
|
|
|
|
if (firstResult == null)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError("第一次截图失败,取消第二次");
|
|
|
|
|
onBothComplete?.Invoke(null, null);
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < designParent.childCount; i++)
|
|
|
|
|
{
|
|
|
|
|
// 存储两次截图的结果
|
|
|
|
|
byte[] secondResult = null;
|
|
|
|
|
|
|
|
|
|
for (var j = 0; j < designParent.childCount; j++)
|
|
|
|
|
{
|
|
|
|
|
designParent.GetChild(j).gameObject.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
designParent.GetChild(i).gameObject.SetActive(true);
|
|
|
|
|
|
|
|
|
|
var verticalLayoutGroup = designParent.GetComponent<LayoutGroup>();
|
|
|
|
|
if (verticalLayoutGroup != null)
|
|
|
|
|
verticalLayoutGroup.enabled = true;
|
|
|
|
|
|
|
|
|
|
var tmpWidth = cropWidth;
|
|
|
|
|
var tmpHeight = cropHeight;
|
|
|
|
|
var productScriptableObject = mugActualModelRenderFixed.productScriptableObject;
|
|
|
|
|
var screenshotSize = productScriptableObject.screenshotSize;
|
|
|
|
|
cropWidth = (int)screenshotSize.x;
|
|
|
|
|
cropHeight = (int)screenshotSize.y;
|
|
|
|
|
cropOffset = new Vector2(0.5f, 0.5f);
|
|
|
|
|
onlyFileName = $"DesignImage{i}";
|
|
|
|
|
|
|
|
|
|
// 第二次截图(使用修改后的参数)
|
|
|
|
|
Debug.Log("开始第二次截图...");
|
|
|
|
|
yield return StartCoroutine(CaptureAndCrop((secondBytes) =>
|
|
|
|
|
{
|
|
|
|
|
secondResult = secondBytes;
|
|
|
|
|
Debug.Log("第二次截图完成");
|
|
|
|
|
}));
|
|
|
|
|
// image.enabled = tmpImageActive;
|
|
|
|
|
|
|
|
|
|
// 1. 校验文件是否存在
|
|
|
|
|
var fileInfo = new FileInfo(fullPath);
|
|
|
|
|
if (!fileInfo.Exists)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"原始图片不存在:{fullPath}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
yield break; // 若在协程中,用 yield break 退出
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// 2. 加载图像并校验原始尺寸
|
|
|
|
|
using (var sImage = SixLabors.ImageSharp.Image.Load(fileInfo.FullName))
|
|
|
|
|
{
|
|
|
|
|
// 校验原始图片尺寸是否有效
|
|
|
|
|
if (sImage.Width <= 0 || sImage.Height <= 0)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"加载的图片尺寸无效:宽={sImage.Width}, 高={sImage.Height}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (productScriptableObject.printingSize.x != 0)
|
|
|
|
|
{
|
|
|
|
|
// 3. 校验缩放宽度是否有效
|
|
|
|
|
int targetWidth = (int)ConvertMmToPixel(productScriptableObject.printingSize.x);
|
|
|
|
|
int targetHeight = (int)ConvertMmToPixel(productScriptableObject.printingSize.y);
|
|
|
|
|
if (targetWidth <= 0)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"缩放宽度无效(必须大于 0):{targetWidth}");
|
|
|
|
|
// 可选:使用默认宽度(如 200)避免错误
|
|
|
|
|
targetWidth = 200;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 等比缩放(确保目标尺寸有效)
|
|
|
|
|
// sImage.Mutate(x => x.Resize(new ResizeOptions
|
|
|
|
|
// {
|
|
|
|
|
// Size = new Size(targetWidth, targetHeight), // 高度为0则自动计算
|
|
|
|
|
// Mode = ResizeMode.Max,
|
|
|
|
|
// Sampler = KnownResamplers.Lanczos3 // 高质量缩放算法
|
|
|
|
|
// }));
|
|
|
|
|
// 强制缩放
|
|
|
|
|
sImage.Mutate(x => x.Resize(targetWidth, targetHeight));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5. 确保保存目录存在
|
|
|
|
|
if (!Directory.Exists(saveFolder))
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(saveFolder); // 自动创建目录
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 6. 保存缩放后的图片
|
|
|
|
|
var filePath = Path.Combine(saveFolder, $"Printing{i}.png");
|
|
|
|
|
sImage.SaveAsPng(filePath, new PngEncoder());
|
|
|
|
|
|
|
|
|
|
// 7. 校验保存结果并读取字节数组
|
|
|
|
|
if (File.Exists(filePath))
|
|
|
|
|
{
|
|
|
|
|
secondResult = File.ReadAllBytes(filePath);
|
|
|
|
|
Debug.Log($"第二次截图缩放后保存至:{filePath}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"图片保存失败,文件不存在:{filePath}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// 捕获所有异常(如图片格式错误、权限问题等)
|
|
|
|
|
Debug.LogError($"图片处理失败:{ex.Message}\n{ex.StackTrace}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 恢复原始参数(避免影响后续截图)
|
|
|
|
|
if (verticalLayoutGroup != null)
|
|
|
|
|
verticalLayoutGroup.enabled = false;
|
|
|
|
|
cropWidth = tmpWidth;
|
|
|
|
|
cropHeight = tmpHeight;
|
|
|
|
|
cropOffset = new Vector2(0f, 0f);
|
|
|
|
|
// image.enabled = false;
|
|
|
|
|
|
|
|
|
|
secondResults.Add(secondResult);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var j = 0; j < designParent.childCount; j++)
|
|
|
|
|
{
|
|
|
|
|
designParent.GetChild(j).gameObject.SetActive(true);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-25 15:53:01 +08:00
|
|
|
|
saveFolder = tmpSaveFolder;
|
2025-08-24 08:37:56 +08:00
|
|
|
|
// 触发最终回调
|
|
|
|
|
onBothComplete?.Invoke(firstResult, secondResults);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IEnumerator CoCaptureTwice_ManyToMany(Action<List<byte[]>, List<byte[]>> onBothComplete)
|
|
|
|
|
{
|
|
|
|
|
List<byte[]> firstResults = new List<byte[]>();
|
|
|
|
|
List<byte[]> secondResults = new List<byte[]>();
|
|
|
|
|
|
2025-08-25 15:53:01 +08:00
|
|
|
|
var tmpSaveFolder = saveFolder;
|
2025-08-24 08:37:56 +08:00
|
|
|
|
var mugActualModelRenderFixed = uiRoot.GetComponent<MugActualModelRender_Fixed>();
|
|
|
|
|
saveFolder = Path.Combine(saveFolder, DateTime.Now.ToString("yyyyMMdd_HHmmss"));
|
|
|
|
|
var designParent = mugActualModelRenderFixed.designParent.GetChild(0);
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < designParent.childCount; i++)
|
|
|
|
|
{
|
|
|
|
|
// 存储两次截图的结果
|
|
|
|
|
byte[] firstResult = null;
|
|
|
|
|
byte[] secondResult = null;
|
|
|
|
|
|
|
|
|
|
onlyFileName = $"PreviewImage{i}";
|
|
|
|
|
|
|
|
|
|
var image = designParent.GetChild(i).GetComponent<UnityEngine.UI.Image>();
|
|
|
|
|
image.enabled = true;
|
|
|
|
|
|
|
|
|
|
// 第一次截图(使用基类默认参数)
|
|
|
|
|
Debug.Log("开始第一次截图...");
|
|
|
|
|
yield return StartCoroutine(CaptureAndCrop((firstBytes) =>
|
|
|
|
|
{
|
|
|
|
|
firstResult = firstBytes;
|
|
|
|
|
Debug.Log("第一次截图完成");
|
|
|
|
|
}));
|
|
|
|
|
image.enabled = false;
|
|
|
|
|
|
|
|
|
|
// 确保第一次完成后再执行第二次
|
|
|
|
|
if (firstResult == null)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError("第一次截图失败,取消第二次");
|
|
|
|
|
onBothComplete?.Invoke(null, null);
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool tmpImageActive = image.enabled;
|
|
|
|
|
image.enabled = mugActualModelRenderFixed.productScriptableObject.isShowTemplate;
|
|
|
|
|
|
|
|
|
|
var verticalLayoutGroup = designParent.GetComponent<VerticalLayoutGroup>();
|
|
|
|
|
verticalLayoutGroup.enabled = true;
|
|
|
|
|
|
|
|
|
|
var tmpWidth = cropWidth;
|
|
|
|
|
var tmpHeight = cropHeight;
|
|
|
|
|
var productScriptableObject = mugActualModelRenderFixed.productScriptableObject;
|
|
|
|
|
var screenshotSize = productScriptableObject.screenshotSize;
|
|
|
|
|
cropWidth = (int)screenshotSize.x;
|
|
|
|
|
cropHeight = (int)screenshotSize.y;
|
|
|
|
|
cropOffset = new Vector2(0.5f, 0.5f);
|
|
|
|
|
onlyFileName = $"DesignImage{i}";
|
|
|
|
|
|
|
|
|
|
// 第二次截图(使用修改后的参数)
|
|
|
|
|
Debug.Log("开始第二次截图...");
|
|
|
|
|
yield return StartCoroutine(CaptureAndCrop((secondBytes) =>
|
|
|
|
|
{
|
|
|
|
|
secondResult = secondBytes;
|
|
|
|
|
Debug.Log("第二次截图完成");
|
|
|
|
|
}));
|
|
|
|
|
image.enabled = tmpImageActive;
|
|
|
|
|
|
|
|
|
|
// 1. 校验文件是否存在
|
|
|
|
|
var fileInfo = new FileInfo(fullPath);
|
|
|
|
|
if (!fileInfo.Exists)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"原始图片不存在:{fullPath}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
yield break; // 若在协程中,用 yield break 退出
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// 2. 加载图像并校验原始尺寸
|
|
|
|
|
using (var sImage = SixLabors.ImageSharp.Image.Load(fileInfo.FullName))
|
|
|
|
|
{
|
|
|
|
|
// 校验原始图片尺寸是否有效
|
|
|
|
|
if (sImage.Width <= 0 || sImage.Height <= 0)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"加载的图片尺寸无效:宽={sImage.Width}, 高={sImage.Height}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (productScriptableObject.printingSize.x != 0)
|
|
|
|
|
{
|
|
|
|
|
// 3. 校验缩放宽度是否有效
|
|
|
|
|
int targetWidth = (int)ConvertMmToPixel(productScriptableObject.printingSize.x);
|
|
|
|
|
int targetHeight = (int)ConvertMmToPixel(productScriptableObject.printingSize.y);
|
|
|
|
|
if (targetWidth <= 0)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"缩放宽度无效(必须大于 0):{targetWidth}");
|
|
|
|
|
// 可选:使用默认宽度(如 200)避免错误
|
|
|
|
|
targetWidth = 200;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 等比缩放(确保目标尺寸有效)
|
|
|
|
|
// sImage.Mutate(x => x.Resize(new ResizeOptions
|
|
|
|
|
// {
|
|
|
|
|
// Size = new Size(targetWidth, targetHeight), // 高度为0则自动计算
|
|
|
|
|
// Mode = ResizeMode.Max,
|
|
|
|
|
// Sampler = KnownResamplers.Lanczos3 // 高质量缩放算法
|
|
|
|
|
// }));
|
|
|
|
|
// 强制缩放
|
|
|
|
|
sImage.Mutate(x => x.Resize(targetWidth, targetHeight));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5. 确保保存目录存在
|
|
|
|
|
if (!Directory.Exists(saveFolder))
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(saveFolder); // 自动创建目录
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 6. 保存缩放后的图片
|
|
|
|
|
var filePath = Path.Combine(saveFolder, $"Printing{i}.png");
|
|
|
|
|
sImage.SaveAsPng(filePath, new PngEncoder());
|
|
|
|
|
|
|
|
|
|
// 7. 校验保存结果并读取字节数组
|
|
|
|
|
if (File.Exists(filePath))
|
|
|
|
|
{
|
|
|
|
|
secondResult = File.ReadAllBytes(filePath);
|
|
|
|
|
Debug.Log($"第二次截图缩放后保存至:{filePath}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"图片保存失败,文件不存在:{filePath}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// 捕获所有异常(如图片格式错误、权限问题等)
|
|
|
|
|
Debug.LogError($"图片处理失败:{ex.Message}\n{ex.StackTrace}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 恢复原始参数(避免影响后续截图)
|
|
|
|
|
verticalLayoutGroup.enabled = false;
|
|
|
|
|
cropWidth = tmpWidth;
|
|
|
|
|
cropHeight = tmpHeight;
|
|
|
|
|
cropOffset = new Vector2(0f, 0f);
|
|
|
|
|
image.enabled = false;
|
|
|
|
|
|
|
|
|
|
firstResults.Add(firstResult);
|
|
|
|
|
secondResults.Add(secondResult);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-25 15:53:01 +08:00
|
|
|
|
saveFolder = tmpSaveFolder;
|
2025-08-24 08:37:56 +08:00
|
|
|
|
// 触发最终回调
|
|
|
|
|
onBothComplete?.Invoke(firstResults, secondResults);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-22 00:33:25 +08:00
|
|
|
|
// 协程:顺序执行一次设计截图
|
2025-08-25 15:53:01 +08:00
|
|
|
|
private IEnumerator CoCaptureOnlyDesign(Action<byte[], string> onBothComplete)
|
2025-08-22 00:33:25 +08:00
|
|
|
|
{
|
|
|
|
|
// 存储两次截图的结果
|
|
|
|
|
byte[] secondResult = null;
|
2025-08-25 15:53:01 +08:00
|
|
|
|
string tmpFolder = "";
|
2025-08-22 00:33:25 +08:00
|
|
|
|
|
2025-08-25 15:53:01 +08:00
|
|
|
|
var tmpSaveFolder = saveFolder;
|
2025-08-22 00:33:25 +08:00
|
|
|
|
saveFolder = Path.Combine(saveFolder, DateTime.Now.ToString("yyyyMMdd_HHmmss"));
|
2025-08-25 15:53:01 +08:00
|
|
|
|
tmpFolder = saveFolder;
|
|
|
|
|
|
2025-08-22 00:33:25 +08:00
|
|
|
|
var mugActualModelRenderFixed = uiRoot.GetComponent<MugActualModelRender_Fixed>();
|
|
|
|
|
var image = mugActualModelRenderFixed.designParent.GetChild(0).GetComponent<UnityEngine.UI.Image>();
|
|
|
|
|
|
|
|
|
|
bool tmpImageActive = image.enabled;
|
|
|
|
|
image.enabled = mugActualModelRenderFixed.productScriptableObject.isShowTemplate;
|
|
|
|
|
|
|
|
|
|
var verticalLayoutGroup = mugActualModelRenderFixed.designParent.GetComponent<VerticalLayoutGroup>();
|
|
|
|
|
verticalLayoutGroup.enabled = true;
|
|
|
|
|
|
|
|
|
|
var tmpWidth = cropWidth;
|
|
|
|
|
var tmpHeight = cropHeight;
|
|
|
|
|
var productScriptableObject = mugActualModelRenderFixed.productScriptableObject;
|
|
|
|
|
var screenshotSize = productScriptableObject.screenshotSize;
|
|
|
|
|
cropWidth = (int)screenshotSize.x;
|
|
|
|
|
cropHeight = (int)screenshotSize.y;
|
|
|
|
|
cropOffset = new Vector2(0.5f, 0.5f);
|
|
|
|
|
onlyFileName = "DesignImage1";
|
|
|
|
|
|
|
|
|
|
// 第二次截图(使用修改后的参数)
|
|
|
|
|
Debug.Log("开始第二次截图...");
|
|
|
|
|
yield return StartCoroutine(CaptureAndCrop((secondBytes) =>
|
|
|
|
|
{
|
|
|
|
|
secondResult = secondBytes;
|
|
|
|
|
Debug.Log("第二次截图完成");
|
|
|
|
|
}));
|
|
|
|
|
image.enabled = tmpImageActive;
|
2025-08-24 08:37:56 +08:00
|
|
|
|
|
2025-08-22 00:33:25 +08:00
|
|
|
|
// 1. 校验文件是否存在
|
|
|
|
|
var fileInfo = new FileInfo(fullPath);
|
|
|
|
|
if (!fileInfo.Exists)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"原始图片不存在:{fullPath}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
yield break; // 若在协程中,用 yield break 退出
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// 2. 加载图像并校验原始尺寸
|
|
|
|
|
using (var sImage = SixLabors.ImageSharp.Image.Load(fileInfo.FullName))
|
|
|
|
|
{
|
|
|
|
|
// 校验原始图片尺寸是否有效
|
|
|
|
|
if (sImage.Width <= 0 || sImage.Height <= 0)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"加载的图片尺寸无效:宽={sImage.Width}, 高={sImage.Height}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (productScriptableObject.printingSize.x != 0)
|
|
|
|
|
{
|
|
|
|
|
// 3. 校验缩放宽度是否有效
|
|
|
|
|
int targetWidth = (int)ConvertMmToPixel(productScriptableObject.printingSize.x);
|
|
|
|
|
int targetHeight = (int)ConvertMmToPixel(productScriptableObject.printingSize.y);
|
|
|
|
|
if (targetWidth <= 0)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"缩放宽度无效(必须大于 0):{targetWidth}");
|
|
|
|
|
// 可选:使用默认宽度(如 200)避免错误
|
|
|
|
|
targetWidth = 200;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 等比缩放(确保目标尺寸有效)
|
|
|
|
|
// sImage.Mutate(x => x.Resize(new ResizeOptions
|
|
|
|
|
// {
|
|
|
|
|
// Size = new Size(targetWidth, targetHeight), // 高度为0则自动计算
|
|
|
|
|
// Mode = ResizeMode.Max,
|
|
|
|
|
// Sampler = KnownResamplers.Lanczos3 // 高质量缩放算法
|
|
|
|
|
// }));
|
|
|
|
|
// 强制缩放
|
|
|
|
|
sImage.Mutate(x => x.Resize(targetWidth, targetHeight));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5. 确保保存目录存在
|
|
|
|
|
if (!Directory.Exists(saveFolder))
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(saveFolder); // 自动创建目录
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 6. 保存缩放后的图片
|
|
|
|
|
var filePath = Path.Combine(saveFolder, "Printing1.png");
|
|
|
|
|
sImage.SaveAsPng(filePath, new PngEncoder());
|
|
|
|
|
|
|
|
|
|
// 7. 校验保存结果并读取字节数组
|
|
|
|
|
if (File.Exists(filePath))
|
|
|
|
|
{
|
|
|
|
|
secondResult = File.ReadAllBytes(filePath);
|
|
|
|
|
Debug.Log($"第二次截图缩放后保存至:{filePath}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"图片保存失败,文件不存在:{filePath}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// 捕获所有异常(如图片格式错误、权限问题等)
|
|
|
|
|
Debug.LogError($"图片处理失败:{ex.Message}\n{ex.StackTrace}");
|
|
|
|
|
secondResult = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 恢复原始参数(避免影响后续截图)
|
|
|
|
|
verticalLayoutGroup.enabled = false;
|
|
|
|
|
cropWidth = tmpWidth;
|
|
|
|
|
cropHeight = tmpHeight;
|
|
|
|
|
cropOffset = new Vector2(0f, 0f);
|
|
|
|
|
image.enabled = false;
|
|
|
|
|
|
2025-08-25 15:53:01 +08:00
|
|
|
|
saveFolder = tmpSaveFolder;
|
2025-08-22 00:33:25 +08:00
|
|
|
|
// 触发最终回调
|
2025-08-25 15:53:01 +08:00
|
|
|
|
onBothComplete?.Invoke(secondResult, tmpFolder);
|
2025-08-22 00:33:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 可选:重写基类的立即截图方法,使其默认执行两次
|
|
|
|
|
// public override void CaptureAndCropNow(Action<byte[]> callback = null)
|
|
|
|
|
// {
|
|
|
|
|
// base.CaptureAndCropNow(callback);
|
|
|
|
|
// // // 如果需要点击按钮时默认执行两次,可在这里调用CaptureTwice
|
|
|
|
|
// // CaptureTwice((first, second) =>
|
|
|
|
|
// // {
|
|
|
|
|
// // callback?.Invoke(first); // 这里仅返回第一次的结果,或按需处理
|
|
|
|
|
// // });
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
}
|