Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/SpotterScope/UnitySpotterScopeService.cs

136 lines
4.4 KiB
C#
Raw Normal View History

2025-06-24 23:49:13 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using BITKit.Entities;
using BITKit.WorldNode;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Unity.Mathematics;
using UnityEngine;
using YamlDotNet.Serialization;
using Object = UnityEngine.Object;
namespace Net.Project.B.World
{
public class UnitySnapshotService : ISnapshotService
{
private readonly IEntitiesService _entitiesService;
private readonly ILogger<UnitySnapshotService> _logger;
private readonly ISerializer _serializer;
private readonly IDeserializer _deserializer;
public UnitySnapshotService(ISerializer serializer, IDeserializer deserializer, ILogger<UnitySnapshotService> logger, IEntitiesService entitiesService)
{
_serializer = serializer;
_deserializer = deserializer;
_logger = logger;
_entitiesService = entitiesService;
}
public string Directory { get; } = Path.Combine(Application.persistentDataPath, "Snapshots").Replace('/', '\\');
public async UniTask<SnapshotData> Snapshot(float3 position, quaternion rotation, int fov)
{
var renderTexture = new RenderTexture(Screen.width, Screen.height, 32);
var camera = Camera.main;
if (!camera) throw new DriveNotFoundException("未找到MainCamera");
camera.targetTexture = renderTexture;
camera.Render();
camera.targetTexture = null;
var screenshot = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGBA32, false);
RenderTexture.active = renderTexture;
screenshot.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
screenshot.Apply();
RenderTexture.active = null;
Object.Destroy(renderTexture);
var bytes = screenshot.EncodeToPNG();
var fileName = DateTime.Now.Ticks;
var path = Path.Combine(Directory, fileName + ".png");
new DirectoryInfo(Directory).Create();
await File.WriteAllBytesAsync(path, bytes);
var data = new SnapshotData
{
FileName = null,
Name = null,
Description = null,
CreateTime = default,
Position = default,
Rotation = default
};
data.FileName = path;
data.Name = "无标题";
data.Description = "无描述";
data.CreateTime = DateTime.Now;
data.Position = camera.transform.position;
data.Rotation = camera.transform.rotation;
if (Physics.Raycast(camera.transform.position, camera.transform.forward, out var hit))
{
if(_entitiesService.Entities.TryGetValue(hit.transform.gameObject.GetInstanceID(),out var hitEntity) && hitEntity.ServiceProvider.GetService<WorldInfoNode>() is {} node)
{
data.Name = node.Name;
data.Description = node.Description;
_logger.LogInformation($"相机命中了:{hit.transform.name}@{node.Name}:{node.Description}");
}
else
{
_logger.LogInformation($"相机命中了:{hit.transform.name},但无有效目标");
}
}
var yaml = _serializer.Serialize(data);
await File.WriteAllTextAsync(Path.Combine(Directory, fileName + ".yaml"), yaml);
await UniTask.SwitchToMainThread();
OnSnapshot?.Invoke(data);
return data;
}
public async UniTask<IReadOnlyList<SnapshotData>> GetSnapshots()
{
var list = new List<SnapshotData>();
new DirectoryInfo(Directory).Create();
foreach (var fileInfo in new DirectoryInfo(Directory).GetFiles("*.yaml"))
{
var yaml = await File.ReadAllTextAsync(fileInfo.FullName);
var data = _deserializer.Deserialize<SnapshotData>(yaml);
list.Add(data);
}
return list;
}
public static event Action<SnapshotData> OnSnapshot;
event Action<SnapshotData> ISnapshotService.OnSnapshot
{
add => OnSnapshot += value;
remove => OnSnapshot -= value;
}
}
}