整合扩展
This commit is contained in:
parent
7ae4ddac09
commit
919678b811
@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using AlicizaX;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace UnityEngine
|
||||
{
|
||||
@ -82,6 +84,42 @@ namespace UnityEngine
|
||||
}
|
||||
}
|
||||
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static class RendererExtensions
|
||||
{
|
||||
public static bool IsVisibleFrom(this Renderer renderer, Camera camera)
|
||||
{
|
||||
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
|
||||
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
|
||||
}
|
||||
}
|
||||
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static class CameraExtensions
|
||||
{
|
||||
public static Texture2D GetCaptureScreenshot(this Camera camera, float scale = 0.5f)
|
||||
{
|
||||
Rect rect = new Rect(0f, 0f, Screen.width * scale, Screen.height * scale);
|
||||
string name = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
|
||||
RenderTexture renderTexture = RenderTexture.GetTemporary((int)rect.width, (int)rect.height, 0);
|
||||
renderTexture.name = SceneManager.GetActiveScene().name + "_" + renderTexture.width + "_" + renderTexture.height + "_" + name;
|
||||
camera.targetTexture = renderTexture;
|
||||
camera.Render();
|
||||
|
||||
RenderTexture.active = renderTexture;
|
||||
Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false)
|
||||
{
|
||||
name = renderTexture.name
|
||||
};
|
||||
screenShot.ReadPixels(rect, 0, 0);
|
||||
screenShot.Apply();
|
||||
camera.targetTexture = null;
|
||||
RenderTexture.active = null;
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
return screenShot;
|
||||
}
|
||||
}
|
||||
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static class AngleExtensions
|
||||
{
|
||||
|
||||
@ -34,5 +34,35 @@
|
||||
lhs.Scale(rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将三维向量投影到 XZ 平面。
|
||||
/// </summary>
|
||||
public static Vector2 IgnoreYAxis(this Vector3 vector3)
|
||||
{
|
||||
return new Vector2(vector3.x, vector3.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保留 XZ 分量并清空 Y 轴。
|
||||
/// </summary>
|
||||
public static Vector3 FlattenY(this Vector3 vector3)
|
||||
{
|
||||
return new Vector3(vector3.x, 0f, vector3.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断目标点是否位于当前方向的左侧。
|
||||
/// </summary>
|
||||
public static bool PointOnLeftSideOfVector(this Vector3 vector3, Vector3 originPoint, Vector3 point)
|
||||
{
|
||||
Vector2 origin = originPoint.IgnoreYAxis();
|
||||
Vector2 targetDirection = (point.IgnoreYAxis() - origin).normalized;
|
||||
Vector2 direction = vector3.IgnoreYAxis();
|
||||
float verticalX = origin.x;
|
||||
float verticalY = (-verticalX * direction.x) / direction.y;
|
||||
Vector2 normalVertical = new Vector2(verticalX, verticalY).normalized;
|
||||
return Vector2.Dot(normalVertical, targetDirection) < 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,206 +0,0 @@
|
||||
using AlicizaX;
|
||||
using ICSharpCode.SharpZipLib.GZip;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认压缩解压缩辅助器。
|
||||
/// </summary>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public class CompressionUtility
|
||||
{
|
||||
private const int CachedBytesLength = 0x1000;
|
||||
private static readonly byte[] m_CachedBytes = new byte[CachedBytesLength];
|
||||
|
||||
/// <summary>
|
||||
/// 压缩数据。
|
||||
/// </summary>
|
||||
/// <param name="bytes">要压缩的数据的二进制流。</param>
|
||||
/// <param name="offset">要压缩的数据的二进制流的偏移。</param>
|
||||
/// <param name="length">要压缩的数据的二进制流的长度。</param>
|
||||
/// <param name="compressedStream">压缩后的数据的二进制流。</param>
|
||||
/// <returns>是否压缩数据成功。</returns>
|
||||
public static bool Compress(byte[] bytes, int offset, int length, Stream compressedStream)
|
||||
{
|
||||
if (bytes == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offset < 0 || length < 0 || offset + length > bytes.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (compressedStream == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
GZipOutputStream gZipOutputStream = new GZipOutputStream(compressedStream);
|
||||
gZipOutputStream.Write(bytes, offset, length);
|
||||
gZipOutputStream.Finish();
|
||||
ProcessHeader(compressedStream);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 压缩数据。
|
||||
/// </summary>
|
||||
/// <param name="stream">要压缩的数据的二进制流。</param>
|
||||
/// <param name="compressedStream">压缩后的数据的二进制流。</param>
|
||||
/// <returns>是否压缩数据成功。</returns>
|
||||
public static bool Compress(Stream stream, Stream compressedStream)
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (compressedStream == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
GZipOutputStream gZipOutputStream = new GZipOutputStream(compressedStream);
|
||||
int bytesRead = 0;
|
||||
while ((bytesRead = stream.Read(m_CachedBytes, 0, CachedBytesLength)) > 0)
|
||||
{
|
||||
gZipOutputStream.Write(m_CachedBytes, 0, bytesRead);
|
||||
}
|
||||
|
||||
gZipOutputStream.Finish();
|
||||
ProcessHeader(compressedStream);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(m_CachedBytes, 0, CachedBytesLength);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解压缩数据。
|
||||
/// </summary>
|
||||
/// <param name="bytes">要解压缩的数据的二进制流。</param>
|
||||
/// <param name="offset">要解压缩的数据的二进制流的偏移。</param>
|
||||
/// <param name="length">要解压缩的数据的二进制流的长度。</param>
|
||||
/// <param name="decompressedStream">解压缩后的数据的二进制流。</param>
|
||||
/// <returns>是否解压缩数据成功。</returns>
|
||||
public static bool Decompress(byte[] bytes, int offset, int length, Stream decompressedStream)
|
||||
{
|
||||
if (bytes == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offset < 0 || length < 0 || offset + length > bytes.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (decompressedStream == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MemoryStream memoryStream = null;
|
||||
try
|
||||
{
|
||||
memoryStream = new MemoryStream(bytes, offset, length, false);
|
||||
using (GZipInputStream gZipInputStream = new GZipInputStream(memoryStream))
|
||||
{
|
||||
int bytesRead = 0;
|
||||
while ((bytesRead = gZipInputStream.Read(m_CachedBytes, 0, CachedBytesLength)) > 0)
|
||||
{
|
||||
decompressedStream.Write(m_CachedBytes, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (memoryStream != null)
|
||||
{
|
||||
memoryStream.Dispose();
|
||||
memoryStream = null;
|
||||
}
|
||||
|
||||
Array.Clear(m_CachedBytes, 0, CachedBytesLength);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解压缩数据。
|
||||
/// </summary>
|
||||
/// <param name="stream">要解压缩的数据的二进制流。</param>
|
||||
/// <param name="decompressedStream">解压缩后的数据的二进制流。</param>
|
||||
/// <returns>是否解压缩数据成功。</returns>
|
||||
public static bool Decompress(Stream stream, Stream decompressedStream)
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (decompressedStream == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
GZipInputStream gZipInputStream = new GZipInputStream(stream);
|
||||
int bytesRead = 0;
|
||||
while ((bytesRead = gZipInputStream.Read(m_CachedBytes, 0, CachedBytesLength)) > 0)
|
||||
{
|
||||
decompressedStream.Write(m_CachedBytes, 0, bytesRead);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(m_CachedBytes, 0, CachedBytesLength);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessHeader(Stream compressedStream)
|
||||
{
|
||||
if (compressedStream.Length >= 8L)
|
||||
{
|
||||
long current = compressedStream.Position;
|
||||
compressedStream.Position = 4L;
|
||||
compressedStream.WriteByte(25);
|
||||
compressedStream.WriteByte(134);
|
||||
compressedStream.WriteByte(2);
|
||||
compressedStream.WriteByte(32);
|
||||
compressedStream.Position = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef59646f457548b0962c49a3434cf7e3
|
||||
timeCreated: 1758265544
|
||||
@ -1,150 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 坐标帮助类
|
||||
/// </summary>
|
||||
public static class PositionHelper
|
||||
{
|
||||
public static Vector3 RayCastV2ToV3(Vector2 pos)
|
||||
{
|
||||
return new Vector3(pos.x, 0, pos.y);
|
||||
}
|
||||
|
||||
public static Vector3 RayCastXYToV3(float x, float y)
|
||||
{
|
||||
return new Vector3(x, 0, y);
|
||||
}
|
||||
|
||||
public static Vector3 RayCastV3ToV3(Vector3 pos)
|
||||
{
|
||||
return new Vector3(pos.x, 0, pos.z);
|
||||
}
|
||||
|
||||
public static Quaternion AngleToQuaternion(int angle)
|
||||
{
|
||||
return Quaternion.AngleAxis(-angle, Vector3.up) * Quaternion.AngleAxis(90, Vector3.up);
|
||||
}
|
||||
|
||||
public static Quaternion GetVector3ToQuaternion(Vector3 source, Vector3 dire)
|
||||
{
|
||||
Vector3 nowPos = source;
|
||||
if (nowPos == dire)
|
||||
{
|
||||
return new Quaternion();
|
||||
}
|
||||
|
||||
Vector3 direction = (dire - nowPos).normalized;
|
||||
return Quaternion.LookRotation(direction, Vector3.up);
|
||||
}
|
||||
|
||||
|
||||
public static float Distance2D(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector2 d1 = new Vector2(v1.x, v1.z);
|
||||
Vector2 d2 = new Vector2(v2.x, v2.z);
|
||||
return Vector2.Distance(d1, d2);
|
||||
}
|
||||
|
||||
public static Quaternion GetAngleToQuaternion(float angle)
|
||||
{
|
||||
return Quaternion.AngleAxis(-angle, Vector3.up) * Quaternion.AngleAxis(90, Vector3.up);
|
||||
}
|
||||
|
||||
public static float Vector3ToAngle360(Vector3 from, Vector3 to)
|
||||
{
|
||||
float angle = Vector3.Angle(from, to);
|
||||
Vector3 cross = Vector3.Cross(from, to);
|
||||
return cross.y > 0 ? angle : 360 - angle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 求点到直线的距离,采用数学公式Ax+By+C = 0; d = A*p.x + B * p.y + C / sqrt(A^2 + B ^ 2)
|
||||
/// </summary>
|
||||
/// <param name="startPoint">线的起点</param>
|
||||
/// <param name="endPoint">线的终点</param>
|
||||
/// <param name="point">点</param>
|
||||
/// <returns></returns>
|
||||
public static float DistanceOfPointToVector(Vector3 startPoint, Vector3 endPoint, Vector3 point)
|
||||
{
|
||||
Vector2 startVe2 = startPoint.IgnoreYAxis();
|
||||
Vector2 endVe2 = endPoint.IgnoreYAxis();
|
||||
float A = endVe2.y - startVe2.y;
|
||||
float B = startVe2.x - endVe2.x;
|
||||
float C = endVe2.x * startVe2.y - startVe2.x * endVe2.y;
|
||||
float denominator = Mathf.Sqrt(A * A + B * B);
|
||||
Vector2 pointVe2 = point.IgnoreYAxis();
|
||||
return Mathf.Abs((A * pointVe2.x + B * pointVe2.y + C) / denominator);
|
||||
;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断射线是否碰撞到球体,如果碰撞到,返回射线起点到碰撞点之间的距离
|
||||
/// </summary>
|
||||
/// <param name="ray">射线</param>
|
||||
/// <param name="center">中心点</param>
|
||||
/// <param name="redis">半径</param>
|
||||
/// <param name="dist">距离</param>
|
||||
/// <returns></returns>
|
||||
public static bool RayCastSphere(Ray ray, Vector3 center, float redis, out float dist)
|
||||
{
|
||||
dist = 0;
|
||||
Vector3 ma = center - ray.origin;
|
||||
float distance = Vector3.Cross(ma, ray.direction).magnitude / ray.direction.magnitude;
|
||||
if (distance < redis)
|
||||
{
|
||||
float op = PythagoreanTheorem(Vector3.Distance(center, ray.origin), distance);
|
||||
float rp = PythagoreanTheorem(redis, distance);
|
||||
dist = op - rp;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 勾股定理
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static float PythagoreanTheorem(float x, float y)
|
||||
{
|
||||
return Mathf.Sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去掉三维向量的Y轴,把向量投射到xz平面。
|
||||
/// </summary>
|
||||
/// <param name="vector3"></param>
|
||||
/// <returns></returns>
|
||||
public static Vector2 IgnoreYAxis(this Vector3 vector3)
|
||||
{
|
||||
return new Vector2(vector3.x, vector3.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断目标点是否位于向量的左边
|
||||
/// </summary>
|
||||
/// <returns>True is on left, false is on right</returns>
|
||||
public static bool PointOnLeftSideOfVector(this Vector3 vector3, Vector3 originPoint, Vector3 point)
|
||||
{
|
||||
Vector2 originVec2 = originPoint.IgnoreYAxis();
|
||||
|
||||
Vector2 pointVec2 = (point.IgnoreYAxis() - originVec2).normalized;
|
||||
|
||||
Vector2 vector2 = vector3.IgnoreYAxis();
|
||||
|
||||
float verticalX = originVec2.x;
|
||||
|
||||
float verticalY = (-verticalX * vector2.x) / vector2.y;
|
||||
|
||||
Vector2 norVertical = (new Vector2(verticalX, verticalY)).normalized;
|
||||
|
||||
float dotValue = Vector2.Dot(norVertical, pointVec2);
|
||||
|
||||
return dotValue < 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb356e4ecfd547b280b88ca74a847918
|
||||
timeCreated: 1666447289
|
||||
@ -1,266 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏时间帮助类
|
||||
/// </summary>
|
||||
public static class TimerHelper
|
||||
{
|
||||
private static readonly DateTime EpochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
private static readonly long Epoch = EpochTime.Ticks;
|
||||
|
||||
/// <summary>
|
||||
/// 时间差
|
||||
/// </summary>
|
||||
private static long _differenceTime;
|
||||
|
||||
private static bool _isSecLevel = true;
|
||||
|
||||
/// <summary>
|
||||
/// 微秒
|
||||
/// </summary>
|
||||
public const long TicksPerMicrosecond = 1; //100微秒
|
||||
|
||||
/// <summary>
|
||||
/// 10微秒
|
||||
/// </summary>
|
||||
public const long TicksPer = 10 * TicksPerMicrosecond;
|
||||
|
||||
/// <summary>
|
||||
/// 1毫秒
|
||||
/// </summary>
|
||||
public const long TicksMillisecondUnit = TicksPer * 1000; //毫秒
|
||||
|
||||
/// <summary>
|
||||
/// 1秒
|
||||
/// </summary>
|
||||
public const long TicksSecondUnit = TicksMillisecondUnit * 1000; // 秒 //10000000
|
||||
|
||||
/// <summary>
|
||||
/// 设置时间差
|
||||
/// </summary>
|
||||
/// <param name="timeSpan"></param>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static void SetDifferenceTime(long timeSpan)
|
||||
{
|
||||
if (timeSpan > 1000000000000)
|
||||
{
|
||||
_isSecLevel = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isSecLevel = true;
|
||||
}
|
||||
|
||||
if (_isSecLevel)
|
||||
{
|
||||
_differenceTime = timeSpan - ClientNow();
|
||||
}
|
||||
else
|
||||
{
|
||||
_differenceTime = timeSpan - ClientNowMillisecond();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 毫秒级
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long ClientNowMillisecond()
|
||||
{
|
||||
return (DateTime.UtcNow.Ticks - Epoch) / TicksMillisecondUnit;
|
||||
}
|
||||
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long ServerToday()
|
||||
{
|
||||
if (_isSecLevel)
|
||||
{
|
||||
return _differenceTime + ClientToday();
|
||||
}
|
||||
|
||||
return (_differenceTime + ClientTodayMillisecond()) / 1000;
|
||||
}
|
||||
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long ClientTodayMillisecond()
|
||||
{
|
||||
return (DateTime.Now.Date.ToUniversalTime().Ticks - Epoch) / 10000;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 服务器当前时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long ServerNow() //秒级
|
||||
{
|
||||
if (_isSecLevel)
|
||||
{
|
||||
return _differenceTime + ClientNow();
|
||||
}
|
||||
|
||||
return (_differenceTime + ClientNowMillisecond()) / 1000;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将秒数转换成TimeSpan
|
||||
/// </summary>
|
||||
/// <param name="seconds">秒</param>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static TimeSpan FromSeconds(int seconds)
|
||||
{
|
||||
return TimeSpan.FromSeconds(seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 今天的客户端时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long ClientToday()
|
||||
{
|
||||
return (DateTime.Now.Date.ToUniversalTime().Ticks - Epoch) / TicksSecondUnit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端时间,毫秒
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long ClientNow()
|
||||
{
|
||||
return (DateTime.UtcNow.Ticks - Epoch) / 10000;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端时间。秒
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long ClientNowSeconds()
|
||||
{
|
||||
return (DateTime.UtcNow.Ticks - Epoch) / 10000000;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long Now()
|
||||
{
|
||||
return ClientNow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UTC时间 秒
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long UnixTimeSeconds()
|
||||
{
|
||||
return new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UTC时间 毫秒
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long UnixTimeMilliseconds()
|
||||
{
|
||||
return new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 按照UTC时间判断两个时间戳是否是同一天
|
||||
/// </summary>
|
||||
/// <param name="timestamp1">时间戳1</param>
|
||||
/// <param name="timestamp2">时间戳2</param>
|
||||
/// <returns>是否是同一天</returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static bool IsUnixSameDay(long timestamp1, long timestamp2)
|
||||
{
|
||||
var time1 = UtcToUtcDateTime(timestamp1);
|
||||
var time2 = UtcToUtcDateTime(timestamp2);
|
||||
return time1.Date.Year == time2.Date.Year && time1.Date.Month == time2.Date.Month && time1.Date.Day == time2.Date.Day;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按照本地时间判断两个时间戳是否是同一天
|
||||
/// </summary>
|
||||
/// <param name="timestamp1">时间戳1</param>
|
||||
/// <param name="timestamp2">时间戳2</param>
|
||||
/// <returns>是否是同一天</returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static bool IsLocalSameDay(long timestamp1, long timestamp2)
|
||||
{
|
||||
var time1 = UtcToLocalDateTime(timestamp1);
|
||||
var time2 = UtcToLocalDateTime(timestamp2);
|
||||
return time1.Date.Year == time2.Date.Year && time1.Date.Month == time2.Date.Month && time1.Date.Day == time2.Date.Day;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UTC 时间戳 转换成UTC时间
|
||||
/// </summary>
|
||||
/// <param name="utcTimestamp">UTC时间戳,单位秒</param>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static DateTime UtcToUtcDateTime(long utcTimestamp)
|
||||
{
|
||||
return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).UtcDateTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UTC 时间戳 转换成本地时间
|
||||
/// </summary>
|
||||
/// <param name="utcTimestamp">UTC时间戳,单位秒</param>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static DateTime UtcToLocalDateTime(long utcTimestamp)
|
||||
{
|
||||
return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).LocalDateTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断两个时间是否是同一天
|
||||
/// </summary>
|
||||
/// <param name="time1">时间1</param>
|
||||
/// <param name="time2">时间2</param>
|
||||
/// <returns>是否是同一天</returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static bool IsSameDay(DateTime time1, DateTime time2)
|
||||
{
|
||||
return time1.Date.Year == time2.Date.Year && time1.Date.Month == time2.Date.Month && time1.Date.Day == time2.Date.Day;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定时间转换成Unix时间戳的时间差,单位秒
|
||||
/// </summary>
|
||||
/// <param name="time">指定时间</param>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long LocalTimeToUnixTimeSeconds(DateTime time)
|
||||
{
|
||||
var utcDateTime = time.ToUniversalTime();
|
||||
return (long)(utcDateTime - EpochTime).TotalSeconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定时间转换成Unix时间戳的时间差,单位毫秒
|
||||
/// </summary>
|
||||
/// <param name="time">指定时间</param>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static long LocalTimeToUnixTimeMilliseconds(DateTime time)
|
||||
{
|
||||
var utcDateTime = time.ToUniversalTime();
|
||||
return (long)(utcDateTime - EpochTime).TotalMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d61562907c14a5295de01e78a41cd22
|
||||
timeCreated: 1666538474
|
||||
@ -1,63 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// Unity 渲染帮助类
|
||||
/// </summary>
|
||||
public static class UnityRendererHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 判断渲染组件是否在相机范围内
|
||||
/// </summary>
|
||||
/// <param name="renderer">渲染组件</param>
|
||||
/// <param name="camera">相机对象</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsVisibleFrom(Renderer renderer, Camera camera)
|
||||
{
|
||||
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
|
||||
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断渲染组件是否在相机范围内
|
||||
/// </summary>
|
||||
/// <param name="renderer">渲染对象</param>
|
||||
/// <param name="camera">相机对象</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsVisibleFrom(MeshRenderer renderer, Camera camera)
|
||||
{
|
||||
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
|
||||
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取相机快照
|
||||
/// </summary>
|
||||
/// <param name="main">相机</param>
|
||||
/// <param name="scale">缩放比</param>
|
||||
public static Texture2D GetCaptureScreenshot(Camera main, float scale = 0.5f)
|
||||
{
|
||||
Rect rect = new Rect(0, 0, Screen.width * scale, Screen.height * scale);
|
||||
string name = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
|
||||
RenderTexture renderTexture = RenderTexture.GetTemporary((int)rect.width, (int)rect.height, 0);
|
||||
renderTexture.name = SceneManager.GetActiveScene().name + "_" + renderTexture.width + "_" + renderTexture.height + "_" + name;
|
||||
main.targetTexture = renderTexture;
|
||||
main.Render();
|
||||
|
||||
RenderTexture.active = renderTexture;
|
||||
Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false)
|
||||
{
|
||||
name = renderTexture.name
|
||||
};
|
||||
screenShot.ReadPixels(rect, 0, 0);
|
||||
screenShot.Apply();
|
||||
main.targetTexture = null;
|
||||
RenderTexture.active = null;
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
return screenShot;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8cc8709b4b6495eab2f7dcba3529dcf
|
||||
timeCreated: 1654011360
|
||||
@ -1,327 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using ICSharpCode.SharpZipLib.Checksums;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 压缩帮助类
|
||||
/// </summary>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static class ZipHelper
|
||||
{
|
||||
private static readonly Crc32 CRC = new Crc32();
|
||||
|
||||
/// <summary>
|
||||
/// 压缩文件夹
|
||||
/// </summary>
|
||||
/// <param name="folderToZip">要压缩的文件夹路径</param>
|
||||
/// <param name="stream">压缩前的Stream,方法执行后变为压缩完成后的文件</param>
|
||||
/// <param name="password">密码</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static bool CompressDirectoryToStream(string folderToZip, Stream stream, string password = null)
|
||||
{
|
||||
return CompressDirectoryToZipStream(folderToZip, stream, password) != null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 压缩文件夹
|
||||
/// </summary>
|
||||
/// <param name="folderToZip">要压缩的文件夹路径</param>
|
||||
/// <param name="stream">压缩前的Stream,方法执行后变为压缩完成后的文件</param>
|
||||
/// <param name="password">密码</param>
|
||||
/// <returns>是否压缩成功返回ZipOutputStream,否则返回null</returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static ZipOutputStream CompressDirectoryToZipStream(string folderToZip, Stream stream, string password = null)
|
||||
{
|
||||
if (!Directory.Exists(folderToZip))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ZipOutputStream zipStream = new ZipOutputStream(stream);
|
||||
zipStream.SetLevel(6);
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
zipStream.Password = password;
|
||||
}
|
||||
|
||||
if (CompressDirectory(folderToZip, zipStream, ""))
|
||||
{
|
||||
zipStream.Finish();
|
||||
return zipStream;
|
||||
}
|
||||
|
||||
GC.Collect(1);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 递归压缩文件夹的内部方法
|
||||
/// </summary>
|
||||
/// <param name="folderToZip">要压缩的文件夹路径</param>
|
||||
/// <param name="zipStream">压缩输出流</param>
|
||||
/// <param name="parentFolderName">此文件夹的上级文件夹</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
private static bool CompressDirectory(string folderToZip, ZipOutputStream zipStream, string parentFolderName)
|
||||
{
|
||||
//这段是创建空文件夹,注释掉可以去掉空文件夹(因为在写入文件的时候也会创建文件夹)
|
||||
if (parentFolderName.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var ent = new ZipEntry(parentFolderName + "/");
|
||||
zipStream.PutNextEntry(ent);
|
||||
zipStream.Flush();
|
||||
}
|
||||
|
||||
var files = Directory.GetFiles(folderToZip);
|
||||
foreach (string file in files)
|
||||
{
|
||||
byte[] buffer = File.ReadAllBytes(file);
|
||||
var path = Path.GetFileName(file);
|
||||
if (parentFolderName.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
path = parentFolderName + Path.DirectorySeparatorChar + Path.GetFileName(file);
|
||||
}
|
||||
|
||||
var ent = new ZipEntry(path)
|
||||
{
|
||||
//ent.DateTime = File.GetLastWriteTime(file);//设置文件最后修改时间
|
||||
DateTime = DateTime.Now,
|
||||
Size = buffer.Length,
|
||||
};
|
||||
|
||||
CRC.Reset();
|
||||
CRC.Update(buffer);
|
||||
|
||||
ent.Crc = CRC.Value;
|
||||
zipStream.PutNextEntry(ent);
|
||||
zipStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
var folders = Directory.GetDirectories(folderToZip);
|
||||
foreach (var folder in folders)
|
||||
{
|
||||
var folderName = folder.Substring(folder.LastIndexOf('\\') + 1);
|
||||
|
||||
if (parentFolderName.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
folderName = parentFolderName + "\\" + folder.Substring(folder.LastIndexOf('\\') + 1);
|
||||
}
|
||||
|
||||
if (!CompressDirectory(folder, zipStream, folderName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 压缩文件夹
|
||||
/// </summary>
|
||||
/// <param name="folderToZip">要压缩的文件夹路径</param>
|
||||
/// <param name="zipFile">压缩文件完整路径</param>
|
||||
/// <param name="password">密码</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static bool CompressDirectory(string folderToZip, string zipFile, string password = null)
|
||||
{
|
||||
if (folderToZip.EndsWithFast(Path.DirectorySeparatorChar.ToString()) || folderToZip.EndsWithFast("/"))
|
||||
{
|
||||
folderToZip = folderToZip.Substring(0, folderToZip.Length - 1);
|
||||
}
|
||||
|
||||
var zipStream = CompressDirectoryToZipStream(folderToZip, new FileStream(zipFile, FileMode.Create, FileAccess.Write, FileShare.Write), password);
|
||||
if (zipStream == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
zipStream.Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 压缩文件
|
||||
/// </summary>
|
||||
/// <param name="fileToZip">要压缩的文件全名</param>
|
||||
/// <param name="zipFile">压缩后的文件名</param>
|
||||
/// <param name="password">密码</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static bool CompressFile(string fileToZip, string zipFile, string password = null)
|
||||
{
|
||||
if (!File.Exists(fileToZip))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using (var readStream = File.OpenRead(fileToZip))
|
||||
{
|
||||
byte[] buffer = new byte[readStream.Length];
|
||||
var read = readStream.Read(buffer, 0, buffer.Length);
|
||||
using (var writeStream = File.Create(zipFile))
|
||||
{
|
||||
var entry = new ZipEntry(Path.GetFileName(fileToZip))
|
||||
{
|
||||
DateTime = DateTime.Now,
|
||||
Size = readStream.Length
|
||||
};
|
||||
CRC.Reset();
|
||||
CRC.Update(buffer);
|
||||
entry.Crc = CRC.Value;
|
||||
using (var zipStream = new ZipOutputStream(writeStream))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
zipStream.Password = password;
|
||||
}
|
||||
|
||||
zipStream.PutNextEntry(entry);
|
||||
zipStream.SetLevel(Deflater.BEST_COMPRESSION);
|
||||
zipStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GC.Collect(1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解压功能(解压压缩文件到指定目录)
|
||||
/// </summary>
|
||||
/// <param name="fileToUnZip">待解压的文件</param>
|
||||
/// <param name="zipFolder">指定解压目标目录</param>
|
||||
/// <param name="password">密码</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static bool DecompressFile(string fileToUnZip, string zipFolder, string password = null)
|
||||
{
|
||||
if (!System.IO.File.Exists(fileToUnZip))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(zipFolder))
|
||||
{
|
||||
Directory.CreateDirectory(zipFolder);
|
||||
}
|
||||
|
||||
if (!zipFolder.EndsWith("\\"))
|
||||
{
|
||||
zipFolder += "\\";
|
||||
}
|
||||
|
||||
using (var zipStream = new ZipInputStream(System.IO.File.OpenRead(fileToUnZip)))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
zipStream.Password = password;
|
||||
}
|
||||
|
||||
ZipEntry zipEntry = null;
|
||||
while ((zipEntry = zipStream.GetNextEntry()) != null)
|
||||
{
|
||||
if (zipEntry.IsDirectory)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(zipEntry.Name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string fileName = zipFolder + zipEntry.Name.Replace('/', '\\');
|
||||
var index = zipEntry.Name.LastIndexOf('/');
|
||||
if (index != -1)
|
||||
{
|
||||
string path = zipFolder + zipEntry.Name.Substring(0, index).Replace('/', '\\');
|
||||
System.IO.Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
var bytes = new byte[zipEntry.Size];
|
||||
var read = zipStream.Read(bytes, 0, bytes.Length);
|
||||
System.IO.File.WriteAllBytes(fileName, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
GC.Collect(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 压缩
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static byte[] Compress(byte[] content)
|
||||
{
|
||||
//return content;
|
||||
Deflater compressor = new Deflater();
|
||||
compressor.SetLevel(Deflater.BEST_COMPRESSION);
|
||||
|
||||
compressor.SetInput(content);
|
||||
compressor.Finish();
|
||||
|
||||
using (MemoryStream bos = new MemoryStream(content.Length))
|
||||
{
|
||||
var buf = new byte[4096];
|
||||
while (!compressor.IsFinished)
|
||||
{
|
||||
int n = compressor.Deflate(buf);
|
||||
bos.Write(buf, 0, n);
|
||||
}
|
||||
|
||||
return bos.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解压缩
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static byte[] Decompress(byte[] content)
|
||||
{
|
||||
return Decompress(content, 0, content.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解压缩
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public static byte[] Decompress(byte[] content, int offset, int count)
|
||||
{
|
||||
//return content;
|
||||
Inflater decompressor = new Inflater();
|
||||
decompressor.SetInput(content, offset, count);
|
||||
using (MemoryStream bos = new MemoryStream(content.Length))
|
||||
{
|
||||
var buf = new byte[4096];
|
||||
while (!decompressor.IsFinished)
|
||||
{
|
||||
int n = decompressor.Inflate(buf);
|
||||
bos.Write(buf, 0, n);
|
||||
}
|
||||
|
||||
return bos.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
240
Runtime/ABase/Utility/Utility.Compression.Zip.cs
Normal file
240
Runtime/ABase/Utility/Utility.Compression.Zip.cs
Normal file
@ -0,0 +1,240 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using ICSharpCode.SharpZipLib.Checksums;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
public static partial class Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Zip 压缩相关的实用函数。
|
||||
/// </summary>
|
||||
public static class Zip
|
||||
{
|
||||
private static readonly Crc32 s_Crc32 = new Crc32();
|
||||
|
||||
public static bool CompressDirectoryToStream(string folderToZip, Stream stream, string password = null)
|
||||
{
|
||||
return CompressDirectoryToZipStream(folderToZip, stream, password) != null;
|
||||
}
|
||||
|
||||
public static ZipOutputStream CompressDirectoryToZipStream(string folderToZip, Stream stream, string password = null)
|
||||
{
|
||||
if (!Directory.Exists(folderToZip) || stream == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ZipOutputStream zipStream = new ZipOutputStream(stream);
|
||||
zipStream.SetLevel(6);
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
zipStream.Password = password;
|
||||
}
|
||||
|
||||
if (!CompressDirectoryInternal(folderToZip, zipStream, string.Empty))
|
||||
{
|
||||
zipStream.Dispose();
|
||||
return null;
|
||||
}
|
||||
|
||||
zipStream.Finish();
|
||||
return zipStream;
|
||||
}
|
||||
|
||||
public static bool CompressDirectory(string folderToZip, string zipFile, string password = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(folderToZip) || string.IsNullOrEmpty(zipFile))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
folderToZip = folderToZip.TrimEnd(System.IO.Path.DirectorySeparatorChar, '/');
|
||||
using (FileStream writeStream = new FileStream(zipFile, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
{
|
||||
return CompressDirectoryToZipStream(folderToZip, writeStream, password) != null;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CompressFile(string fileToZip, string zipFile, string password = null)
|
||||
{
|
||||
if (!System.IO.File.Exists(fileToZip) || string.IsNullOrEmpty(zipFile))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] buffer = System.IO.File.ReadAllBytes(fileToZip);
|
||||
using (FileStream writeStream = System.IO.File.Create(zipFile))
|
||||
using (ZipOutputStream zipStream = new ZipOutputStream(writeStream))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
zipStream.Password = password;
|
||||
}
|
||||
|
||||
ZipEntry entry = new ZipEntry(System.IO.Path.GetFileName(fileToZip))
|
||||
{
|
||||
DateTime = DateTime.Now,
|
||||
Size = buffer.Length
|
||||
};
|
||||
|
||||
s_Crc32.Reset();
|
||||
s_Crc32.Update(buffer);
|
||||
entry.Crc = s_Crc32.Value;
|
||||
|
||||
zipStream.PutNextEntry(entry);
|
||||
zipStream.SetLevel(Deflater.BEST_COMPRESSION);
|
||||
zipStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool DecompressFile(string fileToUnzip, string zipFolder, string password = null)
|
||||
{
|
||||
if (!System.IO.File.Exists(fileToUnzip) || string.IsNullOrEmpty(zipFolder))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(zipFolder);
|
||||
|
||||
using (ZipInputStream zipStream = new ZipInputStream(System.IO.File.OpenRead(fileToUnzip)))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
zipStream.Password = password;
|
||||
}
|
||||
|
||||
ZipEntry zipEntry;
|
||||
while ((zipEntry = zipStream.GetNextEntry()) != null)
|
||||
{
|
||||
if (zipEntry.IsDirectory || string.IsNullOrEmpty(zipEntry.Name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string relativePath = zipEntry.Name.Replace('/', System.IO.Path.DirectorySeparatorChar);
|
||||
string outputPath = System.IO.Path.Combine(zipFolder, relativePath);
|
||||
string directory = System.IO.Path.GetDirectoryName(outputPath);
|
||||
if (!string.IsNullOrEmpty(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
using (FileStream fileStream = System.IO.File.Create(outputPath))
|
||||
{
|
||||
zipStream.CopyTo(fileStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static byte[] Compress(byte[] content)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Deflater compressor = new Deflater();
|
||||
compressor.SetLevel(Deflater.BEST_COMPRESSION);
|
||||
compressor.SetInput(content);
|
||||
compressor.Finish();
|
||||
|
||||
using (MemoryStream output = new MemoryStream(content.Length))
|
||||
{
|
||||
byte[] buffer = new byte[4096];
|
||||
while (!compressor.IsFinished)
|
||||
{
|
||||
int read = compressor.Deflate(buffer);
|
||||
output.Write(buffer, 0, read);
|
||||
}
|
||||
|
||||
return output.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] Decompress(byte[] content)
|
||||
{
|
||||
return content == null ? null : Decompress(content, 0, content.Length);
|
||||
}
|
||||
|
||||
public static byte[] Decompress(byte[] content, int offset, int count)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Inflater decompressor = new Inflater();
|
||||
decompressor.SetInput(content, offset, count);
|
||||
using (MemoryStream output = new MemoryStream(content.Length))
|
||||
{
|
||||
byte[] buffer = new byte[4096];
|
||||
while (!decompressor.IsFinished)
|
||||
{
|
||||
int read = decompressor.Inflate(buffer);
|
||||
output.Write(buffer, 0, read);
|
||||
}
|
||||
|
||||
return output.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CompressDirectoryInternal(string folderToZip, ZipOutputStream zipStream, string parentFolderName)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(parentFolderName))
|
||||
{
|
||||
ZipEntry entry = new ZipEntry(parentFolderName + "/");
|
||||
zipStream.PutNextEntry(entry);
|
||||
zipStream.Flush();
|
||||
}
|
||||
|
||||
string[] files = Directory.GetFiles(folderToZip);
|
||||
foreach (string file in files)
|
||||
{
|
||||
byte[] buffer = System.IO.File.ReadAllBytes(file);
|
||||
string path = System.IO.Path.GetFileName(file);
|
||||
if (!string.IsNullOrWhiteSpace(parentFolderName))
|
||||
{
|
||||
path = parentFolderName + System.IO.Path.DirectorySeparatorChar + System.IO.Path.GetFileName(file);
|
||||
}
|
||||
|
||||
ZipEntry entry = new ZipEntry(path)
|
||||
{
|
||||
DateTime = DateTime.Now,
|
||||
Size = buffer.Length
|
||||
};
|
||||
|
||||
s_Crc32.Reset();
|
||||
s_Crc32.Update(buffer);
|
||||
entry.Crc = s_Crc32.Value;
|
||||
zipStream.PutNextEntry(entry);
|
||||
zipStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
string[] folders = Directory.GetDirectories(folderToZip);
|
||||
foreach (string folder in folders)
|
||||
{
|
||||
string folderName = System.IO.Path.GetFileName(folder);
|
||||
if (!string.IsNullOrWhiteSpace(parentFolderName))
|
||||
{
|
||||
folderName = parentFolderName + System.IO.Path.DirectorySeparatorChar + folderName;
|
||||
}
|
||||
|
||||
if (!CompressDirectoryInternal(folder, zipStream, folderName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d572c5f6d619fd4cab0970b865300f7
|
||||
guid: 4d6547a46fce4ed7b0d0dce5f6f1a211
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using ICSharpCode.SharpZipLib.GZip;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
public static partial class Utility
|
||||
@ -10,6 +12,8 @@ namespace AlicizaX
|
||||
/// </summary>
|
||||
public static partial class Compression
|
||||
{
|
||||
private const int CachedBytesLength = 0x1000;
|
||||
|
||||
/// <summary>
|
||||
/// 压缩数据。
|
||||
/// </summary>
|
||||
@ -90,7 +94,14 @@ namespace AlicizaX
|
||||
|
||||
try
|
||||
{
|
||||
return CompressionUtility.Compress(bytes, offset, length, compressedStream);
|
||||
using (GZipOutputStream gzipOutputStream = new GZipOutputStream(compressedStream))
|
||||
{
|
||||
gzipOutputStream.Write(bytes, offset, length);
|
||||
gzipOutputStream.Finish();
|
||||
}
|
||||
|
||||
ProcessHeader(compressedStream);
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@ -143,7 +154,20 @@ namespace AlicizaX
|
||||
|
||||
try
|
||||
{
|
||||
return CompressionUtility.Compress(stream, compressedStream);
|
||||
byte[] cachedBytes = new byte[CachedBytesLength];
|
||||
using (GZipOutputStream gzipOutputStream = new GZipOutputStream(compressedStream))
|
||||
{
|
||||
int bytesRead;
|
||||
while ((bytesRead = stream.Read(cachedBytes, 0, CachedBytesLength)) > 0)
|
||||
{
|
||||
gzipOutputStream.Write(cachedBytes, 0, bytesRead);
|
||||
}
|
||||
|
||||
gzipOutputStream.Finish();
|
||||
}
|
||||
|
||||
ProcessHeader(compressedStream);
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@ -236,7 +260,18 @@ namespace AlicizaX
|
||||
|
||||
try
|
||||
{
|
||||
return CompressionUtility.Decompress(bytes, offset, length, decompressedStream);
|
||||
byte[] cachedBytes = new byte[CachedBytesLength];
|
||||
using (MemoryStream memoryStream = new MemoryStream(bytes, offset, length, false))
|
||||
using (GZipInputStream gzipInputStream = new GZipInputStream(memoryStream))
|
||||
{
|
||||
int bytesRead;
|
||||
while ((bytesRead = gzipInputStream.Read(cachedBytes, 0, CachedBytesLength)) > 0)
|
||||
{
|
||||
decompressedStream.Write(cachedBytes, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@ -289,7 +324,17 @@ namespace AlicizaX
|
||||
|
||||
try
|
||||
{
|
||||
return CompressionUtility.Decompress(stream, decompressedStream);
|
||||
byte[] cachedBytes = new byte[CachedBytesLength];
|
||||
using (GZipInputStream gzipInputStream = new GZipInputStream(stream))
|
||||
{
|
||||
int bytesRead;
|
||||
while ((bytesRead = gzipInputStream.Read(cachedBytes, 0, CachedBytesLength)) > 0)
|
||||
{
|
||||
decompressedStream.Write(cachedBytes, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@ -301,6 +346,22 @@ namespace AlicizaX
|
||||
throw new GameFrameworkException(Text.Format("Can not decompress with exception '{0}'.", exception), exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessHeader(Stream compressedStream)
|
||||
{
|
||||
if (compressedStream.Length < 8L)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
long current = compressedStream.Position;
|
||||
compressedStream.Position = 4L;
|
||||
compressedStream.WriteByte(25);
|
||||
compressedStream.WriteByte(134);
|
||||
compressedStream.WriteByte(2);
|
||||
compressedStream.WriteByte(32);
|
||||
compressedStream.Position = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ namespace AlicizaX
|
||||
|
||||
public static float PingPong(float min, float max, float speed = 1f)
|
||||
{
|
||||
return Mathf.PingPong(Time.time * speed, max - min) + min;
|
||||
return Mathf.PingPong(UnityEngine.Time.time * speed, max - min) + min;
|
||||
}
|
||||
|
||||
public static int Wrap(int value, int min, int max)
|
||||
|
||||
93
Runtime/ABase/Utility/Utility.Position.cs
Normal file
93
Runtime/ABase/Utility/Utility.Position.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
public static partial class Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// 位置与几何相关的实用函数。
|
||||
/// </summary>
|
||||
public static class Position
|
||||
{
|
||||
public static Vector3 RayCastV2ToV3(Vector2 position)
|
||||
{
|
||||
return position.ToVector3();
|
||||
}
|
||||
|
||||
public static Vector3 RayCastXYToV3(float x, float y)
|
||||
{
|
||||
return new Vector3(x, 0f, y);
|
||||
}
|
||||
|
||||
public static Vector3 RayCastV3ToV3(Vector3 position)
|
||||
{
|
||||
return position.FlattenY();
|
||||
}
|
||||
|
||||
public static Quaternion AngleToQuaternion(int angle)
|
||||
{
|
||||
return GetAngleToQuaternion(angle);
|
||||
}
|
||||
|
||||
public static Quaternion GetAngleToQuaternion(float angle)
|
||||
{
|
||||
return Quaternion.AngleAxis(-angle, Vector3.up) * Quaternion.AngleAxis(90f, Vector3.up);
|
||||
}
|
||||
|
||||
public static Quaternion GetVector3ToQuaternion(Vector3 source, Vector3 direction)
|
||||
{
|
||||
if (source == direction)
|
||||
{
|
||||
return Quaternion.identity;
|
||||
}
|
||||
|
||||
return Quaternion.LookRotation((direction - source).normalized, Vector3.up);
|
||||
}
|
||||
|
||||
public static float Distance2D(Vector3 a, Vector3 b)
|
||||
{
|
||||
return Vector2.Distance(a.IgnoreYAxis(), b.IgnoreYAxis());
|
||||
}
|
||||
|
||||
public static float Vector3ToAngle360(Vector3 from, Vector3 to)
|
||||
{
|
||||
float angle = Vector3.Angle(from, to);
|
||||
Vector3 cross = Vector3.Cross(from, to);
|
||||
return cross.y > 0f ? angle : 360f - angle;
|
||||
}
|
||||
|
||||
public static float DistanceOfPointToVector(Vector3 startPoint, Vector3 endPoint, Vector3 point)
|
||||
{
|
||||
Vector2 start = startPoint.IgnoreYAxis();
|
||||
Vector2 end = endPoint.IgnoreYAxis();
|
||||
float a = end.y - start.y;
|
||||
float b = start.x - end.x;
|
||||
float c = end.x * start.y - start.x * end.y;
|
||||
float denominator = Mathf.Sqrt(a * a + b * b);
|
||||
Vector2 point2 = point.IgnoreYAxis();
|
||||
return Mathf.Abs((a * point2.x + b * point2.y + c) / denominator);
|
||||
}
|
||||
|
||||
public static bool RayCastSphere(Ray ray, Vector3 center, float radius, out float distance)
|
||||
{
|
||||
distance = 0f;
|
||||
Vector3 originToCenter = center - ray.origin;
|
||||
float perpendicularDistance = Vector3.Cross(originToCenter, ray.direction).magnitude / ray.direction.magnitude;
|
||||
if (perpendicularDistance >= radius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float centerDistance = PythagoreanTheorem(Vector3.Distance(center, ray.origin), perpendicularDistance);
|
||||
float radiusDistance = PythagoreanTheorem(radius, perpendicularDistance);
|
||||
distance = centerDistance - radiusDistance;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static float PythagoreanTheorem(float x, float y)
|
||||
{
|
||||
return Mathf.Sqrt(x * x + y * y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75d07d90984a5dc4698c98d2fe3809bf
|
||||
timeCreated: 1474948216
|
||||
licenseType: Pro
|
||||
guid: c82a27c2ab4545f687eac25a4d731f16
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
118
Runtime/ABase/Utility/Utility.Time.cs
Normal file
118
Runtime/ABase/Utility/Utility.Time.cs
Normal file
@ -0,0 +1,118 @@
|
||||
using System;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
public static partial class Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// 时间相关的实用函数。
|
||||
/// </summary>
|
||||
public static class Time
|
||||
{
|
||||
private static readonly DateTime EpochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
private static long s_DifferenceTime;
|
||||
private static bool s_IsSecondLevel = true;
|
||||
|
||||
public const long TicksPerMicrosecond = 1;
|
||||
public const long TicksPer = 10 * TicksPerMicrosecond;
|
||||
public const long TicksMillisecondUnit = TicksPer * 1000;
|
||||
public const long TicksSecondUnit = TicksMillisecondUnit * 1000;
|
||||
|
||||
public static void SetDifferenceTime(long timeSpan)
|
||||
{
|
||||
s_IsSecondLevel = timeSpan <= 1000000000000;
|
||||
s_DifferenceTime = s_IsSecondLevel ? timeSpan - ClientNowSeconds() : timeSpan - ClientNowMillisecond();
|
||||
}
|
||||
|
||||
public static long ClientNowMillisecond()
|
||||
{
|
||||
return (DateTime.UtcNow.Ticks - EpochTime.Ticks) / TicksMillisecondUnit;
|
||||
}
|
||||
|
||||
public static long ServerToday()
|
||||
{
|
||||
return s_IsSecondLevel ? s_DifferenceTime + ClientToday() : (s_DifferenceTime + ClientTodayMillisecond()) / 1000;
|
||||
}
|
||||
|
||||
public static long ClientTodayMillisecond()
|
||||
{
|
||||
return (DateTime.Now.Date.ToUniversalTime().Ticks - EpochTime.Ticks) / TicksMillisecondUnit;
|
||||
}
|
||||
|
||||
public static long ServerNow()
|
||||
{
|
||||
return s_IsSecondLevel ? s_DifferenceTime + ClientNowSeconds() : (s_DifferenceTime + ClientNowMillisecond()) / 1000;
|
||||
}
|
||||
|
||||
public static TimeSpan FromSeconds(int seconds)
|
||||
{
|
||||
return TimeSpan.FromSeconds(seconds);
|
||||
}
|
||||
|
||||
public static long ClientToday()
|
||||
{
|
||||
return (DateTime.Now.Date.ToUniversalTime().Ticks - EpochTime.Ticks) / TicksSecondUnit;
|
||||
}
|
||||
|
||||
public static long ClientNow()
|
||||
{
|
||||
return ClientNowMillisecond();
|
||||
}
|
||||
|
||||
public static long ClientNowSeconds()
|
||||
{
|
||||
return (DateTime.UtcNow.Ticks - EpochTime.Ticks) / TicksSecondUnit;
|
||||
}
|
||||
|
||||
public static long Now()
|
||||
{
|
||||
return ClientNow();
|
||||
}
|
||||
|
||||
public static long UnixTimeSeconds()
|
||||
{
|
||||
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
}
|
||||
|
||||
public static long UnixTimeMilliseconds()
|
||||
{
|
||||
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
}
|
||||
|
||||
public static bool IsUnixSameDay(long timestamp1, long timestamp2)
|
||||
{
|
||||
return IsSameDay(UtcToUtcDateTime(timestamp1), UtcToUtcDateTime(timestamp2));
|
||||
}
|
||||
|
||||
public static bool IsLocalSameDay(long timestamp1, long timestamp2)
|
||||
{
|
||||
return IsSameDay(UtcToLocalDateTime(timestamp1), UtcToLocalDateTime(timestamp2));
|
||||
}
|
||||
|
||||
public static DateTime UtcToUtcDateTime(long utcTimestamp)
|
||||
{
|
||||
return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).UtcDateTime;
|
||||
}
|
||||
|
||||
public static DateTime UtcToLocalDateTime(long utcTimestamp)
|
||||
{
|
||||
return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).LocalDateTime;
|
||||
}
|
||||
|
||||
public static bool IsSameDay(DateTime time1, DateTime time2)
|
||||
{
|
||||
return time1.Date == time2.Date;
|
||||
}
|
||||
|
||||
public static long LocalTimeToUnixTimeSeconds(DateTime time)
|
||||
{
|
||||
return new DateTimeOffset(time.ToUniversalTime()).ToUnixTimeSeconds();
|
||||
}
|
||||
|
||||
public static long LocalTimeToUnixTimeMilliseconds(DateTime time)
|
||||
{
|
||||
return new DateTimeOffset(time.ToUniversalTime()).ToUnixTimeMilliseconds();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/ABase/Utility/Utility.Time.cs.meta
Normal file
11
Runtime/ABase/Utility/Utility.Time.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c88fefb639f4d1dac58f77d9cbba2af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -44,7 +44,7 @@ namespace AlicizaX
|
||||
source.clip = clip;
|
||||
source.volume = volume;
|
||||
source.Play();
|
||||
Object.Destroy(gameObject, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
|
||||
Object.Destroy(gameObject, clip.length * ((UnityEngine.Time.timeScale < 0.01f) ? 0.01f : UnityEngine.Time.timeScale));
|
||||
return source;
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ namespace AlicizaX
|
||||
source.clip = clip;
|
||||
source.volume = volume;
|
||||
source.Play();
|
||||
Object.Destroy(gameObject, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
|
||||
Object.Destroy(gameObject, clip.length * ((UnityEngine.Time.timeScale < 0.01f) ? 0.01f : UnityEngine.Time.timeScale));
|
||||
return source;
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ namespace AlicizaX
|
||||
source.volume = volume;
|
||||
source.maxDistance = maxDistance;
|
||||
source.Play();
|
||||
Object.Destroy(gameObject, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
|
||||
Object.Destroy(gameObject, clip.length * ((UnityEngine.Time.timeScale < 0.01f) ? 0.01f : UnityEngine.Time.timeScale));
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user