mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-30 05:15:59 +02:00
Merge branch 'master' into bufstream-fixes
This commit is contained in:
commit
92738418eb
243 changed files with 19052 additions and 2933 deletions
|
@ -7,7 +7,7 @@ StartupObject = "BeefBuild.Program"
|
||||||
|
|
||||||
[Platform.Windows]
|
[Platform.Windows]
|
||||||
Description = "BeefBuild"
|
Description = "BeefBuild"
|
||||||
FileVersion = "0.43.1"
|
FileVersion = "0.43.2"
|
||||||
|
|
||||||
[Configs.Debug.Win32]
|
[Configs.Debug.Win32]
|
||||||
TargetName = ""
|
TargetName = ""
|
||||||
|
|
|
@ -15,6 +15,9 @@ CLibType = "Static"
|
||||||
BeefLibType = "Static"
|
BeefLibType = "Static"
|
||||||
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64_d.dll\")", "CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64_d.pdb\")"]
|
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64_d.dll\")", "CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64_d.pdb\")"]
|
||||||
|
|
||||||
|
[Configs.Debug.Linux64]
|
||||||
|
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/libBeefySysLib_d.so\")"]
|
||||||
|
|
||||||
[Configs.Release.Win32]
|
[Configs.Release.Win32]
|
||||||
OtherLinkFlags = ""
|
OtherLinkFlags = ""
|
||||||
PreprocessorMacros = ["RELEASE", "BF32"]
|
PreprocessorMacros = ["RELEASE", "BF32"]
|
||||||
|
@ -23,6 +26,9 @@ PreprocessorMacros = ["RELEASE", "BF32"]
|
||||||
OtherLinkFlags = "$(LinkFlags) $(ProjectDir)/dist/BeefySysLib64.lib"
|
OtherLinkFlags = "$(LinkFlags) $(ProjectDir)/dist/BeefySysLib64.lib"
|
||||||
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.dll\")", "CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.pdb\")"]
|
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.dll\")", "CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.pdb\")"]
|
||||||
|
|
||||||
|
[Configs.Release.Linux64]
|
||||||
|
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/libBeefySysLib.so\")"]
|
||||||
|
|
||||||
[Configs.Paranoid.Win32]
|
[Configs.Paranoid.Win32]
|
||||||
CLibType = "Static"
|
CLibType = "Static"
|
||||||
BeefLibType = "Static"
|
BeefLibType = "Static"
|
||||||
|
@ -38,3 +44,15 @@ BeefLibType = "Static"
|
||||||
[Configs.Test.Win64]
|
[Configs.Test.Win64]
|
||||||
CLibType = "Static"
|
CLibType = "Static"
|
||||||
BeefLibType = "Static"
|
BeefLibType = "Static"
|
||||||
|
|
||||||
|
[Configs.DebugOpt.Win32]
|
||||||
|
OtherLinkFlags = "$(LinkFlags) \"$(ProjectDir)/dist/BeefySysLib32_d.lib\""
|
||||||
|
BeefLibType = "Static"
|
||||||
|
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib32_d.dll\")", "CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib32_d.pdb\")"]
|
||||||
|
PreprocessorMacros = ["DEBUG", "BF32"]
|
||||||
|
|
||||||
|
[Configs.DebugOpt.Win64]
|
||||||
|
OtherLinkFlags = "$(LinkFlags) \"$(ProjectDir)/dist/BeefySysLib64.lib\""
|
||||||
|
CLibType = "Static"
|
||||||
|
BeefLibType = "Static"
|
||||||
|
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.dll\")", "CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.pdb\")"]
|
||||||
|
|
|
@ -727,7 +727,7 @@ namespace Beefy
|
||||||
0.10f, 0.00f, 1.05f, 0,
|
0.10f, 0.00f, 1.05f, 0,
|
||||||
0, 0, 0, 1);*/
|
0, 0, 0, 1);*/
|
||||||
|
|
||||||
mGraphics.SetShaderConstantData(0, &mColorMatrix.ValueRef, mColorMatrixDataDef);
|
mGraphics.SetVertexShaderConstantData(0, &mColorMatrix.ValueRef, mColorMatrixDataDef);
|
||||||
}
|
}
|
||||||
window.Draw(mGraphics);
|
window.Draw(mGraphics);
|
||||||
window.PostDraw(mGraphics);
|
window.PostDraw(mGraphics);
|
||||||
|
|
|
@ -295,11 +295,13 @@ namespace Beefy
|
||||||
|
|
||||||
public static Result<void> WriteTextFile(StringView path, StringView text)
|
public static Result<void> WriteTextFile(StringView path, StringView text)
|
||||||
{
|
{
|
||||||
var stream = scope FileStream();
|
var stream = scope UnbufferedFileStream();
|
||||||
if (stream.Create(path) case .Err)
|
if (stream.Open(path, .OpenOrCreate, .Write) case .Err)
|
||||||
{
|
|
||||||
return .Err;
|
return .Err;
|
||||||
}
|
|
||||||
|
if (stream.SetLength(text.Length) case .Err)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
if (stream.WriteStrUnsized(text) case .Err)
|
if (stream.WriteStrUnsized(text) case .Err)
|
||||||
return .Err;
|
return .Err;
|
||||||
|
|
||||||
|
|
14
BeefLibs/Beefy2D/src/geom/BoundingBox.bf
Normal file
14
BeefLibs/Beefy2D/src/geom/BoundingBox.bf
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// This file contains portions of code from the FNA project (github.com/FNA-XNA/FNA),
|
||||||
|
// released under the Microsoft Public License
|
||||||
|
|
||||||
|
namespace Beefy.geom
|
||||||
|
{
|
||||||
|
class BoundingBox
|
||||||
|
{
|
||||||
|
public Vector3 Min;
|
||||||
|
public Vector3 Max;
|
||||||
|
public const int CornerCount = 8;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,19 @@ namespace Beefy.geom
|
||||||
this.m33 = m33;
|
this.m33 = m33;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Matrix4 CreateFromColumnMajor(
|
||||||
|
float m00, float m10, float m20, float m30,
|
||||||
|
float m01, float m11, float m21, float m31,
|
||||||
|
float m02, float m12, float m22, float m32,
|
||||||
|
float m03, float m13, float m23, float m33)
|
||||||
|
{
|
||||||
|
return .(
|
||||||
|
m00, m01, m02, m03,
|
||||||
|
m10, m11, m12, m13,
|
||||||
|
m20, m21, m22, m23,
|
||||||
|
m30, m31, m32, m33);
|
||||||
|
}
|
||||||
|
|
||||||
public static Matrix4 CreatePerspective(float width, float height, float nearPlaneDistance, float farPlaneDistance)
|
public static Matrix4 CreatePerspective(float width, float height, float nearPlaneDistance, float farPlaneDistance)
|
||||||
{
|
{
|
||||||
Matrix4 matrix;
|
Matrix4 matrix;
|
||||||
|
@ -190,25 +203,23 @@ namespace Beefy.geom
|
||||||
public static Matrix4 Multiply(Matrix4 m1, Matrix4 m2)
|
public static Matrix4 Multiply(Matrix4 m1, Matrix4 m2)
|
||||||
{
|
{
|
||||||
Matrix4 r;
|
Matrix4 r;
|
||||||
r.m00 = m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20 + m1.m03 * m2.m30;
|
|
||||||
r.m01 = m1.m00 * m2.m01 + m1.m01 * m2.m11 + m1.m02 * m2.m21 + m1.m03 * m2.m31;
|
|
||||||
r.m02 = m1.m00 * m2.m02 + m1.m01 * m2.m12 + m1.m02 * m2.m22 + m1.m03 * m2.m32;
|
|
||||||
r.m03 = m1.m00 * m2.m03 + m1.m01 * m2.m13 + m1.m02 * m2.m23 + m1.m03 * m2.m33;
|
|
||||||
|
|
||||||
r.m10 = m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20 + m1.m13 * m2.m30;
|
r.m00 = (((m1.m00 * m2.m00) + (m1.m10 * m2.m01)) + (m1.m20 * m2.m02)) + (m1.m30 * m2.m03);
|
||||||
r.m11 = m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31;
|
r.m10 = (((m1.m00 * m2.m10) + (m1.m10 * m2.m11)) + (m1.m20 * m2.m12)) + (m1.m30 * m2.m13);
|
||||||
r.m12 = m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32;
|
r.m20 = (((m1.m00 * m2.m20) + (m1.m10 * m2.m21)) + (m1.m20 * m2.m22)) + (m1.m30 * m2.m23);
|
||||||
r.m13 = m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33;
|
r.m30 = (((m1.m00 * m2.m30) + (m1.m10 * m2.m31)) + (m1.m20 * m2.m32)) + (m1.m30 * m2.m33);
|
||||||
|
r.m01 = (((m1.m01 * m2.m00) + (m1.m11 * m2.m01)) + (m1.m21 * m2.m02)) + (m1.m31 * m2.m03);
|
||||||
r.m20 = m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20 + m1.m23 * m2.m30;
|
r.m11 = (((m1.m01 * m2.m10) + (m1.m11 * m2.m11)) + (m1.m21 * m2.m12)) + (m1.m31 * m2.m13);
|
||||||
r.m21 = m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31;
|
r.m21 = (((m1.m01 * m2.m20) + (m1.m11 * m2.m21)) + (m1.m21 * m2.m22)) + (m1.m31 * m2.m23);
|
||||||
r.m22 = m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32;
|
r.m31 = (((m1.m01 * m2.m30) + (m1.m11 * m2.m31)) + (m1.m21 * m2.m32)) + (m1.m31 * m2.m33);
|
||||||
r.m23 = m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33;
|
r.m02 = (((m1.m02 * m2.m00) + (m1.m12 * m2.m01)) + (m1.m22 * m2.m02)) + (m1.m32 * m2.m03);
|
||||||
|
r.m12 = (((m1.m02 * m2.m10) + (m1.m12 * m2.m11)) + (m1.m22 * m2.m12)) + (m1.m32 * m2.m13);
|
||||||
r.m30 = m1.m30 * m2.m00 + m1.m31 * m2.m10 + m1.m32 * m2.m20 + m1.m33 * m2.m30;
|
r.m22 = (((m1.m02 * m2.m20) + (m1.m12 * m2.m21)) + (m1.m22 * m2.m22)) + (m1.m32 * m2.m23);
|
||||||
r.m31 = m1.m30 * m2.m01 + m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31;
|
r.m32 = (((m1.m02 * m2.m30) + (m1.m12 * m2.m31)) + (m1.m22 * m2.m32)) + (m1.m32 * m2.m33);
|
||||||
r.m32 = m1.m30 * m2.m02 + m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32;
|
r.m03 = (((m1.m03 * m2.m00) + (m1.m13 * m2.m01)) + (m1.m23 * m2.m02)) + (m1.m33 * m2.m03);
|
||||||
r.m33 = m1.m30 * m2.m03 + m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33;
|
r.m13 = (((m1.m03 * m2.m10) + (m1.m13 * m2.m11)) + (m1.m23 * m2.m12)) + (m1.m33 * m2.m13);
|
||||||
|
r.m23 = (((m1.m03 * m2.m20) + (m1.m13 * m2.m21)) + (m1.m23 * m2.m22)) + (m1.m33 * m2.m23);
|
||||||
|
r.m33 = (((m1.m03 * m2.m30) + (m1.m13 * m2.m31)) + (m1.m23 * m2.m32)) + (m1.m33 * m2.m33);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -489,5 +500,730 @@ namespace Beefy.geom
|
||||||
r20, r21, r22, r23,
|
r20, r21, r22, r23,
|
||||||
0, 0, 0, 1);
|
0, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Invert(Matrix4 matrix, out Matrix4 result)
|
||||||
|
{
|
||||||
|
float num1 = matrix.m00;
|
||||||
|
float num2 = matrix.m10;
|
||||||
|
float num3 = matrix.m20;
|
||||||
|
float num4 = matrix.m30;
|
||||||
|
float num5 = matrix.m01;
|
||||||
|
float num6 = matrix.m11;
|
||||||
|
float num7 = matrix.m21;
|
||||||
|
float num8 = matrix.m31;
|
||||||
|
float num9 = matrix.m02;
|
||||||
|
float num10 = matrix.m12;
|
||||||
|
float num11 = matrix.m22;
|
||||||
|
float num12 = matrix.m32;
|
||||||
|
float num13 = matrix.m03;
|
||||||
|
float num14 = matrix.m13;
|
||||||
|
float num15 = matrix.m23;
|
||||||
|
float num16 = matrix.m33;
|
||||||
|
float num17 = (float) ((double) num11 * (double) num16 - (double) num12 * (double) num15);
|
||||||
|
float num18 = (float) ((double) num10 * (double) num16 - (double) num12 * (double) num14);
|
||||||
|
float num19 = (float) ((double) num10 * (double) num15 - (double) num11 * (double) num14);
|
||||||
|
float num20 = (float) ((double) num9 * (double) num16 - (double) num12 * (double) num13);
|
||||||
|
float num21 = (float) ((double) num9 * (double) num15 - (double) num11 * (double) num13);
|
||||||
|
float num22 = (float) ((double) num9 * (double) num14 - (double) num10 * (double) num13);
|
||||||
|
float num23 = (float) ((double) num6 * (double) num17 - (double) num7 * (double) num18 + (double) num8 * (double) num19);
|
||||||
|
float num24 = (float) -((double) num5 * (double) num17 - (double) num7 * (double) num20 + (double) num8 * (double) num21);
|
||||||
|
float num25 = (float) ((double) num5 * (double) num18 - (double) num6 * (double) num20 + (double) num8 * (double) num22);
|
||||||
|
float num26 = (float) -((double) num5 * (double) num19 - (double) num6 * (double) num21 + (double) num7 * (double) num22);
|
||||||
|
float num27 = (float) (1.0 / ((double) num1 * (double) num23 + (double) num2 * (double) num24 + (double) num3 * (double) num25 + (double) num4 * (double) num26));
|
||||||
|
|
||||||
|
result.m00 = num23 * num27;
|
||||||
|
result.m01 = num24 * num27;
|
||||||
|
result.m02 = num25 * num27;
|
||||||
|
result.m03 = num26 * num27;
|
||||||
|
result.m10 = (float)(-((double) num2 * (double) num17 - (double) num3 * (double) num18 + (double) num4 * (double) num19) * num27);
|
||||||
|
result.m11 = (float) ((double) num1 * (double) num17 - (double) num3 * (double) num20 + (double) num4 * (double) num21) * num27;
|
||||||
|
result.m12 = (float)(-((double) num1 * (double) num18 - (double) num2 * (double) num20 + (double) num4 * (double) num22) * num27);
|
||||||
|
result.m13 = (float) ((double) num1 * (double) num19 - (double) num2 * (double) num21 + (double) num3 * (double) num22) * num27;
|
||||||
|
float num28 = (float) ((double) num7 * (double) num16 - (double) num8 * (double) num15);
|
||||||
|
float num29 = (float) ((double) num6 * (double) num16 - (double) num8 * (double) num14);
|
||||||
|
float num30 = (float) ((double) num6 * (double) num15 - (double) num7 * (double) num14);
|
||||||
|
float num31 = (float) ((double) num5 * (double) num16 - (double) num8 * (double) num13);
|
||||||
|
float num32 = (float) ((double) num5 * (double) num15 - (double) num7 * (double) num13);
|
||||||
|
float num33 = (float) ((double) num5 * (double) num14 - (double) num6 * (double) num13);
|
||||||
|
result.m20 = (float) ((double) num2 * (double) num28 - (double) num3 * (double) num29 + (double) num4 * (double) num30) * num27;
|
||||||
|
result.m21 = (float)(-((double) num1 * (double) num28 - (double) num3 * (double) num31 + (double) num4 * (double) num32) * num27);
|
||||||
|
result.m22 = (float) ((double) num1 * (double) num29 - (double) num2 * (double) num31 + (double) num4 * (double) num33) * num27;
|
||||||
|
result.m23 = (float)(-((double) num1 * (double) num30 - (double) num2 * (double) num32 + (double) num3 * (double) num33) * num27);
|
||||||
|
float num34 = (float) ((double) num7 * (double) num12 - (double) num8 * (double) num11);
|
||||||
|
float num35 = (float) ((double) num6 * (double) num12 - (double) num8 * (double) num10);
|
||||||
|
float num36 = (float) ((double) num6 * (double) num11 - (double) num7 * (double) num10);
|
||||||
|
float num37 = (float) ((double) num5 * (double) num12 - (double) num8 * (double) num9);
|
||||||
|
float num38 = (float) ((double) num5 * (double) num11 - (double) num7 * (double) num9);
|
||||||
|
float num39 = (float) ((double) num5 * (double) num10 - (double) num6 * (double) num9);
|
||||||
|
result.m30 = (float)(-((double) num2 * (double) num34 - (double) num3 * (double) num35 + (double) num4 * (double) num36) * num27);
|
||||||
|
result.m31 = (float) ((double) num1 * (double) num34 - (double) num3 * (double) num37 + (double) num4 * (double) num38) * num27;
|
||||||
|
result.m32 = (float)(-((double) num1 * (double) num35 - (double) num2 * (double) num37 + (double) num4 * (double) num39) * num27);
|
||||||
|
result.m33 = (float) ((double) num1 * (double) num36 - (double) num2 * (double) num38 + (double) num3 * (double) num39) * num27;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
// Use Laplace expansion theorem to calculate the inverse of a 4x4 matrix
|
||||||
|
//
|
||||||
|
// 1. Calculate the 2x2 determinants needed the 4x4 determinant based on the 2x2 determinants
|
||||||
|
// 3. Create the adjugate matrix, which satisfies: A * adj(A) = det(A) * I
|
||||||
|
// 4. Divide adjugate matrix with the determinant to find the inverse
|
||||||
|
|
||||||
|
float det1, det2, det3, det4, det5, det6, det7, det8, det9, det10, det11, det12;
|
||||||
|
float detMatrix;
|
||||||
|
FindDeterminants(ref matrix, out detMatrix, out det1, out det2, out det3, out det4, out det5, out det6,
|
||||||
|
out det7, out det8, out det9, out det10, out det11, out det12);
|
||||||
|
|
||||||
|
float invDetMatrix = 1f / detMatrix;
|
||||||
|
|
||||||
|
Matrix ret; // Allow for matrix and result to point to the same structure
|
||||||
|
|
||||||
|
ret.M11 = (matrix.M22*det12 - matrix.M23*det11 + matrix.M24*det10) * invDetMatrix;
|
||||||
|
ret.M12 = (-matrix.M12*det12 + matrix.M13*det11 - matrix.M14*det10) * invDetMatrix;
|
||||||
|
ret.M13 = (matrix.M42*det6 - matrix.M43*det5 + matrix.M44*det4) * invDetMatrix;
|
||||||
|
ret.M14 = (-matrix.M32*det6 + matrix.M33*det5 - matrix.M34*det4) * invDetMatrix;
|
||||||
|
ret.M21 = (-matrix.M21*det12 + matrix.M23*det9 - matrix.M24*det8) * invDetMatrix;
|
||||||
|
ret.M22 = (matrix.M11*det12 - matrix.M13*det9 + matrix.M14*det8) * invDetMatrix;
|
||||||
|
ret.M23 = (-matrix.M41*det6 + matrix.M43*det3 - matrix.M44*det2) * invDetMatrix;
|
||||||
|
ret.M24 = (matrix.M31*det6 - matrix.M33*det3 + matrix.M34*det2) * invDetMatrix;
|
||||||
|
ret.M31 = (matrix.M21*det11 - matrix.M22*det9 + matrix.M24*det7) * invDetMatrix;
|
||||||
|
ret.M32 = (-matrix.M11*det11 + matrix.M12*det9 - matrix.M14*det7) * invDetMatrix;
|
||||||
|
ret.M33 = (matrix.M41*det5 - matrix.M42*det3 + matrix.M44*det1) * invDetMatrix;
|
||||||
|
ret.M34 = (-matrix.M31*det5 + matrix.M32*det3 - matrix.M34*det1) * invDetMatrix;
|
||||||
|
ret.M41 = (-matrix.M21*det10 + matrix.M22*det8 - matrix.M23*det7) * invDetMatrix;
|
||||||
|
ret.M42 = (matrix.M11*det10 - matrix.M12*det8 + matrix.M13*det7) * invDetMatrix;
|
||||||
|
ret.M43 = (-matrix.M41*det4 + matrix.M42*det2 - matrix.M43*det1) * invDetMatrix;
|
||||||
|
ret.M44 = (matrix.M31*det4 - matrix.M32*det2 + matrix.M33*det1) * invDetMatrix;
|
||||||
|
|
||||||
|
result = ret;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix4 Invert(Matrix4 matrix)
|
||||||
|
{
|
||||||
|
Invert(matrix, var outMatrix);
|
||||||
|
return outMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decomposes this matrix to translation, rotation and scale elements. Returns <c>true</c> if matrix can be decomposed; <c>false</c> otherwise.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scale">Scale vector as an output parameter.
|
||||||
|
/// <param name="rotation">Rotation quaternion as an output parameter.
|
||||||
|
/// <param name="translation">Translation vector as an output parameter.
|
||||||
|
/// <returns><c>true</c> if matrix can be decomposed; <c>false</c> otherwise.</returns>
|
||||||
|
public bool Decompose(
|
||||||
|
out Vector3 scale,
|
||||||
|
out Quaternion rotation,
|
||||||
|
out Vector3 translation
|
||||||
|
) {
|
||||||
|
translation.mX = m03;
|
||||||
|
translation.mY = m13;
|
||||||
|
translation.mZ = m23;
|
||||||
|
|
||||||
|
float xs = (Math.Sign(m00 * m10 * m20 * m30) < 0) ? -1 : 1;
|
||||||
|
float ys = (Math.Sign(m01 * m11 * m21 * m31) < 0) ? -1 : 1;
|
||||||
|
float zs = (Math.Sign(m02 * m12 * m22 * m32) < 0) ? -1 : 1;
|
||||||
|
|
||||||
|
scale.mX = xs * (float) Math.Sqrt(m00 * m00 + m10 * m10 + m20 * m20);
|
||||||
|
scale.mY = ys * (float) Math.Sqrt(m01 * m01 + m11 * m11 + m21 * m21);
|
||||||
|
scale.mZ = zs * (float) Math.Sqrt(m02 * m02 + m12 * m12 + m22 * m22);
|
||||||
|
|
||||||
|
if (Math.WithinEpsilon(scale.mX, 0.0f) ||
|
||||||
|
Math.WithinEpsilon(scale.mY, 0.0f) ||
|
||||||
|
Math.WithinEpsilon(scale.mZ, 0.0f) )
|
||||||
|
{
|
||||||
|
rotation = Quaternion.Identity;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix4 m1 = Matrix4.CreateFromColumnMajor(
|
||||||
|
m00 / scale.mX, m10 / scale.mX, m20 / scale.mX, 0,
|
||||||
|
m01 / scale.mY, m11 / scale.mY, m21 / scale.mY, 0,
|
||||||
|
m02 / scale.mZ, m12 / scale.mZ, m22 / scale.mZ, 0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
);
|
||||||
|
|
||||||
|
rotation = Quaternion.CreateFromRotationMatrix(m1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a determinant of this matrix.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Determinant of this matrix</returns>
|
||||||
|
/// <remarks>See more about determinant here - http://en.wikipedia.org/wiki/Determinant.
|
||||||
|
/// </remarks>
|
||||||
|
public float Determinant()
|
||||||
|
{
|
||||||
|
float num18 = (m22 * m33) - (m32 * m23);
|
||||||
|
float num17 = (m12 * m33) - (m32 * m13);
|
||||||
|
float num16 = (m12 * m23) - (m22 * m13);
|
||||||
|
float num15 = (m02 * m33) - (m32 * m03);
|
||||||
|
float num14 = (m02 * m23) - (m22 * m03);
|
||||||
|
float num13 = (m02 * m13) - (m12 * m03);
|
||||||
|
return (
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(m00 * (((m11 * num18) - (m21 * num17)) + (m31 * num16))) -
|
||||||
|
(m10 * (((m01 * num18) - (m21 * num15)) + (m31 * num14)))
|
||||||
|
) + (m20 * (((m01 * num17) - (m11 * num15)) + (m31 * num13)))
|
||||||
|
) - (m30 * (((m01 * num16) - (m11 * num14)) + (m21 * num13)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new matrix for spherical billboarding that rotates around specified object position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="objectPosition">Position of billboard object. It will rotate around that vector.
|
||||||
|
/// <param name="cameraPosition">The camera position.
|
||||||
|
/// <param name="cameraUpVector">The camera up vector.
|
||||||
|
/// <param name="cameraForwardVector">Optional camera forward vector.
|
||||||
|
/// <returns>The matrix for spherical billboarding.</returns>
|
||||||
|
public static Matrix4 CreateBillboard(
|
||||||
|
Vector3 objectPosition,
|
||||||
|
Vector3 cameraPosition,
|
||||||
|
Vector3 cameraUpVector,
|
||||||
|
Nullable<Vector3> cameraForwardVector
|
||||||
|
) {
|
||||||
|
Matrix4 result;
|
||||||
|
|
||||||
|
// Delegate to the other overload of the function to do the work
|
||||||
|
CreateBillboard(
|
||||||
|
objectPosition,
|
||||||
|
cameraPosition,
|
||||||
|
cameraUpVector,
|
||||||
|
cameraForwardVector,
|
||||||
|
out result
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new matrix for spherical billboarding that rotates around specified object position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="objectPosition">Position of billboard object. It will rotate around that vector.
|
||||||
|
/// <param name="cameraPosition">The camera position.
|
||||||
|
/// <param name="cameraUpVector">The camera up vector.
|
||||||
|
/// <param name="cameraForwardVector">Optional camera forward vector.
|
||||||
|
/// <param name="result">The matrix for spherical billboarding as an output parameter.
|
||||||
|
public static void CreateBillboard(
|
||||||
|
Vector3 objectPosition,
|
||||||
|
Vector3 cameraPosition,
|
||||||
|
Vector3 cameraUpVector,
|
||||||
|
Vector3? cameraForwardVector,
|
||||||
|
out Matrix4 result
|
||||||
|
) {
|
||||||
|
Vector3 vector;
|
||||||
|
Vector3 vector2;
|
||||||
|
Vector3 vector3;
|
||||||
|
vector.mX = objectPosition.mX - cameraPosition.mX;
|
||||||
|
vector.mY = objectPosition.mY - cameraPosition.mY;
|
||||||
|
vector.mZ = objectPosition.mZ - cameraPosition.mZ;
|
||||||
|
float num = vector.LengthSquared;
|
||||||
|
if (num < 0.0001f)
|
||||||
|
{
|
||||||
|
vector = cameraForwardVector.HasValue ?
|
||||||
|
-cameraForwardVector.Value :
|
||||||
|
Vector3.Forward;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vector *= (float) (1f / ((float) Math.Sqrt((double) num)));
|
||||||
|
}
|
||||||
|
vector3 = Vector3.Cross(cameraUpVector, vector);
|
||||||
|
vector3.Normalize();
|
||||||
|
vector2 = Vector3.Cross(vector, vector3);
|
||||||
|
result.m00 = vector3.mX;
|
||||||
|
result.m10 = vector3.mY;
|
||||||
|
result.m20 = vector3.mZ;
|
||||||
|
result.m30 = 0;
|
||||||
|
result.m01 = vector2.mX;
|
||||||
|
result.m11 = vector2.mY;
|
||||||
|
result.m21 = vector2.mZ;
|
||||||
|
result.m31 = 0;
|
||||||
|
result.m02 = vector.mX;
|
||||||
|
result.m12 = vector.mY;
|
||||||
|
result.m22 = vector.mZ;
|
||||||
|
result.m32 = 0;
|
||||||
|
result.m03 = objectPosition.mX;
|
||||||
|
result.m13 = objectPosition.mY;
|
||||||
|
result.m23 = objectPosition.mZ;
|
||||||
|
result.m33 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new matrix for cylindrical billboarding that rotates around specified axis.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="objectPosition">Object position the billboard will rotate around.
|
||||||
|
/// <param name="cameraPosition">Camera position.
|
||||||
|
/// <param name="rotateAxis">Axis of billboard for rotation.
|
||||||
|
/// <param name="cameraForwardVector">Optional camera forward vector.
|
||||||
|
/// <param name="objectForwardVector">Optional object forward vector.
|
||||||
|
/// <returns>The matrix for cylindrical billboarding.</returns>
|
||||||
|
public static Matrix4 CreateConstrainedBillboard(
|
||||||
|
Vector3 objectPosition,
|
||||||
|
Vector3 cameraPosition,
|
||||||
|
Vector3 rotateAxis,
|
||||||
|
Nullable<Vector3> cameraForwardVector,
|
||||||
|
Nullable<Vector3> objectForwardVector
|
||||||
|
) {
|
||||||
|
Matrix4 result;
|
||||||
|
CreateConstrainedBillboard(
|
||||||
|
objectPosition,
|
||||||
|
cameraPosition,
|
||||||
|
rotateAxis,
|
||||||
|
cameraForwardVector,
|
||||||
|
objectForwardVector,
|
||||||
|
out result
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new matrix for cylindrical billboarding that rotates around specified axis.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="objectPosition">Object position the billboard will rotate around.
|
||||||
|
/// <param name="cameraPosition">Camera position.
|
||||||
|
/// <param name="rotateAxis">Axis of billboard for rotation.
|
||||||
|
/// <param name="cameraForwardVector">Optional camera forward vector.
|
||||||
|
/// <param name="objectForwardVector">Optional object forward vector.
|
||||||
|
/// <param name="result">The matrix for cylindrical billboarding as an output parameter.
|
||||||
|
public static void CreateConstrainedBillboard(
|
||||||
|
Vector3 objectPosition,
|
||||||
|
Vector3 cameraPosition,
|
||||||
|
Vector3 rotateAxis,
|
||||||
|
Vector3? cameraForwardVector,
|
||||||
|
Vector3? objectForwardVector,
|
||||||
|
out Matrix4 result
|
||||||
|
) {
|
||||||
|
float num;
|
||||||
|
Vector3 vector;
|
||||||
|
Vector3 vector2;
|
||||||
|
Vector3 vector3;
|
||||||
|
vector2.mX = objectPosition.mX - cameraPosition.mX;
|
||||||
|
vector2.mY = objectPosition.mY - cameraPosition.mY;
|
||||||
|
vector2.mZ = objectPosition.mZ - cameraPosition.mZ;
|
||||||
|
float num2 = vector2.LengthSquared;
|
||||||
|
if (num2 < 0.0001f)
|
||||||
|
{
|
||||||
|
vector2 = cameraForwardVector.HasValue ?
|
||||||
|
-cameraForwardVector.Value :
|
||||||
|
Vector3.Forward;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vector2 *= (float) (1f / ((float) Math.Sqrt((double) num2)));
|
||||||
|
}
|
||||||
|
Vector3 vector4 = rotateAxis;
|
||||||
|
num = Vector3.Dot(rotateAxis, vector2);
|
||||||
|
if (Math.Abs(num) > 0.9982547f)
|
||||||
|
{
|
||||||
|
if (objectForwardVector.HasValue)
|
||||||
|
{
|
||||||
|
vector = objectForwardVector.Value;
|
||||||
|
num = Vector3.Dot(rotateAxis, vector);
|
||||||
|
if (Math.Abs(num) > 0.9982547f)
|
||||||
|
{
|
||||||
|
num = (
|
||||||
|
(rotateAxis.mX * Vector3.Forward.mX) +
|
||||||
|
(rotateAxis.mY * Vector3.Forward.mY)
|
||||||
|
) + (rotateAxis.mZ * Vector3.Forward.mZ);
|
||||||
|
vector = (Math.Abs(num) > 0.9982547f) ?
|
||||||
|
Vector3.Right :
|
||||||
|
Vector3.Forward;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num = (
|
||||||
|
(rotateAxis.mX * Vector3.Forward.mX) +
|
||||||
|
(rotateAxis.mY * Vector3.Forward.mY)
|
||||||
|
) + (rotateAxis.mZ * Vector3.Forward.mZ);
|
||||||
|
vector = (Math.Abs(num) > 0.9982547f) ?
|
||||||
|
Vector3.Right :
|
||||||
|
Vector3.Forward;
|
||||||
|
}
|
||||||
|
vector3 = Vector3.Cross(rotateAxis, vector);
|
||||||
|
vector3.Normalize();
|
||||||
|
vector = Vector3.Cross(vector3, rotateAxis);
|
||||||
|
vector.Normalize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vector3 = Vector3.Cross(rotateAxis, vector2);
|
||||||
|
vector3.Normalize();
|
||||||
|
vector = Vector3.Cross(vector3, vector4);
|
||||||
|
vector.Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.m00 = vector3.mX;
|
||||||
|
result.m10 = vector3.mY;
|
||||||
|
result.m20 = vector3.mZ;
|
||||||
|
result.m30 = 0;
|
||||||
|
result.m01 = vector4.mX;
|
||||||
|
result.m11 = vector4.mY;
|
||||||
|
result.m21 = vector4.mZ;
|
||||||
|
result.m31 = 0;
|
||||||
|
result.m02 = vector.mX;
|
||||||
|
result.m12 = vector.mY;
|
||||||
|
result.m22 = vector.mZ;
|
||||||
|
result.m32 = 0;
|
||||||
|
result.m03 = objectPosition.mX;
|
||||||
|
result.m13 = objectPosition.mY;
|
||||||
|
result.m23 = objectPosition.mZ;
|
||||||
|
result.m33 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new matrix which contains the rotation moment around specified axis.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="axis">The axis of rotation.
|
||||||
|
/// <param name="angle">The angle of rotation in radians.
|
||||||
|
/// <returns>The rotation matrix.</returns>
|
||||||
|
public static Matrix4 CreateFromAxisAngle(Vector3 axis, float angle)
|
||||||
|
{
|
||||||
|
Matrix4 result;
|
||||||
|
CreateFromAxisAngle(axis, angle, out result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new matrix which contains the rotation moment around specified axis.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="axis">The axis of rotation.
|
||||||
|
/// <param name="angle">The angle of rotation in radians.
|
||||||
|
/// <param name="result">The rotation matrix as an output parameter.
|
||||||
|
public static void CreateFromAxisAngle(
|
||||||
|
Vector3 axis,
|
||||||
|
float angle,
|
||||||
|
out Matrix4 result
|
||||||
|
) {
|
||||||
|
float x = axis.mX;
|
||||||
|
float y = axis.mY;
|
||||||
|
float z = axis.mZ;
|
||||||
|
float num2 = (float) Math.Sin((double) angle);
|
||||||
|
float num = (float) Math.Cos((double) angle);
|
||||||
|
float num11 = x * x;
|
||||||
|
float num10 = y * y;
|
||||||
|
float num9 = z * z;
|
||||||
|
float num8 = x * y;
|
||||||
|
float num7 = x * z;
|
||||||
|
float num6 = y * z;
|
||||||
|
result.m00 = num11 + (num * (1f - num11));
|
||||||
|
result.m10 = (num8 - (num * num8)) + (num2 * z);
|
||||||
|
result.m20 = (num7 - (num * num7)) - (num2 * y);
|
||||||
|
result.m30 = 0;
|
||||||
|
result.m01 = (num8 - (num * num8)) - (num2 * z);
|
||||||
|
result.m11 = num10 + (num * (1f - num10));
|
||||||
|
result.m21 = (num6 - (num * num6)) + (num2 * x);
|
||||||
|
result.m31 = 0;
|
||||||
|
result.m02 = (num7 - (num * num7)) + (num2 * y);
|
||||||
|
result.m12 = (num6 - (num * num6)) - (num2 * x);
|
||||||
|
result.m22 = num9 + (num * (1f - num9));
|
||||||
|
result.m32 = 0;
|
||||||
|
result.m03 = 0;
|
||||||
|
result.m13 = 0;
|
||||||
|
result.m23 = 0;
|
||||||
|
result.m33 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new rotation matrix from a <see cref="Quaternion"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quaternion"><see cref="Quaternion"/> of rotation moment.
|
||||||
|
/// <returns>The rotation matrix.</returns>
|
||||||
|
public static Matrix4 CreateFromQuaternion(Quaternion quaternion)
|
||||||
|
{
|
||||||
|
Matrix4 result;
|
||||||
|
CreateFromQuaternion(quaternion, out result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new rotation matrix from a <see cref="Quaternion"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quaternion"><see cref="Quaternion"/> of rotation moment.
|
||||||
|
/// <param name="result">The rotation matrix as an output parameter.
|
||||||
|
public static void CreateFromQuaternion(Quaternion quaternion, out Matrix4 result)
|
||||||
|
{
|
||||||
|
float num9 = quaternion.mX * quaternion.mX;
|
||||||
|
float num8 = quaternion.mY * quaternion.mY;
|
||||||
|
float num7 = quaternion.mZ * quaternion.mZ;
|
||||||
|
float num6 = quaternion.mX * quaternion.mY;
|
||||||
|
float num5 = quaternion.mZ * quaternion.mW;
|
||||||
|
float num4 = quaternion.mZ * quaternion.mX;
|
||||||
|
float num3 = quaternion.mY * quaternion.mW;
|
||||||
|
float num2 = quaternion.mY * quaternion.mZ;
|
||||||
|
float num = quaternion.mX * quaternion.mW;
|
||||||
|
result.m00 = 1f - (2f * (num8 + num7));
|
||||||
|
result.m10 = 2f * (num6 + num5);
|
||||||
|
result.m20 = 2f * (num4 - num3);
|
||||||
|
result.m30 = 0f;
|
||||||
|
result.m01 = 2f * (num6 - num5);
|
||||||
|
result.m11 = 1f - (2f * (num7 + num9));
|
||||||
|
result.m21 = 2f * (num2 + num);
|
||||||
|
result.m31 = 0f;
|
||||||
|
result.m02 = 2f * (num4 + num3);
|
||||||
|
result.m12 = 2f * (num2 - num);
|
||||||
|
result.m22 = 1f - (2f * (num8 + num9));
|
||||||
|
result.m32 = 0f;
|
||||||
|
result.m03 = 0f;
|
||||||
|
result.m13 = 0f;
|
||||||
|
result.m23 = 0f;
|
||||||
|
result.m33 = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new rotation matrix from the specified yaw, pitch and roll values.
|
||||||
|
/// @param yaw The yaw rotation value in radians.
|
||||||
|
/// @param pitch The pitch rotation value in radians.
|
||||||
|
/// @param roll The roll rotation value in radians.
|
||||||
|
/// @returns The rotation matrix
|
||||||
|
/// @remarks For more information about yaw, pitch and roll visit http://en.wikipedia.org/wiki/Euler_angles.
|
||||||
|
public static Matrix4 CreateFromYawPitchRoll(float yaw, float pitch, float roll)
|
||||||
|
{
|
||||||
|
Matrix4 matrix;
|
||||||
|
CreateFromYawPitchRoll(yaw, pitch, roll, out matrix);
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new rotation matrix from the specified yaw, pitch and roll values.
|
||||||
|
/// @param yaw The yaw rotation value in radians.
|
||||||
|
/// @param pitch The pitch rotation value in radians.
|
||||||
|
/// @param roll The roll rotation value in radians.
|
||||||
|
/// @param result The rotation matrix as an output parameter.
|
||||||
|
/// @remarks>For more information about yaw, pitch and roll visit http://en.wikipedia.org/wiki/Euler_angles.
|
||||||
|
public static void CreateFromYawPitchRoll(
|
||||||
|
float yaw,
|
||||||
|
float pitch,
|
||||||
|
float roll,
|
||||||
|
out Matrix4 result
|
||||||
|
) {
|
||||||
|
Quaternion quaternion;
|
||||||
|
Quaternion.CreateFromYawPitchRoll(yaw, pitch, roll, out quaternion);
|
||||||
|
CreateFromQuaternion(quaternion, out result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new viewing matrix.
|
||||||
|
/// @param cameraPosition Position of the camera.
|
||||||
|
/// @param cameraTarget Lookup vector of the camera.
|
||||||
|
/// @param cameraUpVector The direction of the upper edge of the camera.
|
||||||
|
/// @returns The viewing matrix.
|
||||||
|
public static Matrix4 CreateLookAt(
|
||||||
|
Vector3 cameraPosition,
|
||||||
|
Vector3 cameraTarget,
|
||||||
|
Vector3 cameraUpVector
|
||||||
|
) {
|
||||||
|
Matrix4 matrix;
|
||||||
|
CreateLookAt(cameraPosition, cameraTarget, cameraUpVector, out matrix);
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new viewing matrix.
|
||||||
|
/// @param cameraPosition Position of the camera.
|
||||||
|
/// @param cameraTarget Lookup vector of the camera.
|
||||||
|
/// @param cameraUpVector The direction of the upper edge of the camera.
|
||||||
|
/// @param result The viewing matrix as an output parameter.
|
||||||
|
public static void CreateLookAt(
|
||||||
|
Vector3 cameraPosition,
|
||||||
|
Vector3 cameraTarget,
|
||||||
|
Vector3 cameraUpVector,
|
||||||
|
out Matrix4 result
|
||||||
|
) {
|
||||||
|
Vector3 vectorA = Vector3.Normalize(cameraPosition - cameraTarget);
|
||||||
|
Vector3 vectorB = Vector3.Normalize(Vector3.Cross(cameraUpVector, vectorA));
|
||||||
|
Vector3 vectorC = Vector3.Cross(vectorA, vectorB);
|
||||||
|
result.m00 = vectorB.mX;
|
||||||
|
result.m10 = vectorC.mX;
|
||||||
|
result.m20 = vectorA.mX;
|
||||||
|
result.m30 = 0f;
|
||||||
|
result.m01 = vectorB.mY;
|
||||||
|
result.m11 = vectorC.mY;
|
||||||
|
result.m21 = vectorA.mY;
|
||||||
|
result.m31 = 0f;
|
||||||
|
result.m02 = vectorB.mZ;
|
||||||
|
result.m12 = vectorC.mZ;
|
||||||
|
result.m22 = vectorA.mZ;
|
||||||
|
result.m32 = 0f;
|
||||||
|
result.m03 = -Vector3.Dot(vectorB, cameraPosition);
|
||||||
|
result.m13 = -Vector3.Dot(vectorC, cameraPosition);
|
||||||
|
result.m23 = -Vector3.Dot(vectorA, cameraPosition);
|
||||||
|
result.m33 = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new projection matrix for orthographic view.
|
||||||
|
/// @param width Width of the viewing volume.
|
||||||
|
/// @param height Height of the viewing volume.
|
||||||
|
/// @param zNearPlane Depth of the near plane.
|
||||||
|
/// @param zFarPlane Depth of the far plane.
|
||||||
|
/// @returns The new projection matrix for orthographic view.</returns>
|
||||||
|
public static Matrix4 CreateOrthographic(
|
||||||
|
float width,
|
||||||
|
float height,
|
||||||
|
float zNearPlane,
|
||||||
|
float zFarPlane
|
||||||
|
) {
|
||||||
|
Matrix4 matrix;
|
||||||
|
CreateOrthographic(width, height, zNearPlane, zFarPlane, out matrix);
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new projection matrix for orthographic view.
|
||||||
|
/// @param width Width of the viewing volume.
|
||||||
|
/// @param height Height of the viewing volume.
|
||||||
|
/// @param zNearPlane Depth of the near plane.
|
||||||
|
/// @param zFarPlane Depth of the far plane.
|
||||||
|
/// @param result The new projection matrix for orthographic view as an output parameter.
|
||||||
|
public static void CreateOrthographic(
|
||||||
|
float width,
|
||||||
|
float height,
|
||||||
|
float zNearPlane,
|
||||||
|
float zFarPlane,
|
||||||
|
out Matrix4 result
|
||||||
|
) {
|
||||||
|
result.m00 = 2f / width;
|
||||||
|
result.m10 = result.m20 = result.m30 = 0f;
|
||||||
|
result.m11 = 2f / height;
|
||||||
|
result.m01 = result.m21 = result.m31 = 0f;
|
||||||
|
result.m22 = 1f / (zNearPlane - zFarPlane);
|
||||||
|
result.m02 = result.m12 = result.m32 = 0f;
|
||||||
|
result.m03 = result.m13 = 0f;
|
||||||
|
result.m23 = zNearPlane / (zNearPlane - zFarPlane);
|
||||||
|
result.m33 = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new projection matrix for customized orthographic view.
|
||||||
|
/// @param left Lower x-value at the near plane.
|
||||||
|
/// @param right Upper x-value at the near plane.
|
||||||
|
/// @param bottom Lower y-coordinate at the near plane.
|
||||||
|
/// @param top Upper y-value at the near plane.
|
||||||
|
/// @param zNearPlane Depth of the near plane.
|
||||||
|
/// @param zFarPlane Depth of the far plane.
|
||||||
|
/// @returns The new projection matrix for customized orthographic view.</returns>
|
||||||
|
public static Matrix4 CreateOrthographicOffCenter(
|
||||||
|
float left,
|
||||||
|
float right,
|
||||||
|
float bottom,
|
||||||
|
float top,
|
||||||
|
float zNearPlane,
|
||||||
|
float zFarPlane
|
||||||
|
) {
|
||||||
|
Matrix4 matrix;
|
||||||
|
CreateOrthographicOffCenter(
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
bottom,
|
||||||
|
top,
|
||||||
|
zNearPlane,
|
||||||
|
zFarPlane,
|
||||||
|
out matrix
|
||||||
|
);
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new projection matrix for customized orthographic view.
|
||||||
|
/// @param left Lower x-value at the near plane.
|
||||||
|
/// @param right Upper x-value at the near plane.
|
||||||
|
/// @param bottom Lower y-coordinate at the near plane.
|
||||||
|
/// @param top Upper y-value at the near plane.
|
||||||
|
/// @param zNearPlane Depth of the near plane.
|
||||||
|
/// @param zFarPlane Depth of the far plane.
|
||||||
|
/// @param result The new projection matrix for customized orthographic view as an output parameter.
|
||||||
|
public static void CreateOrthographicOffCenter(
|
||||||
|
float left,
|
||||||
|
float right,
|
||||||
|
float bottom,
|
||||||
|
float top,
|
||||||
|
float zNearPlane,
|
||||||
|
float zFarPlane,
|
||||||
|
out Matrix4 result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
result.m00 = (float) (2.0 / ((double) right - (double) left));
|
||||||
|
result.m10 = 0.0f;
|
||||||
|
result.m20 = 0.0f;
|
||||||
|
result.m30 = 0.0f;
|
||||||
|
result.m01 = 0.0f;
|
||||||
|
result.m11 = (float) (2.0 / ((double) top - (double) bottom));
|
||||||
|
result.m21 = 0.0f;
|
||||||
|
result.m31 = 0.0f;
|
||||||
|
result.m02 = 0.0f;
|
||||||
|
result.m12 = 0.0f;
|
||||||
|
result.m22 = (float) (1.0 / ((double) zNearPlane - (double) zFarPlane));
|
||||||
|
result.m32 = 0.0f;
|
||||||
|
result.m03 = (float) (
|
||||||
|
((double) left + (double) right) /
|
||||||
|
((double) left - (double) right)
|
||||||
|
);
|
||||||
|
result.m13 = (float) (
|
||||||
|
((double) top + (double) bottom) /
|
||||||
|
((double) bottom - (double) top)
|
||||||
|
);
|
||||||
|
result.m23 = (float) (
|
||||||
|
(double) zNearPlane /
|
||||||
|
((double) zNearPlane - (double) zFarPlane)
|
||||||
|
);
|
||||||
|
result.m33 = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new matrix that flattens geometry into a specified <see cref="Plane"/> as if casting a shadow from a specified light source.
|
||||||
|
/// @param lightDirection A vector specifying the direction from which the light that will cast the shadow is coming.
|
||||||
|
/// @param plane The plane onto which the new matrix should flatten geometry so as to cast a shadow.
|
||||||
|
/// @returns>A matrix that can be used to flatten geometry onto the specified plane from the specified direction.
|
||||||
|
public static Matrix4 CreateShadow(Vector3 lightDirection, Plane plane)
|
||||||
|
{
|
||||||
|
Matrix4 result;
|
||||||
|
result = CreateShadow(lightDirection, plane);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new matrix that flattens geometry into a specified <see cref="Plane"/> as if casting a shadow from a specified light source.
|
||||||
|
/// @param lightDirection A vector specifying the direction from which the light that will cast the shadow is coming.
|
||||||
|
/// @param plane The plane onto which the new matrix should flatten geometry so as to cast a shadow.
|
||||||
|
/// @param result A matrix that can be used to flatten geometry onto the specified plane from the specified direction as an output parameter.
|
||||||
|
public static void CreateShadow(
|
||||||
|
Vector3 lightDirection,
|
||||||
|
Plane plane,
|
||||||
|
out Matrix4 result)
|
||||||
|
{
|
||||||
|
float dot = (
|
||||||
|
(plane.Normal.mX * lightDirection.mX) +
|
||||||
|
(plane.Normal.mY * lightDirection.mY) +
|
||||||
|
(plane.Normal.mZ * lightDirection.mZ)
|
||||||
|
);
|
||||||
|
float x = -plane.Normal.mX;
|
||||||
|
float y = -plane.Normal.mY;
|
||||||
|
float z = -plane.Normal.mZ;
|
||||||
|
float d = -plane.D;
|
||||||
|
|
||||||
|
result.m00 = (x * lightDirection.mX) + dot;
|
||||||
|
result.m10 = x * lightDirection.mY;
|
||||||
|
result.m20 = x * lightDirection.mZ;
|
||||||
|
result.m30 = 0;
|
||||||
|
result.m01 = y * lightDirection.mX;
|
||||||
|
result.m11 = (y * lightDirection.mY) + dot;
|
||||||
|
result.m21 = y * lightDirection.mZ;
|
||||||
|
result.m31 = 0;
|
||||||
|
result.m02 = z * lightDirection.mX;
|
||||||
|
result.m12 = z * lightDirection.mY;
|
||||||
|
result.m22 = (z * lightDirection.mZ) + dot;
|
||||||
|
result.m32 = 0;
|
||||||
|
result.m03 = d * lightDirection.mX;
|
||||||
|
result.m13 = d * lightDirection.mY;
|
||||||
|
result.m23 = d * lightDirection.mZ;
|
||||||
|
result.m33 = dot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ToString(System.String strBuffer)
|
||||||
|
{
|
||||||
|
for (int row < 4)
|
||||||
|
for (int col < 4)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
strBuffer.AppendF($"M{row+1}{col+1}:{((float*)&this)[row+col*4]}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
291
BeefLibs/Beefy2D/src/geom/Plane.bf
Normal file
291
BeefLibs/Beefy2D/src/geom/Plane.bf
Normal file
|
@ -0,0 +1,291 @@
|
||||||
|
// This file contains portions of code from the FNA project (github.com/FNA-XNA/FNA),
|
||||||
|
// released under the Microsoft Public License
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Beefy.geom
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the intersection between a <see cref="Plane"/> and a bounding volume.
|
||||||
|
/// </summary>
|
||||||
|
public enum PlaneIntersectionType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// There is no intersection, the bounding volume is in the negative half space of the plane.
|
||||||
|
/// </summary>
|
||||||
|
Front,
|
||||||
|
/// <summary>
|
||||||
|
/// There is no intersection, the bounding volume is in the positive half space of the plane.
|
||||||
|
/// </summary>
|
||||||
|
Back,
|
||||||
|
/// <summary>
|
||||||
|
/// The plane is intersected.
|
||||||
|
/// </summary>
|
||||||
|
Intersecting
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Plane
|
||||||
|
{
|
||||||
|
public Vector3 Normal;
|
||||||
|
public float D;
|
||||||
|
|
||||||
|
public this(Vector4 value)
|
||||||
|
: this(Vector3(value.mX, value.mY, value.mZ), value.mW)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(Vector3 normal, float d)
|
||||||
|
{
|
||||||
|
Normal = normal;
|
||||||
|
D = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(Vector3 a, Vector3 b, Vector3 c)
|
||||||
|
{
|
||||||
|
Vector3 ab = b - a;
|
||||||
|
Vector3 ac = c - a;
|
||||||
|
|
||||||
|
Vector3 cross = Vector3.Cross(ab, ac);
|
||||||
|
Vector3.Normalize(cross, out Normal);
|
||||||
|
D = -(Vector3.Dot(Normal, a));
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(float a, float b, float c, float d)
|
||||||
|
: this(Vector3(a, b, c), d)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Dot(Vector4 value)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
(this.Normal.mX * value.mX) +
|
||||||
|
(this.Normal.mY * value.mY) +
|
||||||
|
(this.Normal.mZ * value.mZ) +
|
||||||
|
(this.D * value.mW)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dot(ref Vector4 value, out float result)
|
||||||
|
{
|
||||||
|
result = (
|
||||||
|
(this.Normal.mX * value.mX) +
|
||||||
|
(this.Normal.mY * value.mY) +
|
||||||
|
(this.Normal.mZ * value.mZ) +
|
||||||
|
(this.D * value.mW)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float DotCoordinate(Vector3 value)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
(this.Normal.mX * value.mX) +
|
||||||
|
(this.Normal.mY * value.mY) +
|
||||||
|
(this.Normal.mZ * value.mZ) +
|
||||||
|
this.D
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DotCoordinate(ref Vector3 value, out float result)
|
||||||
|
{
|
||||||
|
result = (
|
||||||
|
(this.Normal.mX * value.mX) +
|
||||||
|
(this.Normal.mY * value.mY) +
|
||||||
|
(this.Normal.mZ * value.mZ) +
|
||||||
|
this.D
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float DotNormal(Vector3 value)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
(this.Normal.mX * value.mX) +
|
||||||
|
(this.Normal.mY * value.mY) +
|
||||||
|
(this.Normal.mZ * value.mZ)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DotNormal(Vector3 value, out float result)
|
||||||
|
{
|
||||||
|
result = (
|
||||||
|
(this.Normal.mX * value.mX) +
|
||||||
|
(this.Normal.mY * value.mY) +
|
||||||
|
(this.Normal.mZ * value.mZ)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Normalize() mut
|
||||||
|
{
|
||||||
|
float length = Normal.Length;
|
||||||
|
float factor = 1.0f / length;
|
||||||
|
Normal = Vector3.Multiply(Normal, factor);
|
||||||
|
D = D * factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public PlaneIntersectionType Intersects(BoundingBox box)
|
||||||
|
{
|
||||||
|
return box.Intersects(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Intersects(ref BoundingBox box, out PlaneIntersectionType result)
|
||||||
|
{
|
||||||
|
box.Intersects(ref this, out result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlaneIntersectionType Intersects(BoundingSphere sphere)
|
||||||
|
{
|
||||||
|
return sphere.Intersects(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Intersects(ref BoundingSphere sphere, out PlaneIntersectionType result)
|
||||||
|
{
|
||||||
|
sphere.Intersects(ref this, out result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlaneIntersectionType Intersects(BoundingFrustum frustum)
|
||||||
|
{
|
||||||
|
return frustum.Intersects(this);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Internal Methods
|
||||||
|
|
||||||
|
internal PlaneIntersectionType Intersects(ref Vector3 point)
|
||||||
|
{
|
||||||
|
float distance;
|
||||||
|
DotCoordinate(ref point, out distance);
|
||||||
|
if (distance > 0)
|
||||||
|
{
|
||||||
|
return PlaneIntersectionType.Front;
|
||||||
|
}
|
||||||
|
if (distance < 0)
|
||||||
|
{
|
||||||
|
return PlaneIntersectionType.Back;
|
||||||
|
}
|
||||||
|
return PlaneIntersectionType.Intersecting;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Static Methods
|
||||||
|
|
||||||
|
public static Plane Normalize(Plane value)
|
||||||
|
{
|
||||||
|
Plane ret;
|
||||||
|
Normalize(value, out ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Normalize(Plane value, out Plane result)
|
||||||
|
{
|
||||||
|
float length = value.Normal.Length;
|
||||||
|
float factor = 1.0f / length;
|
||||||
|
result.Normal = Vector3.Multiply(value.Normal, factor);
|
||||||
|
result.D = value.D * factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transforms a normalized plane by a matrix.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="plane">The normalized plane to transform.</param>
|
||||||
|
/// <param name="matrix">The transformation matrix.</param>
|
||||||
|
/// <returns>The transformed plane.</returns>
|
||||||
|
public static Plane Transform(Plane plane, Matrix4 matrix)
|
||||||
|
{
|
||||||
|
Plane result;
|
||||||
|
Transform(plane, matrix, out result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transforms a normalized plane by a matrix.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="plane">The normalized plane to transform.</param>
|
||||||
|
/// <param name="matrix">The transformation matrix.</param>
|
||||||
|
/// <param name="result">The transformed plane.</param>
|
||||||
|
public static void Transform(
|
||||||
|
Plane plane,
|
||||||
|
Matrix4 matrix,
|
||||||
|
out Plane result
|
||||||
|
) {
|
||||||
|
/* See "Transforming Normals" in
|
||||||
|
* http://www.glprogramming.com/red/appendixf.html
|
||||||
|
* for an explanation of how this works.
|
||||||
|
*/
|
||||||
|
Matrix4 transformedMatrix;
|
||||||
|
transformedMatrix = Matrix4.Invert(matrix);
|
||||||
|
transformedMatrix = Matrix4.Transpose(transformedMatrix);
|
||||||
|
Vector4 vector = Vector4(plane.Normal, plane.D);
|
||||||
|
Vector4 transformedVector;
|
||||||
|
Vector4.Transform(
|
||||||
|
vector,
|
||||||
|
transformedMatrix,
|
||||||
|
out transformedVector
|
||||||
|
);
|
||||||
|
result = Plane(transformedVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transforms a normalized plane by a quaternion rotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="plane">The normalized plane to transform.</param>
|
||||||
|
/// <param name="rotation">The quaternion rotation.</param>
|
||||||
|
/// <returns>The transformed plane.</returns>
|
||||||
|
public static Plane Transform(Plane plane, Quaternion rotation)
|
||||||
|
{
|
||||||
|
Plane result;
|
||||||
|
Transform(plane, rotation, out result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transforms a normalized plane by a quaternion rotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="plane">The normalized plane to transform.</param>
|
||||||
|
/// <param name="rotation">The quaternion rotation.</param>
|
||||||
|
/// <param name="result">The transformed plane.</param>
|
||||||
|
public static void Transform(
|
||||||
|
Plane plane,
|
||||||
|
Quaternion rotation,
|
||||||
|
out Plane result
|
||||||
|
) {
|
||||||
|
result.Normal = Vector3.Transform(
|
||||||
|
plane.Normal,
|
||||||
|
rotation
|
||||||
|
);
|
||||||
|
result.D = plane.D;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Static Operators and Override Methods
|
||||||
|
|
||||||
|
public static bool operator !=(Plane plane1, Plane plane2)
|
||||||
|
{
|
||||||
|
return !plane1.Equals(plane2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Plane plane1, Plane plane2)
|
||||||
|
{
|
||||||
|
return plane1.Equals(plane2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Plane other)
|
||||||
|
{
|
||||||
|
return (Normal == other.Normal && D == other.D);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode()
|
||||||
|
{
|
||||||
|
return Normal.GetHashCode() ^ D.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ToString(String str)
|
||||||
|
{
|
||||||
|
str.AppendF($"{Normal:{Normal} D:{D}}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,6 @@
|
||||||
|
// This file contains portions of code from the FNA project (github.com/FNA-XNA/FNA),
|
||||||
|
// released under the Microsoft Public License
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Beefy.gfx;
|
using Beefy.gfx;
|
||||||
|
|
||||||
|
@ -189,43 +192,50 @@ namespace Beefy.geom
|
||||||
|
|
||||||
public static void CreateFromRotationMatrix(ref Matrix4 matrix, out Quaternion result)
|
public static void CreateFromRotationMatrix(ref Matrix4 matrix, out Quaternion result)
|
||||||
{
|
{
|
||||||
float num8 = (matrix.m11 + matrix.m22) + matrix.m33;
|
float sqrt;
|
||||||
if (num8 > 0f)
|
float half;
|
||||||
{
|
float scale = matrix.m00 + matrix.m11 + matrix.m22;
|
||||||
float num = (float)Math.Sqrt((double)(num8 + 1f));
|
|
||||||
result.mW = num * 0.5f;
|
if (scale > 0.0f)
|
||||||
num = 0.5f / num;
|
{
|
||||||
result.mX = (matrix.m23 - matrix.m32) * num;
|
sqrt = (float) Math.Sqrt(scale + 1.0f);
|
||||||
result.mY = (matrix.m31 - matrix.m13) * num;
|
result.mW = sqrt * 0.5f;
|
||||||
result.mZ = (matrix.m12 - matrix.m21) * num;
|
sqrt = 0.5f / sqrt;
|
||||||
}
|
|
||||||
else if ((matrix.m11 >= matrix.m22) && (matrix.m11 >= matrix.m33))
|
result.mX = (matrix.m21 - matrix.m12) * sqrt;
|
||||||
{
|
result.mY = (matrix.m02 - matrix.m20) * sqrt;
|
||||||
float num7 = (float)Math.Sqrt((double)(((1f + matrix.m11) - matrix.m22) - matrix.m33));
|
result.mZ = (matrix.m10 - matrix.m01) * sqrt;
|
||||||
float num4 = 0.5f / num7;
|
}
|
||||||
result.mX = 0.5f * num7;
|
else if ((matrix.m00 >= matrix.m11) && (matrix.m00 >= matrix.m22))
|
||||||
result.mY = (matrix.m12 + matrix.m21) * num4;
|
{
|
||||||
result.mZ = (matrix.m13 + matrix.m31) * num4;
|
sqrt = (float) Math.Sqrt(1.0f + matrix.m00 - matrix.m11 - matrix.m22);
|
||||||
result.mW = (matrix.m23 - matrix.m32) * num4;
|
half = 0.5f / sqrt;
|
||||||
}
|
|
||||||
else if (matrix.m22 > matrix.m33)
|
result.mX = 0.5f * sqrt;
|
||||||
{
|
result.mY = (matrix.m10 + matrix.m01) * half;
|
||||||
float num6 = (float)Math.Sqrt((double)(((1f + matrix.m22) - matrix.m11) - matrix.m33));
|
result.mZ = (matrix.m20 + matrix.m02) * half;
|
||||||
float num3 = 0.5f / num6;
|
result.mW = (matrix.m21 - matrix.m12) * half;
|
||||||
result.mX = (matrix.m21 + matrix.m12) * num3;
|
}
|
||||||
result.mY = 0.5f * num6;
|
else if (matrix.m11 > matrix.m22)
|
||||||
result.mZ = (matrix.m32 + matrix.m23) * num3;
|
{
|
||||||
result.mW = (matrix.m31 - matrix.m13) * num3;
|
sqrt = (float) Math.Sqrt(1.0f + matrix.m11 - matrix.m00 - matrix.m22);
|
||||||
}
|
half = 0.5f/sqrt;
|
||||||
else
|
|
||||||
{
|
result.mX = (matrix.m01 + matrix.m10)*half;
|
||||||
float num5 = (float)Math.Sqrt((double)(((1f + matrix.m33) - matrix.m11) - matrix.m22));
|
result.mY = 0.5f*sqrt;
|
||||||
float num2 = 0.5f / num5;
|
result.mZ = (matrix.m12 + matrix.m21)*half;
|
||||||
result.mX = (matrix.m31 + matrix.m13) * num2;
|
result.mW = (matrix.m02 - matrix.m20)*half;
|
||||||
result.mY = (matrix.m32 + matrix.m23) * num2;
|
}
|
||||||
result.mZ = 0.5f * num5;
|
else
|
||||||
result.mW = (matrix.m12 - matrix.m21) * num2;
|
{
|
||||||
}
|
sqrt = (float) Math.Sqrt(1.0f + matrix.m22 - matrix.m00 - matrix.m11);
|
||||||
|
half = 0.5f / sqrt;
|
||||||
|
|
||||||
|
result.mX = (matrix.m02 + matrix.m20) * half;
|
||||||
|
result.mY = (matrix.m12 + matrix.m21) * half;
|
||||||
|
result.mZ = 0.5f * sqrt;
|
||||||
|
result.mW = (matrix.m10 - matrix.m01) * half;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float roll)
|
public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float roll)
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// This file contains portions of code from the FNA project (github.com/FNA-XNA/FNA),
|
||||||
|
// released under the Microsoft Public License
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -131,7 +134,7 @@ namespace Beefy.geom
|
||||||
{
|
{
|
||||||
Vector3 newVec;
|
Vector3 newVec;
|
||||||
Normalize(vector, out newVec);
|
Normalize(vector, out newVec);
|
||||||
return vector;
|
return newVec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Normalize(Vector3 value, out Vector3 result)
|
public static void Normalize(Vector3 value, out Vector3 result)
|
||||||
|
@ -173,7 +176,7 @@ namespace Beefy.geom
|
||||||
return new Vector2D((float)Math.Cos(angle) * length, (float)Math.Sin(angle) * length);
|
return new Vector2D((float)Math.Cos(angle) * length, (float)Math.Sin(angle) * length);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public static Vector3 Transform(Vector3 vec, Matrix4 matrix)
|
public static Vector3 TransformW(Vector3 vec, Matrix4 matrix)
|
||||||
{
|
{
|
||||||
Vector3 result;
|
Vector3 result;
|
||||||
float fInvW = 1.0f / (matrix.m30 * vec.mX + matrix.m31 * vec.mY + matrix.m32 * vec.mZ + matrix.m33);
|
float fInvW = 1.0f / (matrix.m30 * vec.mX + matrix.m31 * vec.mY + matrix.m32 * vec.mZ + matrix.m33);
|
||||||
|
@ -181,9 +184,19 @@ namespace Beefy.geom
|
||||||
result.mX = (matrix.m00 * vec.mX + matrix.m01 * vec.mY + matrix.m02 * vec.mZ + matrix.m03) * fInvW;
|
result.mX = (matrix.m00 * vec.mX + matrix.m01 * vec.mY + matrix.m02 * vec.mZ + matrix.m03) * fInvW;
|
||||||
result.mY = (matrix.m10 * vec.mX + matrix.m11 * vec.mY + matrix.m12 * vec.mZ + matrix.m13) * fInvW;
|
result.mY = (matrix.m10 * vec.mX + matrix.m11 * vec.mY + matrix.m12 * vec.mZ + matrix.m13) * fInvW;
|
||||||
result.mZ = (matrix.m20 * vec.mX + matrix.m21 * vec.mY + matrix.m22 * vec.mZ + matrix.m23) * fInvW;
|
result.mZ = (matrix.m20 * vec.mX + matrix.m21 * vec.mY + matrix.m22 * vec.mZ + matrix.m23) * fInvW;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Vector3 Transform(Vector3 vec, Matrix4 matrix)
|
||||||
|
{
|
||||||
|
Vector3 result;
|
||||||
|
result.mX = (vec.mX * matrix.m00) + (vec.mY * matrix.m01) + (vec.mZ * matrix.m02) + matrix.m03;
|
||||||
|
result.mY = (vec.mX * matrix.m10) + (vec.mY * matrix.m11) + (vec.mZ * matrix.m12) + matrix.m13;
|
||||||
|
result.mZ = (vec.mX * matrix.m20) + (vec.mY * matrix.m21) + (vec.mZ * matrix.m22) + matrix.m23;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*public static void Transform(Vector3[] sourceArray, ref Matrix4 matrix, Vector3[] destinationArray)
|
/*public static void Transform(Vector3[] sourceArray, ref Matrix4 matrix, Vector3[] destinationArray)
|
||||||
{
|
{
|
||||||
//Debug.Assert(destinationArray.Length >= sourceArray.Length, "The destination array is smaller than the source array.");
|
//Debug.Assert(destinationArray.Length >= sourceArray.Length, "The destination array is smaller than the source array.");
|
||||||
|
@ -199,6 +212,51 @@ namespace Beefy.geom
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see>Vector3</see> pointing in the opposite
|
||||||
|
/// direction of <paramref name="value"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The vector to negate.</param>
|
||||||
|
/// <returns>The vector negation of <paramref name="value"/>.</returns>
|
||||||
|
public static Vector3 Negate(Vector3 value)
|
||||||
|
{
|
||||||
|
return .(-value.mX, -value.mY, -value.mZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores a <see>Vector3</see> pointing in the opposite
|
||||||
|
/// direction of <paramref name="value"/> in <paramref name="result"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The vector to negate.</param>
|
||||||
|
/// <param name="result">The vector that the negation of <paramref name="value"/> will be stored in.</param>
|
||||||
|
public static void Negate(Vector3 value, out Vector3 result)
|
||||||
|
{
|
||||||
|
result.mX = -value.mX;
|
||||||
|
result.mY = -value.mY;
|
||||||
|
result.mZ = -value.mZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="Vector3"/> that contains a multiplication of two vectors.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value1">Source <see cref="Vector3"/>.</param>
|
||||||
|
/// <param name="value2">Source <see cref="Vector3"/>.</param>
|
||||||
|
/// <returns>The result of the vector multiplication.</returns>
|
||||||
|
public static Vector3 Multiply(Vector3 value1, Vector3 value2)
|
||||||
|
{
|
||||||
|
return .(value1.mX * value2.mX, value1.mY * value2.mY, value1.mZ * value2.mZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 Multiply(Vector3 value1, float value2)
|
||||||
|
{
|
||||||
|
return .(value1.mX * value2, value1.mY * value2, value1.mZ * value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Normalize() mut
|
||||||
|
{
|
||||||
|
Normalize(this, out this);
|
||||||
|
}
|
||||||
|
|
||||||
public static Vector3 Transform(Vector3 vec, Quaternion quat)
|
public static Vector3 Transform(Vector3 vec, Quaternion quat)
|
||||||
{
|
{
|
||||||
Matrix4 matrix = quat.ToMatrix();
|
Matrix4 matrix = quat.ToMatrix();
|
||||||
|
@ -234,6 +292,11 @@ namespace Beefy.geom
|
||||||
return Vector3(vec1.mX - vec2.mX, vec1.mY - vec2.mY, vec1.mZ - vec2.mZ);
|
return Vector3(vec1.mX - vec2.mX, vec1.mY - vec2.mY, vec1.mZ - vec2.mZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Vector3 operator -(Vector3 vec1)
|
||||||
|
{
|
||||||
|
return Vector3(-vec1.mX, -vec1.mY, -vec1.mZ);
|
||||||
|
}
|
||||||
|
|
||||||
public static Vector3 operator *(Vector3 vec, float scale)
|
public static Vector3 operator *(Vector3 vec, float scale)
|
||||||
{
|
{
|
||||||
return Vector3(vec.mX * scale, vec.mY * scale, vec.mZ * scale);
|
return Vector3(vec.mX * scale, vec.mY * scale, vec.mZ * scale);
|
||||||
|
|
1435
BeefLibs/Beefy2D/src/geom/Vector4.bf
Normal file
1435
BeefLibs/Beefy2D/src/geom/Vector4.bf
Normal file
File diff suppressed because it is too large
Load diff
59
BeefLibs/Beefy2D/src/geom/Viewport.bf
Normal file
59
BeefLibs/Beefy2D/src/geom/Viewport.bf
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// This file contains portions of code from the FNA project (github.com/FNA-XNA/FNA),
|
||||||
|
// released under the Microsoft Public License
|
||||||
|
|
||||||
|
using Beefy.geom;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Beefy.geom
|
||||||
|
{
|
||||||
|
struct Viewport
|
||||||
|
{
|
||||||
|
private int mX;
|
||||||
|
private int mY;
|
||||||
|
private int mWidth;
|
||||||
|
private int mHeight;
|
||||||
|
private float mMinDepth;
|
||||||
|
private float mMaxDepth;
|
||||||
|
|
||||||
|
public this(int x, int y, int width, int height,float minDepth,float maxDepth)
|
||||||
|
{
|
||||||
|
this.mX = x;
|
||||||
|
this.mY = y;
|
||||||
|
this.mWidth = width;
|
||||||
|
this.mHeight = height;
|
||||||
|
this.mMinDepth = minDepth;
|
||||||
|
this.mMaxDepth = maxDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unprojects a Vector3 from screen space into world space.
|
||||||
|
/// @param source The Vector3 to unproject.
|
||||||
|
/// @param projection The projection
|
||||||
|
/// @param view The view
|
||||||
|
/// @param world The world
|
||||||
|
public Vector3 Unproject(Vector3 source, Matrix4 projection, Matrix4 view, Matrix4 world)
|
||||||
|
{
|
||||||
|
var source;
|
||||||
|
|
||||||
|
Matrix4 matrix = Matrix4.Invert(Matrix4.Multiply(Matrix4.Multiply(world, view), projection));
|
||||||
|
source.mX = (((source.mX - this.mX) / ((float) this.mWidth)) * 2f) - 1f;
|
||||||
|
source.mY = -((((source.mY - this.mY) / ((float) this.mHeight)) * 2f) - 1f);
|
||||||
|
source.mZ = (source.mZ - this.mMinDepth) / (this.mMaxDepth - this.mMinDepth);
|
||||||
|
Vector3 vector = Vector3.Transform(source, matrix);
|
||||||
|
float a = (((source.mX * matrix.m30) + (source.mY * matrix.m31)) + (source.mZ * matrix.m32)) + matrix.m33;
|
||||||
|
if (!WithinEpsilon(a, 1f))
|
||||||
|
{
|
||||||
|
vector.mX = vector.mX / a;
|
||||||
|
vector.mY = vector.mY / a;
|
||||||
|
vector.mZ = vector.mZ / a;
|
||||||
|
}
|
||||||
|
return vector;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool WithinEpsilon(float a, float b)
|
||||||
|
{
|
||||||
|
float num = a - b;
|
||||||
|
return ((-1.401298E-45f <= num) && (num <= float.Epsilon));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -112,13 +112,13 @@ namespace Beefy.gfx
|
||||||
enum MarkPosition
|
enum MarkPosition
|
||||||
{
|
{
|
||||||
AboveC, // Center
|
AboveC, // Center
|
||||||
AboveR, // Left edge of mark aligned on center of char8
|
AboveR, // Left edge of mark aligned on center of char
|
||||||
AboveE, // Center of mark aligned on right edge of char8
|
AboveE, // Center of mark aligned on right edge of char
|
||||||
BelowC,
|
BelowC,
|
||||||
BelowR,
|
BelowR,
|
||||||
OverC,
|
OverC,
|
||||||
OverE,
|
OverE,
|
||||||
TopR, // Center of edge aligned to top of char8
|
TopR, // Center of edge aligned to top of char
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32 LOW_CHAR_COUNT = 128;
|
const int32 LOW_CHAR_COUNT = 128;
|
||||||
|
@ -171,16 +171,33 @@ namespace Beefy.gfx
|
||||||
{
|
{
|
||||||
if (valType == 1)
|
if (valType == 1)
|
||||||
{
|
{
|
||||||
String fontName = new String(&fontNameArr);
|
String fontName = scope String(&fontNameArr);
|
||||||
int parenPos = fontName.IndexOf(" (");
|
int parenPos = fontName.IndexOf(" (");
|
||||||
if (parenPos != -1)
|
if (parenPos != -1)
|
||||||
fontName.RemoveToEnd(parenPos);
|
fontName.RemoveToEnd(parenPos);
|
||||||
fontName.ToUpper();
|
fontName.ToUpper();
|
||||||
String fontPath = new String(&data);
|
String fontPath = scope String(&data);
|
||||||
if ((!fontPath.EndsWith(".TTF", .OrdinalIgnoreCase)) || (!sFontNameMap.TryAdd(fontName, fontPath)))
|
if ((!fontPath.EndsWith(".TTF", .OrdinalIgnoreCase)) && (!fontPath.EndsWith(".TTC", .OrdinalIgnoreCase)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fontName.Contains('&'))
|
||||||
{
|
{
|
||||||
delete fontName;
|
int collectionIdx = 0;
|
||||||
delete fontPath;
|
for (var namePart in fontName.Split('&', .RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
namePart.Trim();
|
||||||
|
if (sFontNameMap.TryAddAlt(namePart, var keyPtr, var valuePtr))
|
||||||
|
{
|
||||||
|
*keyPtr = new String(namePart);
|
||||||
|
*valuePtr = new $"{fontPath}@{collectionIdx}";
|
||||||
|
collectionIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sFontNameMap.TryAdd(fontName, var keyPtr, var valuePtr))
|
||||||
|
{
|
||||||
|
*keyPtr = new String(fontName);
|
||||||
|
*valuePtr = new String(fontPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -781,7 +798,7 @@ namespace Beefy.gfx
|
||||||
else if (newMatrix.tx > clipRect.mX + clipRect.mWidth)
|
else if (newMatrix.tx > clipRect.mX + clipRect.mWidth)
|
||||||
{
|
{
|
||||||
isFullyClipped = true;
|
isFullyClipped = true;
|
||||||
if ((newMatrix.a > 0) && (fontMetrics == null)) // Forward? If so, all future char8s will clip
|
if ((newMatrix.a > 0) && (fontMetrics == null)) // Forward? If so, all future chars will clip
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,11 @@ namespace Beefy.gfx
|
||||||
protected DisposeProxy mClipDisposeProxy ~ delete _;
|
protected DisposeProxy mClipDisposeProxy ~ delete _;
|
||||||
const int32 CLIP_STACK_SIZE = 256;
|
const int32 CLIP_STACK_SIZE = 256;
|
||||||
public Rect?[] mClipStack = new Rect?[CLIP_STACK_SIZE] ~ delete _;
|
public Rect?[] mClipStack = new Rect?[CLIP_STACK_SIZE] ~ delete _;
|
||||||
|
|
||||||
|
public bool mTexWrap;
|
||||||
|
protected DisposeProxy mTexWrapDisableProxy ~ delete _;
|
||||||
|
protected DisposeProxy mTexWrapEnableProxy ~ delete _;
|
||||||
|
|
||||||
public int32 mClipStackIdx = 0;
|
public int32 mClipStackIdx = 0;
|
||||||
public Rect? mClipRect = null;
|
public Rect? mClipRect = null;
|
||||||
|
|
||||||
|
@ -106,6 +110,10 @@ namespace Beefy.gfx
|
||||||
mClipDisposeProxy = new DisposeProxy();
|
mClipDisposeProxy = new DisposeProxy();
|
||||||
mClipDisposeProxy.mDisposeProxyDelegate = new => PopClip;
|
mClipDisposeProxy.mDisposeProxyDelegate = new => PopClip;
|
||||||
mRenderStateDisposeProxy = new DisposeProxy();
|
mRenderStateDisposeProxy = new DisposeProxy();
|
||||||
|
mTexWrapDisableProxy = new DisposeProxy();
|
||||||
|
mTexWrapDisableProxy.mDisposeProxyDelegate = new () => { PopTexWrap(false); };
|
||||||
|
mTexWrapEnableProxy = new DisposeProxy();
|
||||||
|
mTexWrapEnableProxy.mDisposeProxyDelegate = new () => { PopTexWrap(true); };
|
||||||
|
|
||||||
mWhiteDot = Image.LoadFromFile("!white");
|
mWhiteDot = Image.LoadFromFile("!white");
|
||||||
|
|
||||||
|
@ -341,15 +349,15 @@ namespace Beefy.gfx
|
||||||
Rect rectThing = mClipRect.Value;
|
Rect rectThing = mClipRect.Value;
|
||||||
mClipRect = rectThing;
|
mClipRect = rectThing;
|
||||||
|
|
||||||
var clipRenderState = AllocRenderState(mDefaultShader, mClipRect);
|
var clipRenderState = AllocRenderState(mDefaultShader, mClipRect, mTexWrap);
|
||||||
|
|
||||||
//clipRenderState.ClipRect = mClipRect;
|
//clipRenderState.ClipRect = mClipRect;
|
||||||
PushRenderState(clipRenderState);
|
PushRenderState(clipRenderState);
|
||||||
|
|
||||||
return mClipDisposeProxy;
|
return mClipDisposeProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderState AllocRenderState(Shader shader, Rect? clipRect)
|
RenderState AllocRenderState(Shader shader, Rect? clipRect, bool texWrap)
|
||||||
{
|
{
|
||||||
RenderState renderState = null;
|
RenderState renderState = null;
|
||||||
var curRenderState = mRenderStateStack[mRenderStateStackIdx];
|
var curRenderState = mRenderStateStack[mRenderStateStackIdx];
|
||||||
|
@ -365,6 +373,7 @@ namespace Beefy.gfx
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
renderState = RenderState.Create(curRenderState);
|
renderState = RenderState.Create(curRenderState);
|
||||||
|
renderState.TexWrap = texWrap;
|
||||||
renderState.Shader = shader;
|
renderState.Shader = shader;
|
||||||
renderState.ClipRect = clipRect;
|
renderState.ClipRect = clipRect;
|
||||||
return renderState;
|
return renderState;
|
||||||
|
@ -375,16 +384,33 @@ namespace Beefy.gfx
|
||||||
mClipStackIdx++;
|
mClipStackIdx++;
|
||||||
mClipStack[mClipStackIdx] = null;
|
mClipStack[mClipStackIdx] = null;
|
||||||
mClipRect = null;
|
mClipRect = null;
|
||||||
var clipRenderState = AllocRenderState(mDefaultShader, null);
|
var clipRenderState = AllocRenderState(mDefaultShader, mClipRect, mTexWrap);
|
||||||
//clipRenderState.ClipRect = null;
|
//clipRenderState.ClipRect = null;
|
||||||
PushRenderState(clipRenderState);
|
PushRenderState(clipRenderState);
|
||||||
|
|
||||||
return mClipDisposeProxy;
|
return mClipDisposeProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DisposeProxy PushTexWrap(bool texWrap)
|
||||||
|
{
|
||||||
|
bool prevTexWrap = mTexWrap;
|
||||||
|
mTexWrap = texWrap;
|
||||||
|
|
||||||
|
var clipRenderState = AllocRenderState(mDefaultShader, mClipRect, mTexWrap);
|
||||||
|
PushRenderState(clipRenderState);
|
||||||
|
|
||||||
|
return prevTexWrap ? mTexWrapEnableProxy : mTexWrapDisableProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void PopTexWrap(bool texWrap)
|
||||||
|
{
|
||||||
|
mTexWrap = texWrap;
|
||||||
|
PopRenderState();
|
||||||
|
}
|
||||||
|
|
||||||
public void PushTextRenderState()
|
public void PushTextRenderState()
|
||||||
{
|
{
|
||||||
var textRenderState = AllocRenderState(mTextShader, mClipRect);
|
var textRenderState = AllocRenderState(mTextShader, mClipRect, mTexWrap);
|
||||||
//textRenderState.ClipRect = mClipRect;
|
//textRenderState.ClipRect = mClipRect;
|
||||||
//textRenderState.Shader = mTextShader;
|
//textRenderState.Shader = mTextShader;
|
||||||
PushRenderState(textRenderState);
|
PushRenderState(textRenderState);
|
||||||
|
@ -416,13 +442,16 @@ namespace Beefy.gfx
|
||||||
//static unsafe extern void Gfx_DrawIndexedVertices2D(void* vtxData, int vtxCount, int* idxData, int idxCount, float a, float b, float c, float d, float tx, float ty, float z);
|
//static unsafe extern void Gfx_DrawIndexedVertices2D(void* vtxData, int vtxCount, int* idxData, int idxCount, float a, float b, float c, float d, float tx, float ty, float z);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void Gfx_DrawIndexedVertices2D(int32 vertexSize, void* vtxData, int32 vtxCount, uint16* idxData, int32 idxCount, float a, float b, float c, float d, float tx, float ty, float z);
|
static extern void Gfx_DrawIndexedVertices(int32 vertexSize, void* vtxData, int32 vtxCount, uint16* idxData, int32 idxCount);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
static extern void Gfx_DrawIndexedVertices2D(int32 vertexSize, void* vtxData, int32 vtxCount, uint16* idxData, int32 idxCount, float a, float b, float c, float d, float tx, float ty, float z);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void Gfx_SetShaderConstantData(int32 slotIdx, void* data, int32 size);
|
static extern void Gfx_SetShaderConstantData(int32 usageIdx, int32 slotIdx, void* data, int32 size);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void Gfx_SetShaderConstantDataTyped(int32 slotIdx, void* data, int32 size, int32* typeData, int32 typeCount);
|
static extern void Gfx_SetShaderConstantDataTyped(int usageIdx, int32 slotIdx, void* data, int32 size, int32* typeData, int32 typeCount);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void Gfx_DrawQuads(void* textureSegment, Vertex3D* vertices, int32 vtxCount);
|
static extern void Gfx_DrawQuads(void* textureSegment, Vertex3D* vertices, int32 vtxCount);
|
||||||
|
@ -768,32 +797,57 @@ namespace Beefy.gfx
|
||||||
|
|
||||||
public void DrawIndexedVertices(VertexDefinition vertexDef, void* vertices, int vtxCount, uint16[] indices)
|
public void DrawIndexedVertices(VertexDefinition vertexDef, void* vertices, int vtxCount, uint16[] indices)
|
||||||
{
|
{
|
||||||
Gfx_DrawIndexedVertices2D(vertexDef.mVertexSize, vertices, (int32)vtxCount, indices.CArray(), (int32)indices.Count,
|
if (vertexDef.mPosition2DOffset != -1)
|
||||||
mMatrix.a, mMatrix.b, mMatrix.c, mMatrix.d, mMatrix.tx, mMatrix.ty, ZDepth);
|
{
|
||||||
|
Gfx_DrawIndexedVertices2D(vertexDef.mVertexSize, vertices, (int32)vtxCount, indices.CArray(), (int32)indices.Count,
|
||||||
|
mMatrix.a, mMatrix.b, mMatrix.c, mMatrix.d, mMatrix.tx, mMatrix.ty, ZDepth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Gfx_DrawIndexedVertices(vertexDef.mVertexSize, vertices, (int32)vtxCount, indices.CArray(), (int32)indices.Count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawIndexedVertices(VertexDefinition vertexDef, void* vertices, int vtxCount, uint16* indices, int idxCount)
|
public void DrawIndexedVertices(VertexDefinition vertexDef, void* vertices, int vtxCount, uint16* indices, int idxCount)
|
||||||
{
|
{
|
||||||
Gfx_DrawIndexedVertices2D(vertexDef.mVertexSize, vertices, (int32)vtxCount, indices, (int32)idxCount,
|
if (vertexDef.mPosition2DOffset != -1)
|
||||||
mMatrix.a, mMatrix.b, mMatrix.c, mMatrix.d, mMatrix.tx, mMatrix.ty, ZDepth);
|
{
|
||||||
|
Gfx_DrawIndexedVertices2D(vertexDef.mVertexSize, vertices, (int32)vtxCount, indices, (int32)idxCount,
|
||||||
|
mMatrix.a, mMatrix.b, mMatrix.c, mMatrix.d, mMatrix.tx, mMatrix.ty, ZDepth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Gfx_DrawIndexedVertices(vertexDef.mVertexSize, vertices, (int32)vtxCount, indices, (int32)idxCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetShaderConstantData(int slotIdx, void* data, int size)
|
public void SetVertexShaderConstantData(int slotIdx, void* data, int size)
|
||||||
{
|
{
|
||||||
Gfx_SetShaderConstantData((int32)slotIdx, data, (int32)size);
|
Gfx_SetShaderConstantData(0, (int32)slotIdx, data, (int32)size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetShaderConstantData(int32 slotIdx, void* data, ConstantDataDefinition constantDataDefinition)
|
public void SetPixelShaderConstantData(int slotIdx, void* data, int size)
|
||||||
|
{
|
||||||
|
Gfx_SetShaderConstantData(1, (int32)slotIdx, data, (int32)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetVertexShaderConstantData(int32 slotIdx, void* data, ConstantDataDefinition constantDataDefinition)
|
||||||
{
|
{
|
||||||
int32* dataTypesPtr = (int32*)constantDataDefinition.mDataTypes.CArray();
|
int32* dataTypesPtr = (int32*)constantDataDefinition.mDataTypes.CArray();
|
||||||
Gfx_SetShaderConstantDataTyped(slotIdx, data, constantDataDefinition.mDataSize, dataTypesPtr, (int32)constantDataDefinition.mDataTypes.Count);
|
Gfx_SetShaderConstantDataTyped(0, slotIdx, data, constantDataDefinition.mDataSize, dataTypesPtr, (int32)constantDataDefinition.mDataTypes.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetShaderConstantData(int32 slotIdx, Matrix4 matrix)
|
public void SetVertexShaderConstantData(int32 slotIdx, Matrix4 matrix)
|
||||||
|
{
|
||||||
|
var mtx = matrix;
|
||||||
|
Gfx_SetShaderConstantData(0, slotIdx, &mtx, (int32)sizeof(Matrix4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPixelShaderConstantData(int32 slotIdx, Matrix4 matrix)
|
||||||
{
|
{
|
||||||
var mtx = matrix;
|
var mtx = matrix;
|
||||||
Gfx_SetShaderConstantData(slotIdx, &mtx, (int32)sizeof(Matrix4));
|
Gfx_SetShaderConstantData(1, slotIdx, &mtx, (int32)sizeof(Matrix4));
|
||||||
}
|
}
|
||||||
|
|
||||||
public float DrawString(StringView theString, float x, float y, FontAlign alignment = FontAlign.Left, float width = 0, FontOverflowMode overflowMode = FontOverflowMode.Overflow, FontMetrics* fontMetrics = null)
|
public float DrawString(StringView theString, float x, float y, FontAlign alignment = FontAlign.Left, float width = 0, FontOverflowMode overflowMode = FontOverflowMode.Overflow, FontMetrics* fontMetrics = null)
|
||||||
{
|
{
|
||||||
|
@ -811,12 +865,12 @@ namespace Beefy.gfx
|
||||||
float d = m.d * height;
|
float d = m.d * height;
|
||||||
|
|
||||||
Gfx_AllocTris(image.mNativeTextureSegment, 6);
|
Gfx_AllocTris(image.mNativeTextureSegment, 6);
|
||||||
Gfx_SetDrawVertex(0, m.tx, m.ty, 0, u1, 0, mColor);
|
Gfx_SetDrawVertex(0, m.tx, m.ty, 0, u1, v1, mColor);
|
||||||
Gfx_SetDrawVertex(1, m.tx + a, m.ty + b, 0, u2, 0, mColor);
|
Gfx_SetDrawVertex(1, m.tx + a, m.ty + b, 0, u2, v1, mColor);
|
||||||
Gfx_SetDrawVertex(2, m.tx + c, m.ty + d, 0, u1, 1, mColor);
|
Gfx_SetDrawVertex(2, m.tx + c, m.ty + d, 0, u1, v2, mColor);
|
||||||
Gfx_CopyDrawVertex(3, 2);
|
Gfx_CopyDrawVertex(3, 2);
|
||||||
Gfx_CopyDrawVertex(4, 1);
|
Gfx_CopyDrawVertex(4, 1);
|
||||||
Gfx_SetDrawVertex(5, m.tx + (a + c), m.ty + (b + d), 0, u2, 1, mColor);
|
Gfx_SetDrawVertex(5, m.tx + (a + c), m.ty + (b + d), 0, u2, v2, mColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Untranslated
|
// Untranslated
|
||||||
|
|
|
@ -210,6 +210,25 @@ namespace Beefy.gfx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Image[] CreateImageCels(int32 cols, int32 rows)
|
||||||
|
{
|
||||||
|
int32 celW = mSrcWidth / cols;
|
||||||
|
int32 celH = mSrcHeight / rows;
|
||||||
|
|
||||||
|
Debug.Assert(celW * cols == mSrcWidth);
|
||||||
|
Debug.Assert(celH * rows == mSrcHeight);
|
||||||
|
|
||||||
|
Image[] celImages = new .[cols * rows];
|
||||||
|
for (int32 row = 0; row < rows; row++)
|
||||||
|
{
|
||||||
|
for (int32 col = 0; col < cols; col++)
|
||||||
|
{
|
||||||
|
celImages[row * cols + col] = CreateImageSegment(col * celW, row * celH, celW, celH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return celImages;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public class Image : IDrawable
|
public class Image : IDrawable
|
||||||
|
|
|
@ -48,7 +48,13 @@ namespace Beefy.gfx
|
||||||
|
|
||||||
#if !STUDIO_CLIENT
|
#if !STUDIO_CLIENT
|
||||||
extension ModelDef
|
extension ModelDef
|
||||||
{
|
{
|
||||||
|
public enum ModelCreateFlags
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
NoSetRenderState = 1
|
||||||
|
}
|
||||||
|
|
||||||
public class Animation
|
public class Animation
|
||||||
{
|
{
|
||||||
public void* mNativeModelDefAnimation;
|
public void* mNativeModelDefAnimation;
|
||||||
|
@ -90,14 +96,32 @@ namespace Beefy.gfx
|
||||||
public void* mNativeModelDef;
|
public void* mNativeModelDef;
|
||||||
public float mFrameRate;
|
public float mFrameRate;
|
||||||
public int32 mJointCount;
|
public int32 mJointCount;
|
||||||
public Animation[] mAnims;
|
public Animation[] mAnims ~ DeleteContainerAndItems!(_);
|
||||||
public Dictionary<String, Animation> mAnimMap = new Dictionary<String, Animation>();
|
public Dictionary<String, Animation> mAnimMap = new Dictionary<String, Animation>() ~ DeleteDictionaryAndKeys!(_);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
extern static void* Res_OpenFBX(String fileName, void* nativeVertexDef);
|
extern static void* Res_OpenFBX(char8* fileName, void* nativeVertexDef);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static void* Res_OpenGLTF(char8* fileName, char8* baseDir, void* nativeVertexDef);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static void* Res_OpenModel(char8* fileName, char8* baseDir, void* nativeVertexDef);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
extern static void* ModelDef_CreateModelInstance(void* nativeModel);
|
extern static void* ModelDef_CreateModelInstance(void* nativeModel, ModelCreateFlags flags);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static void ModelDef_Compact(void* nativeModel);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static void ModelDef_SetBaseDir(void* nativeModel, char8* baseDir);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static char8* ModelDef_GetInfo(void* nativeModel);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static void ModelDef_GetBounds(void* nativeModel, out Vector3 min, out Vector3 max);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
extern static float ModelDef_GetFrameRate(void* nativeModel);
|
extern static float ModelDef_GetFrameRate(void* nativeModel);
|
||||||
|
@ -111,6 +135,15 @@ namespace Beefy.gfx
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
extern static void* ModelDef_GetAnimation(void* nativeModel, int32 animIdx);
|
extern static void* ModelDef_GetAnimation(void* nativeModel, int32 animIdx);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static void ModelDef_SetTextures(void* nativeModel, int32 meshIdx, int32 primitivesIdx, char8** paths, int32 pathCount);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static bool ModelDef_RayIntersect(void* nativeModel, Matrix4 worldMtx, Vector3 origin, Vector3 vec, out Vector3 outIntersect, out float outDistance);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static Span<uint8> Res_SerializeModel(void* nativeModel);
|
||||||
|
|
||||||
this(void* nativeModelDef)
|
this(void* nativeModelDef)
|
||||||
{
|
{
|
||||||
mNativeModelDef = nativeModelDef;
|
mNativeModelDef = nativeModelDef;
|
||||||
|
@ -129,17 +162,23 @@ namespace Beefy.gfx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ModelDef LoadModel(String fileName)
|
public static ModelDef LoadModel(String fileName, String baseDir)
|
||||||
{
|
{
|
||||||
void* nativeModelDef = Res_OpenFBX(fileName, VertexDef.sVertexDefinition.mNativeVertexDefinition);
|
void* nativeModelDef = null;
|
||||||
|
if (fileName.EndsWith(".gltf", .OrdinalIgnoreCase))
|
||||||
|
nativeModelDef = Res_OpenGLTF(fileName, baseDir, VertexDef.sVertexDefinition.mNativeVertexDefinition);
|
||||||
|
else if (fileName.EndsWith(".fbx", .OrdinalIgnoreCase))
|
||||||
|
nativeModelDef = Res_OpenFBX(fileName, VertexDef.sVertexDefinition.mNativeVertexDefinition);
|
||||||
|
else
|
||||||
|
nativeModelDef = Res_OpenModel(fileName, baseDir, VertexDef.sVertexDefinition.mNativeVertexDefinition);
|
||||||
if (nativeModelDef == null)
|
if (nativeModelDef == null)
|
||||||
return null;
|
return null;
|
||||||
return new ModelDef(nativeModelDef);
|
return new ModelDef(nativeModelDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelInstance CreateInstance()
|
public ModelInstance CreateInstance(ModelCreateFlags flags = .None)
|
||||||
{
|
{
|
||||||
void* nativeModelInstance = ModelDef_CreateModelInstance(mNativeModelDef);
|
void* nativeModelInstance = ModelDef_CreateModelInstance(mNativeModelDef, flags);
|
||||||
if (nativeModelInstance == null)
|
if (nativeModelInstance == null)
|
||||||
return null;
|
return null;
|
||||||
var modelInstance = new ModelInstance(nativeModelInstance, this);
|
var modelInstance = new ModelInstance(nativeModelInstance, this);
|
||||||
|
@ -150,6 +189,42 @@ namespace Beefy.gfx
|
||||||
{
|
{
|
||||||
return mAnimMap[name];
|
return mAnimMap[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GetInfo(String str)
|
||||||
|
{
|
||||||
|
str.Append(ModelDef_GetInfo(mNativeModelDef));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetBounds(out Vector3 min, out Vector3 max)
|
||||||
|
{
|
||||||
|
ModelDef_GetBounds(mNativeModelDef, out min, out max);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Compact()
|
||||||
|
{
|
||||||
|
ModelDef_Compact(mNativeModelDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBaseDir(StringView baseDir)
|
||||||
|
{
|
||||||
|
ModelDef_SetBaseDir(mNativeModelDef, baseDir.ToScopeCStr!());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTextures(int meshIdx, int primitivesIdx, Span<char8*> paths)
|
||||||
|
{
|
||||||
|
ModelDef_SetTextures(mNativeModelDef, (.)meshIdx, (.)primitivesIdx, paths.Ptr, (.)paths.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Serialize(List<uint8> data)
|
||||||
|
{
|
||||||
|
var span = Res_SerializeModel(mNativeModelDef);
|
||||||
|
data.AddRange(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RayIntersect(Matrix4 worldMtx, Vector3 origin, Vector3 vec, out Vector3 outIntersect, out float outDistance)
|
||||||
|
{
|
||||||
|
return ModelDef_RayIntersect(mNativeModelDef, worldMtx, origin, vec, out outIntersect, out outDistance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ModelInstance : RenderCmd
|
public class ModelInstance : RenderCmd
|
||||||
|
|
|
@ -19,6 +19,12 @@ namespace Beefy.gfx
|
||||||
Always
|
Always
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Topology
|
||||||
|
{
|
||||||
|
TriangleList,
|
||||||
|
LineList
|
||||||
|
}
|
||||||
|
|
||||||
#if !STUDIO_CLIENT
|
#if !STUDIO_CLIENT
|
||||||
public class RenderState
|
public class RenderState
|
||||||
{
|
{
|
||||||
|
@ -31,6 +37,12 @@ namespace Beefy.gfx
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void RenderState_SetClip(void* renderState, float x, float y, float width, float height);
|
static extern void RenderState_SetClip(void* renderState, float x, float y, float width, float height);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
static extern void RenderState_SetTexWrap(void* renderState, bool texWrap);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
static extern void RenderState_SetWireframe(void* renderState, bool wireframe);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void RenderState_DisableClip(void* renderState);
|
static extern void RenderState_DisableClip(void* renderState);
|
||||||
|
|
||||||
|
@ -43,6 +55,9 @@ namespace Beefy.gfx
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void RenderState_SetDepthWrite(void* nativeRenderState, int32 depthWrite);
|
static extern void RenderState_SetDepthWrite(void* nativeRenderState, int32 depthWrite);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
static extern void RenderState_SetTopology(void* nativeRenderState, int32 topology);
|
||||||
|
|
||||||
public void* mNativeRenderState;
|
public void* mNativeRenderState;
|
||||||
public bool mIsFromDefaultRenderState;
|
public bool mIsFromDefaultRenderState;
|
||||||
|
|
||||||
|
@ -103,7 +118,31 @@ namespace Beefy.gfx
|
||||||
else
|
else
|
||||||
RenderState_DisableClip(mNativeRenderState);
|
RenderState_DisableClip(mNativeRenderState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TexWrap
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
RenderState_SetTexWrap(mNativeRenderState, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Wireframe
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
RenderState_SetWireframe(mNativeRenderState, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Topology Topology
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
RenderState_SetTopology(mNativeRenderState, (.)value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public class RenderState
|
public class RenderState
|
||||||
|
|
|
@ -424,9 +424,9 @@ namespace Beefy.theme.dark
|
||||||
|
|
||||||
if (selEnd > selStart)
|
if (selEnd > selStart)
|
||||||
{
|
{
|
||||||
String selPrevString = scope String(selStart);
|
String selPrevString = new:ScopedAlloc! String(selStart);
|
||||||
selPrevString.Append(sectionText, 0, selStart);
|
selPrevString.Append(sectionText, 0, selStart);
|
||||||
String selIncludeString = scope String(selEnd);
|
String selIncludeString = new:ScopedAlloc! String(selEnd);
|
||||||
selIncludeString.Append(sectionText, 0, selEnd);
|
selIncludeString.Append(sectionText, 0, selEnd);
|
||||||
|
|
||||||
float selStartX = GetTabbedWidth(selPrevString, curX);
|
float selStartX = GetTabbedWidth(selPrevString, curX);
|
||||||
|
@ -473,7 +473,7 @@ namespace Beefy.theme.dark
|
||||||
|
|
||||||
if (isInside)
|
if (isInside)
|
||||||
{
|
{
|
||||||
String subText = scope String(mCursorTextPos - lineDrawStart);
|
String subText = new:ScopedAlloc! String(mCursorTextPos - lineDrawStart);
|
||||||
subText.Append(sectionText, 0, mCursorTextPos - lineDrawStart);
|
subText.Append(sectionText, 0, mCursorTextPos - lineDrawStart);
|
||||||
aX = GetTabbedWidth(subText, curX);
|
aX = GetTabbedWidth(subText, curX);
|
||||||
}
|
}
|
||||||
|
@ -587,7 +587,7 @@ namespace Beefy.theme.dark
|
||||||
|
|
||||||
if (char8Count < lineText.Length)
|
if (char8Count < lineText.Length)
|
||||||
{
|
{
|
||||||
String subString = scope String(char8Count);
|
String subString = new:ScopedAlloc! String(char8Count);
|
||||||
subString.Append(lineText, 0, char8Count);
|
subString.Append(lineText, 0, char8Count);
|
||||||
float subWidth = GetTabbedWidth(subString, 0);
|
float subWidth = GetTabbedWidth(subString, 0);
|
||||||
|
|
||||||
|
|
|
@ -398,12 +398,12 @@ namespace Beefy.theme.dark
|
||||||
func(mRightTab);
|
func(mRightTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override TabButton AddTab(String label, float width, Widget content, bool ownsContent)
|
public override TabButton AddTab(String label, float width, Widget content, bool ownsContent, int insertIdx)
|
||||||
{
|
{
|
||||||
float useWidth = width;
|
float useWidth = width;
|
||||||
if (useWidth == 0)
|
if (useWidth == 0)
|
||||||
useWidth = DarkTheme.sDarkTheme.mSmallFont.GetWidth(label) + GS!(30);
|
useWidth = DarkTheme.sDarkTheme.mSmallFont.GetWidth(label) + GS!(30);
|
||||||
return base.AddTab(label, useWidth, content, ownsContent);
|
return base.AddTab(label, useWidth, content, ownsContent, insertIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RemoveTab(TabButton tabButton, bool deleteTab = true)
|
public override void RemoveTab(TabButton tabButton, bool deleteTab = true)
|
||||||
|
|
54
BeefLibs/Beefy2D/src/utils/Compression.bf
Normal file
54
BeefLibs/Beefy2D/src/utils/Compression.bf
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
class Compression
|
||||||
|
{
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static bool Compression_Compress(void* ptr, int size, void** outPtr, int* outSize);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
extern static bool Compression_Decompress(void* ptr, int size, void** outPtr, int* outSize);
|
||||||
|
|
||||||
|
public static Result<void> Compress(Span<uint8> inData, List<uint8> outData)
|
||||||
|
{
|
||||||
|
void* outPtr = null;
|
||||||
|
int outSize = 0;
|
||||||
|
if (!Compression_Compress(inData.Ptr, inData.Length, &outPtr, &outSize))
|
||||||
|
return .Err;
|
||||||
|
outData.AddRange(.((.)outPtr, outSize));
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result<void> Compress(Span<uint8> inData, String outData)
|
||||||
|
{
|
||||||
|
void* outPtr = null;
|
||||||
|
int outSize = 0;
|
||||||
|
if (!Compression_Compress(inData.Ptr, inData.Length, &outPtr, &outSize))
|
||||||
|
return .Err;
|
||||||
|
outData.Insert(outData.Length, StringView((.)outPtr, outSize));
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result<void> Decompress(Span<uint8> inData, List<uint8> outData)
|
||||||
|
{
|
||||||
|
void* outPtr = null;
|
||||||
|
int outSize = 0;
|
||||||
|
if (!Compression_Decompress(inData.Ptr, inData.Length, &outPtr, &outSize))
|
||||||
|
return .Err;
|
||||||
|
outData.AddRange(.((.)outPtr, outSize));
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result<void> Decompress(Span<uint8> inData, String outData)
|
||||||
|
{
|
||||||
|
void* outPtr = null;
|
||||||
|
int outSize = 0;
|
||||||
|
if (!Compression_Decompress(inData.Ptr, inData.Length, &outPtr, &outSize))
|
||||||
|
return .Err;
|
||||||
|
outData.Insert(outData.Length, StringView((.)outPtr, outSize));
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -405,7 +405,7 @@ namespace Beefy.utils
|
||||||
return;
|
return;
|
||||||
switch (obj.GetType())
|
switch (obj.GetType())
|
||||||
{
|
{
|
||||||
case typeof(Int32): val = (int32)obj;
|
case typeof(Int64): val = (.)(int64)obj;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,7 @@ namespace Beefy.utils
|
||||||
return;
|
return;
|
||||||
switch (obj.GetType())
|
switch (obj.GetType())
|
||||||
{
|
{
|
||||||
case typeof(Int32): val = (int32)obj;
|
case typeof(Int64): val = (int64)obj;
|
||||||
case typeof(Float): val = (float)obj;
|
case typeof(Float): val = (float)obj;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -470,6 +470,7 @@ namespace Beefy.utils
|
||||||
Object val = Get(name);
|
Object val = Get(name);
|
||||||
|
|
||||||
outString.Clear();
|
outString.Clear();
|
||||||
|
|
||||||
if (val is uint64)
|
if (val is uint64)
|
||||||
val.ToString(outString);
|
val.ToString(outString);
|
||||||
|
|
||||||
|
@ -493,58 +494,112 @@ namespace Beefy.utils
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int32 GetInt(String name, int32 theDefault = 0)
|
public int32 GetInt(String name, int32 defaultVal = 0)
|
||||||
{
|
|
||||||
Object aVal = Get(name);
|
|
||||||
if ((aVal == null) || (!(aVal is int32)))
|
|
||||||
return theDefault;
|
|
||||||
return (int32)aVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int64 GetLong(String name, int64 theDefault = 0)
|
|
||||||
{
|
|
||||||
Object aVal = Get(name);
|
|
||||||
|
|
||||||
if (aVal is int32)
|
|
||||||
return (int64)(int32)aVal;
|
|
||||||
|
|
||||||
if ((aVal == null) || (!(aVal is int64)))
|
|
||||||
return theDefault;
|
|
||||||
return (int64)aVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint64 GetULong(String name, uint64 theDefault = 0)
|
|
||||||
{
|
|
||||||
Object aVal = Get(name);
|
|
||||||
|
|
||||||
if (aVal is int32)
|
|
||||||
return (uint64)(int32)aVal;
|
|
||||||
|
|
||||||
if ((aVal == null) || (!(aVal is uint64)))
|
|
||||||
return theDefault;
|
|
||||||
return (uint64)aVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float GetFloat(String name, float theDefault = 0)
|
|
||||||
{
|
{
|
||||||
Object val = Get(name);
|
Object val = Get(name);
|
||||||
if (val == null)
|
if (val == null)
|
||||||
return theDefault;
|
return defaultVal;
|
||||||
switch (val.GetType())
|
switch (val.GetType())
|
||||||
{
|
{
|
||||||
case typeof(Float): return (float)val;
|
case typeof(Float): return (.)(float)val;
|
||||||
case typeof(Int32): return (int32)val;
|
case typeof(Int32): return (.)(int32)val;
|
||||||
case typeof(Int): return (int)val;
|
case typeof(Int64): return (.)(int64)val;
|
||||||
default: return theDefault;
|
case typeof(Int): return (.)(int)val;
|
||||||
|
case typeof(String):
|
||||||
|
if (int32.Parse((String)val) case .Ok(var fVal))
|
||||||
|
return (.)fVal;
|
||||||
|
return defaultVal;
|
||||||
|
case typeof(StringView):
|
||||||
|
if (int32.Parse((StringView)val) case .Ok(var fVal))
|
||||||
|
return (.)fVal;
|
||||||
|
return defaultVal;
|
||||||
|
default: return defaultVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetBool(String name, bool theDefault = false)
|
public int64 GetLong(String name, int64 defaultVal = 0)
|
||||||
{
|
{
|
||||||
Object aVal = Get(name);
|
Object val = Get(name);
|
||||||
if ((aVal == null) || (!(aVal is bool)))
|
if (val == null)
|
||||||
return theDefault;
|
return defaultVal;
|
||||||
return (bool)aVal;
|
switch (val.GetType())
|
||||||
|
{
|
||||||
|
case typeof(Float): return (.)(float)val;
|
||||||
|
case typeof(Int32): return (.)(int32)val;
|
||||||
|
case typeof(Int64): return (.)(int64)val;
|
||||||
|
case typeof(Int): return (.)(int)val;
|
||||||
|
case typeof(String):
|
||||||
|
if (int64.Parse((String)val) case .Ok(var parsedVal))
|
||||||
|
return (.)parsedVal;
|
||||||
|
return defaultVal;
|
||||||
|
case typeof(StringView):
|
||||||
|
if (int64.Parse((StringView)val) case .Ok(var parsedVal))
|
||||||
|
return (.)parsedVal;
|
||||||
|
return defaultVal;
|
||||||
|
default: return defaultVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint64 GetULong(String name, uint64 defaultVal = 0)
|
||||||
|
{
|
||||||
|
Object val = Get(name);
|
||||||
|
if (val == null)
|
||||||
|
return defaultVal;
|
||||||
|
switch (val.GetType())
|
||||||
|
{
|
||||||
|
case typeof(Float): return (.)(float)val;
|
||||||
|
case typeof(Int32): return (.)(int32)val;
|
||||||
|
case typeof(Int64): return (.)(int64)val;
|
||||||
|
case typeof(Int): return (.)(int)val;
|
||||||
|
case typeof(String):
|
||||||
|
if (int64.Parse((String)val) case .Ok(var parsedVal))
|
||||||
|
return (.)parsedVal;
|
||||||
|
return defaultVal;
|
||||||
|
case typeof(StringView):
|
||||||
|
if (int64.Parse((StringView)val) case .Ok(var parsedVal))
|
||||||
|
return (.)parsedVal;
|
||||||
|
return defaultVal;
|
||||||
|
default: return defaultVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetFloat(String name, float defaultVal = 0)
|
||||||
|
{
|
||||||
|
Object val = Get(name);
|
||||||
|
if (val == null)
|
||||||
|
return defaultVal;
|
||||||
|
switch (val.GetType())
|
||||||
|
{
|
||||||
|
case typeof(Float): return (.)(float)val;
|
||||||
|
case typeof(Int32): return (.)(int32)val;
|
||||||
|
case typeof(Int64): return (.)(int64)val;
|
||||||
|
case typeof(Int): return (.)(int)val;
|
||||||
|
case typeof(String):
|
||||||
|
if (float.Parse((String)val) case .Ok(var parsedVal))
|
||||||
|
return parsedVal;
|
||||||
|
return defaultVal;
|
||||||
|
case typeof(StringView):
|
||||||
|
if (float.Parse((StringView)val) case .Ok(var parsedVal))
|
||||||
|
return parsedVal;
|
||||||
|
return defaultVal;
|
||||||
|
default: return defaultVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetBool(String name, bool defaultVal = false)
|
||||||
|
{
|
||||||
|
Object val = Get(name);
|
||||||
|
if (val == null)
|
||||||
|
return defaultVal;
|
||||||
|
switch (val.GetType())
|
||||||
|
{
|
||||||
|
case typeof(Boolean): return (bool)val;
|
||||||
|
case typeof(String):
|
||||||
|
if (bool.Parse((String)val) case .Ok(var parsedVal))
|
||||||
|
return (.)parsedVal;
|
||||||
|
return defaultVal;
|
||||||
|
default: return defaultVal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetEnum<T>(String name, T defaultVal = default(T)) where T : enum
|
public T GetEnum<T>(String name, T defaultVal = default(T)) where T : enum
|
||||||
|
@ -634,9 +689,9 @@ namespace Beefy.utils
|
||||||
public int32 GetCurInt(int32 theDefault = 0)
|
public int32 GetCurInt(int32 theDefault = 0)
|
||||||
{
|
{
|
||||||
Object aVal = GetCurrent();
|
Object aVal = GetCurrent();
|
||||||
if ((aVal == null) || (!(aVal is int32)))
|
if ((aVal == null) || (!(aVal is int64)))
|
||||||
return theDefault;
|
return theDefault;
|
||||||
return (int32)aVal;
|
return (.)(int64)aVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint32 GetCurUInt(uint32 theDefault = 0)
|
public uint32 GetCurUInt(uint32 theDefault = 0)
|
||||||
|
@ -1786,7 +1841,7 @@ namespace Beefy.utils
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var parseVal = int32.Parse(strView);
|
var parseVal = int64.Parse(strView);
|
||||||
if (parseVal case .Ok(var intVal))
|
if (parseVal case .Ok(var intVal))
|
||||||
aValue = new:mBumpAllocator box intVal;
|
aValue = new:mBumpAllocator box intVal;
|
||||||
else
|
else
|
||||||
|
@ -2187,7 +2242,7 @@ namespace Beefy.utils
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Int32.Parse(value))
|
switch (Int64.Parse(value))
|
||||||
{
|
{
|
||||||
case .Err: return null;
|
case .Err: return null;
|
||||||
case .Ok(let num): return new:mBumpAllocator box num;
|
case .Ok(let num): return new:mBumpAllocator box num;
|
||||||
|
@ -2344,6 +2399,223 @@ namespace Beefy.utils
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<void, Error> LoadXMLHelper(String contentStr, Values values, ref int32 idx, ref int32 lineNum)
|
||||||
|
{
|
||||||
|
LoadSection loadRoot = scope LoadSection();
|
||||||
|
loadRoot.mSectionDict = new Dictionary<String, LoadSection>();
|
||||||
|
loadRoot.mCurrentEntry = CurrentEntry(values);
|
||||||
|
//LoadSection loadSection = loadRoot;
|
||||||
|
//CurrentEntry currentEntry = default;
|
||||||
|
|
||||||
|
char8* cPtr = contentStr.CStr();
|
||||||
|
|
||||||
|
char8 NextChar()
|
||||||
|
{
|
||||||
|
char8 c = cPtr[idx];
|
||||||
|
if (c != 0)
|
||||||
|
idx++;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
char8* GetCharPtr()
|
||||||
|
{
|
||||||
|
return &cPtr[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
char8 PeekNextChar()
|
||||||
|
{
|
||||||
|
return cPtr[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
void EatWhiteSpace()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char8 nextC = PeekNextChar();
|
||||||
|
if ((nextC != ' ') && (nextC != '\t'))
|
||||||
|
return;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadSection(ref CurrentEntry arrayEntry)
|
||||||
|
{
|
||||||
|
char8* dataStart = null;
|
||||||
|
|
||||||
|
void FlushData()
|
||||||
|
{
|
||||||
|
if (dataStart != null)
|
||||||
|
{
|
||||||
|
StringView valueSV = StringView(dataStart, GetCharPtr() - dataStart - 1);
|
||||||
|
valueSV.Trim();
|
||||||
|
String value = new:mBumpAllocator String(valueSV);
|
||||||
|
DoAdd(ref arrayEntry, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStart = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLoop: while (true)
|
||||||
|
{
|
||||||
|
char8 c = NextChar();
|
||||||
|
if (c == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '<')
|
||||||
|
{
|
||||||
|
FlushData();
|
||||||
|
|
||||||
|
EatWhiteSpace();
|
||||||
|
c = PeekNextChar();
|
||||||
|
if (c == '/')
|
||||||
|
{
|
||||||
|
// Is closing
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
c = NextChar();
|
||||||
|
if ((c == 0) || (c == '>'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedValues childNamedValues = null;
|
||||||
|
CurrentEntry childTableEntry = default;
|
||||||
|
|
||||||
|
void EnsureChildEntry()
|
||||||
|
{
|
||||||
|
if (childNamedValues != null)
|
||||||
|
return;
|
||||||
|
childNamedValues = new:mBumpAllocator NamedValues();
|
||||||
|
childTableEntry = CurrentEntry(childNamedValues);
|
||||||
|
DoAdd(ref arrayEntry, childNamedValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
char8* namePtr = null;
|
||||||
|
char8* nameEndPtr = null;
|
||||||
|
char8* equalPtr = null;
|
||||||
|
char8* valuePtr = null;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
c = NextChar();
|
||||||
|
if (c.IsWhiteSpace)
|
||||||
|
{
|
||||||
|
if ((namePtr != null) && (nameEndPtr == null))
|
||||||
|
nameEndPtr = GetCharPtr() - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valuePtr != null)
|
||||||
|
{
|
||||||
|
if (c == '"')
|
||||||
|
{
|
||||||
|
EnsureChildEntry();
|
||||||
|
StringView name = StringView(namePtr, nameEndPtr - namePtr + 1);
|
||||||
|
name.Trim();
|
||||||
|
StringView valueSV = StringView(valuePtr, GetCharPtr() - valuePtr - 1);
|
||||||
|
String value = new:mBumpAllocator String(valueSV);
|
||||||
|
DoAdd(ref childTableEntry, name, value);
|
||||||
|
|
||||||
|
namePtr = null;
|
||||||
|
nameEndPtr = null;
|
||||||
|
equalPtr = null;
|
||||||
|
valuePtr = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((c == '?') || (c == '/'))
|
||||||
|
{
|
||||||
|
// Wait for close. Not nested.
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
c = NextChar();
|
||||||
|
if ((c == 0) || (c == '>'))
|
||||||
|
continue MainLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '>')
|
||||||
|
{
|
||||||
|
// Closing, but we're nested
|
||||||
|
EnsureChildEntry();
|
||||||
|
Values childArrayValues = new:mBumpAllocator Values();
|
||||||
|
CurrentEntry childArrayEntry = CurrentEntry(childArrayValues);
|
||||||
|
DoAdd(ref childTableEntry, ".", childArrayValues);
|
||||||
|
|
||||||
|
ReadSection(ref childArrayEntry);
|
||||||
|
continue MainLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (namePtr == null)
|
||||||
|
{
|
||||||
|
namePtr = GetCharPtr() - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (equalPtr == null)
|
||||||
|
{
|
||||||
|
if (c == '=')
|
||||||
|
{
|
||||||
|
equalPtr = GetCharPtr() - 1;
|
||||||
|
if (nameEndPtr == null)
|
||||||
|
nameEndPtr = equalPtr - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (c == '"')
|
||||||
|
{
|
||||||
|
valuePtr = GetCharPtr();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nameEndPtr == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Flush
|
||||||
|
StringView name = StringView(namePtr, nameEndPtr - namePtr + 1);
|
||||||
|
name.Trim();
|
||||||
|
|
||||||
|
if (name.IsEmpty)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
EnsureChildEntry();
|
||||||
|
if (childTableEntry.mLastKey == -1)
|
||||||
|
{
|
||||||
|
Object value = new:mBumpAllocator String(name);
|
||||||
|
DoAdd(ref childTableEntry, "", value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Object value = new:mBumpAllocator box true;
|
||||||
|
DoAdd(ref childTableEntry, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
namePtr = null;
|
||||||
|
nameEndPtr = null;
|
||||||
|
idx--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!c.IsWhiteSpace) && (dataStart == null))
|
||||||
|
dataStart = GetCharPtr() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlushData();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadSection(ref loadRoot.mCurrentEntry);
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
protected Result<void, Error> Load()
|
protected Result<void, Error> Load()
|
||||||
{
|
{
|
||||||
EnsureHasData();
|
EnsureHasData();
|
||||||
|
@ -2354,13 +2626,34 @@ namespace Beefy.utils
|
||||||
mNextKeys.Reserve(guessItems);
|
mNextKeys.Reserve(guessItems);
|
||||||
|
|
||||||
bool isJson = false;
|
bool isJson = false;
|
||||||
|
bool isXml = false;
|
||||||
|
bool mayBeJsonArray = false;
|
||||||
for (char8 c in mSource.RawChars)
|
for (char8 c in mSource.RawChars)
|
||||||
{
|
{
|
||||||
if (c.IsWhiteSpace)
|
if (c.IsWhiteSpace)
|
||||||
continue;
|
continue;
|
||||||
if (c == '{')
|
|
||||||
isJson = true;
|
if (mayBeJsonArray)
|
||||||
break;
|
{
|
||||||
|
if (c == '[')
|
||||||
|
continue; // Still ambiguous
|
||||||
|
if ((c == '{') || (c == '"'))
|
||||||
|
isJson = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (c == '{')
|
||||||
|
isJson = true;
|
||||||
|
if (c == '<')
|
||||||
|
isXml = true;
|
||||||
|
if (c == '[')
|
||||||
|
{
|
||||||
|
mayBeJsonArray = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 aLineNum = 1;
|
int32 aLineNum = 1;
|
||||||
|
@ -2373,6 +2666,14 @@ namespace Beefy.utils
|
||||||
return .Err(err);
|
return .Err(err);
|
||||||
objResult = result.Get();
|
objResult = result.Get();
|
||||||
}
|
}
|
||||||
|
else if (isXml)
|
||||||
|
{
|
||||||
|
var values = new:mBumpAllocator Values();
|
||||||
|
let result = LoadXMLHelper(mSource, values, ref anIdx, ref aLineNum);
|
||||||
|
if (result case .Err(var err))
|
||||||
|
return .Err(err);
|
||||||
|
objResult = values;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var values = new:mBumpAllocator NamedValues();
|
var values = new:mBumpAllocator NamedValues();
|
||||||
|
|
|
@ -459,7 +459,7 @@ namespace Beefy.widgets
|
||||||
public UndoManager mUndoManager = new UndoManager() ~ delete _;
|
public UndoManager mUndoManager = new UndoManager() ~ delete _;
|
||||||
public int32 mNextCharId = 1; //
|
public int32 mNextCharId = 1; //
|
||||||
public int32 mCurTextVersionId = 1; // Changes when text is modified
|
public int32 mCurTextVersionId = 1; // Changes when text is modified
|
||||||
//public int mCurComplexChangeId = 1; // Changes when text is modified by more than a single-char8acter insertion or deletion
|
//public int mCurComplexChangeId = 1; // Changes when text is modified by more than a single-character insertion or deletion
|
||||||
|
|
||||||
public List<EditWidgetContent> mUsers = new List<EditWidgetContent>() ~ delete _;
|
public List<EditWidgetContent> mUsers = new List<EditWidgetContent>() ~ delete _;
|
||||||
|
|
||||||
|
@ -1985,6 +1985,9 @@ namespace Beefy.widgets
|
||||||
{
|
{
|
||||||
scope AutoBeefPerf("EWC.Undo");
|
scope AutoBeefPerf("EWC.Undo");
|
||||||
|
|
||||||
|
if (CheckReadOnly())
|
||||||
|
return;
|
||||||
|
|
||||||
//Profiler.StartSampling();
|
//Profiler.StartSampling();
|
||||||
if (WantsUndo)
|
if (WantsUndo)
|
||||||
mData.mUndoManager.Undo();
|
mData.mUndoManager.Undo();
|
||||||
|
@ -1995,6 +1998,9 @@ namespace Beefy.widgets
|
||||||
{
|
{
|
||||||
scope AutoBeefPerf("EWC.Redo");
|
scope AutoBeefPerf("EWC.Redo");
|
||||||
|
|
||||||
|
if (CheckReadOnly())
|
||||||
|
return;
|
||||||
|
|
||||||
if (WantsUndo)
|
if (WantsUndo)
|
||||||
mData.mUndoManager.Redo();
|
mData.mUndoManager.Redo();
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,8 @@ namespace Beefy.widgets
|
||||||
F12 = 0x7B,
|
F12 = 0x7B,
|
||||||
Numlock = 0x90,
|
Numlock = 0x90,
|
||||||
Scroll = 0x91,
|
Scroll = 0x91,
|
||||||
|
RAlt = 0xA5,
|
||||||
|
RMenu = 0xA5,
|
||||||
Semicolon = 0xBA,
|
Semicolon = 0xBA,
|
||||||
Equals = 0xBB,
|
Equals = 0xBB,
|
||||||
Comma = 0xBC,
|
Comma = 0xBC,
|
||||||
|
|
|
@ -339,7 +339,7 @@ namespace Beefy.widgets
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (item.Selected)
|
if ((item.Selected) && (item.mMouseOver))
|
||||||
{
|
{
|
||||||
item.mOnMouseUp.AddFront(new => ItemMouseUpHandler);
|
item.mOnMouseUp.AddFront(new => ItemMouseUpHandler);
|
||||||
|
|
||||||
|
|
|
@ -103,13 +103,13 @@ namespace Beefy.widgets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HorzScrollTo(double horzPos)
|
public bool HorzScrollTo(double horzPos, bool immediate = false)
|
||||||
{
|
{
|
||||||
double aHorzPos = Math.Max(0, Math.Min(horzPos, mScrollContent.mWidth - mScrollContentContainer.mWidth));
|
double aHorzPos = Math.Max(0, Math.Min(horzPos, mScrollContent.mWidth - mScrollContentContainer.mWidth));
|
||||||
if (aHorzPos == mHorzPos.mDest)
|
if (aHorzPos == mHorzPos.mDest)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mHorzPos.Set(aHorzPos);
|
mHorzPos.Set(aHorzPos, immediate);
|
||||||
if (mHorzScrollbar != null)
|
if (mHorzScrollbar != null)
|
||||||
{
|
{
|
||||||
mHorzScrollbar.mContentPos = mHorzPos.v;
|
mHorzScrollbar.mContentPos = mHorzPos.v;
|
||||||
|
|
|
@ -162,7 +162,7 @@ namespace Beefy.widgets
|
||||||
if ((mSrcDraggingWindow != null) && (mSrcDraggingWindow.mCaptureWidget != null))
|
if ((mSrcDraggingWindow != null) && (mSrcDraggingWindow.mCaptureWidget != null))
|
||||||
mSrcDraggingWindow.ReleaseMouseCaptures();
|
mSrcDraggingWindow.ReleaseMouseCaptures();
|
||||||
|
|
||||||
mTabbedView.mParentDockingFrame.GetRootDockingFrame().HideDragTarget(this, !mDragHelper.mAborted);
|
mTabbedView.mParentDockingFrame?.GetRootDockingFrame().HideDragTarget(this, !mDragHelper.mAborted);
|
||||||
if (mNewDraggingWindow != null)
|
if (mNewDraggingWindow != null)
|
||||||
{
|
{
|
||||||
mNewDraggingWindow.mOnWindowLostFocus.Remove(scope => WindowDragLostFocusHandler, true);
|
mNewDraggingWindow.mOnWindowLostFocus.Remove(scope => WindowDragLostFocusHandler, true);
|
||||||
|
@ -176,7 +176,7 @@ namespace Beefy.widgets
|
||||||
|
|
||||||
public void MouseDrag(float x, float y, float dX, float dY)
|
public void MouseDrag(float x, float y, float dX, float dY)
|
||||||
{
|
{
|
||||||
mTabbedView.mParentDockingFrame.GetRootDockingFrame().ShowDragTarget(this);
|
mTabbedView.mParentDockingFrame?.GetRootDockingFrame().ShowDragTarget(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MouseUp(float x, float y, int32 btn)
|
public override void MouseUp(float x, float y, int32 btn)
|
||||||
|
@ -198,6 +198,8 @@ namespace Beefy.widgets
|
||||||
|
|
||||||
public virtual bool IsTotalWindowContent()
|
public virtual bool IsTotalWindowContent()
|
||||||
{
|
{
|
||||||
|
if (mTabbedView.mParentDockingFrame == null)
|
||||||
|
return false;
|
||||||
return (mTabbedView.mParentDockingFrame.mParentDockingFrame == null) &&
|
return (mTabbedView.mParentDockingFrame.mParentDockingFrame == null) &&
|
||||||
(mTabbedView.mParentDockingFrame.GetDockedWindowCount() == 1) &&
|
(mTabbedView.mParentDockingFrame.GetDockedWindowCount() == 1) &&
|
||||||
(mTabbedView.GetTabCount() == 1) &&
|
(mTabbedView.GetTabCount() == 1) &&
|
||||||
|
@ -318,7 +320,7 @@ namespace Beefy.widgets
|
||||||
//tabbedView.mSharedData.mOpenNewWindowDelegate = mTabbedView.mSharedData.mOpenNewWindowDelegate;
|
//tabbedView.mSharedData.mOpenNewWindowDelegate = mTabbedView.mSharedData.mOpenNewWindowDelegate;
|
||||||
tabbedView.SetRequestedSize(mTabbedView.mWidth, mTabbedView.mHeight);
|
tabbedView.SetRequestedSize(mTabbedView.mWidth, mTabbedView.mHeight);
|
||||||
mTabbedView.RemoveTab(this, false);
|
mTabbedView.RemoveTab(this, false);
|
||||||
tabbedView.AddTab(this);
|
tabbedView.AddTab(this, 0);
|
||||||
|
|
||||||
float rootX;
|
float rootX;
|
||||||
float rootY;
|
float rootY;
|
||||||
|
@ -470,7 +472,7 @@ namespace Beefy.widgets
|
||||||
return activeTab;
|
return activeTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual TabButton AddTab(String label, float width, Widget content, bool ownsContent)
|
public virtual TabButton AddTab(String label, float width, Widget content, bool ownsContent, int insertIdx)
|
||||||
{
|
{
|
||||||
TabButton aTabButton = CreateTabButton();
|
TabButton aTabButton = CreateTabButton();
|
||||||
aTabButton.mTabbedView = this;
|
aTabButton.mTabbedView = this;
|
||||||
|
@ -479,7 +481,7 @@ namespace Beefy.widgets
|
||||||
aTabButton.mWantWidth = width;
|
aTabButton.mWantWidth = width;
|
||||||
aTabButton.mHeight = mTabHeight;
|
aTabButton.mHeight = mTabHeight;
|
||||||
aTabButton.mContent = content;
|
aTabButton.mContent = content;
|
||||||
AddTab(aTabButton);
|
AddTab(aTabButton, insertIdx);
|
||||||
return aTabButton;
|
return aTabButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +501,7 @@ namespace Beefy.widgets
|
||||||
return bestIdx;
|
return bestIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void AddTab(TabButton tabButton, int insertIdx = 0)
|
public virtual void AddTab(TabButton tabButton, int insertIdx)
|
||||||
{
|
{
|
||||||
AddWidget(tabButton);
|
AddWidget(tabButton);
|
||||||
mTabs.Insert(insertIdx, tabButton);
|
mTabs.Insert(insertIdx, tabButton);
|
||||||
|
|
|
@ -121,7 +121,7 @@ namespace Beefy.widgets
|
||||||
KeyFlags keyFlags = default;
|
KeyFlags keyFlags = default;
|
||||||
if (IsKeyDown(KeyCode.Shift))
|
if (IsKeyDown(KeyCode.Shift))
|
||||||
keyFlags |= KeyFlags.Shift;
|
keyFlags |= KeyFlags.Shift;
|
||||||
if (IsKeyDown(KeyCode.Control))
|
if ((IsKeyDown(KeyCode.Control)) && (!IsKeyDown(KeyCode.RAlt)))
|
||||||
keyFlags |= KeyFlags.Ctrl;
|
keyFlags |= KeyFlags.Ctrl;
|
||||||
if (IsKeyDown(KeyCode.Menu))
|
if (IsKeyDown(KeyCode.Menu))
|
||||||
keyFlags |= KeyFlags.Alt;
|
keyFlags |= KeyFlags.Alt;
|
||||||
|
@ -137,7 +137,7 @@ namespace Beefy.widgets
|
||||||
{
|
{
|
||||||
if (mRootWidget == null)
|
if (mRootWidget == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
base.Draw(g);
|
base.Draw(g);
|
||||||
mRootWidget.DrawAll(g);
|
mRootWidget.DrawAll(g);
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,7 +192,8 @@ namespace SDL2
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int32 channel = SDLMixer.PlayChannel(-1, sound.mChunk, 0);
|
int32 channel = SDLMixer.PlayChannel(-1, sound.mChunk, 0);
|
||||||
//SDLMixer.SetPanning()
|
if (channel < 0)
|
||||||
|
return;
|
||||||
SDLMixer.Volume(channel, (int32)(volume * 128));
|
SDLMixer.Volume(channel, (int32)(volume * 128));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,8 @@ namespace System
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEmpty
|
public bool IsEmpty
|
||||||
{
|
{
|
||||||
|
[Inline]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return mLength == 0;
|
return mLength == 0;
|
||||||
|
@ -259,6 +260,46 @@ namespace System
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref T this[Index index]
|
||||||
|
{
|
||||||
|
[Checked, Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
if ((uint)idx >= (uint)mLength)
|
||||||
|
Internal.ThrowIndexOutOfRange(1);
|
||||||
|
return ref (&mFirstElement)[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
return ref (&mFirstElement)[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Span<T> this[IndexRange range]
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
[Inline]
|
||||||
|
#endif
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Span<T>(&mFirstElement, mLength)[range];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Inline]
|
[Inline]
|
||||||
public T* CArray()
|
public T* CArray()
|
||||||
{
|
{
|
||||||
|
@ -276,7 +317,7 @@ namespace System
|
||||||
Debug.Assert(length >= 0);
|
Debug.Assert(length >= 0);
|
||||||
Debug.Assert((uint)srcOffset + (uint)length <= (uint)mLength);
|
Debug.Assert((uint)srcOffset + (uint)length <= (uint)mLength);
|
||||||
Debug.Assert((uint)dstOffset + (uint)length <= (uint)arrayTo.mLength);
|
Debug.Assert((uint)dstOffset + (uint)length <= (uint)arrayTo.mLength);
|
||||||
Internal.MemCpy(&arrayTo.GetRef(dstOffset), &GetRef(srcOffset), strideof(T) * length, alignof(T));
|
Internal.MemMove(&arrayTo.GetRef(dstOffset), &GetRef(srcOffset), strideof(T) * length, alignof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo<T2>(T2[] arrayTo, int srcOffset, int dstOffset, int length) where T2 : operator explicit T
|
public void CopyTo<T2>(T2[] arrayTo, int srcOffset, int dstOffset, int length) where T2 : operator explicit T
|
||||||
|
@ -299,17 +340,18 @@ namespace System
|
||||||
public void CopyTo(Span<T> destination)
|
public void CopyTo(Span<T> destination)
|
||||||
{
|
{
|
||||||
Debug.Assert(destination.[Friend]mLength >= mLength);
|
Debug.Assert(destination.[Friend]mLength >= mLength);
|
||||||
Internal.MemCpy(destination.Ptr, &GetRef(0), strideof(T) * mLength, alignof(T));
|
Internal.MemMove(destination.Ptr, &GetRef(0), strideof(T) * mLength, alignof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(Span<T> destination, int srcOffset)
|
public void CopyTo(Span<T> destination, int srcOffset)
|
||||||
{
|
{
|
||||||
Debug.Assert((uint)srcOffset + (uint)destination.[Friend]mLength <= (uint)mLength);
|
Debug.Assert((uint)srcOffset + (uint)destination.[Friend]mLength <= (uint)mLength);
|
||||||
Internal.MemCpy(destination.Ptr, &GetRef(srcOffset), strideof(T) * (destination.[Friend]mLength - srcOffset), alignof(T));
|
Internal.MemMove(destination.Ptr, &GetRef(srcOffset), strideof(T) * (destination.[Friend]mLength - srcOffset), alignof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo<T2>(Span<T2> destination, int srcOffset) where T2 : operator explicit T
|
public void CopyTo<T2>(Span<T2> destination, int srcOffset) where T2 : operator explicit T
|
||||||
{
|
{
|
||||||
|
//TODO: Handle src/dest overlap (MemMove)
|
||||||
Debug.Assert((uint)srcOffset + (uint)destination.[Friend]mLength <= (uint)mLength);
|
Debug.Assert((uint)srcOffset + (uint)destination.[Friend]mLength <= (uint)mLength);
|
||||||
var ptr = destination.[Friend]mPtr;
|
var ptr = destination.[Friend]mPtr;
|
||||||
for (int i = 0; i < destination.[Friend]mLength; i++)
|
for (int i = 0; i < destination.[Friend]mLength; i++)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace System
|
namespace System
|
||||||
{
|
{
|
||||||
struct Char16 : char16, IHashable, IIsNaN
|
struct Char16 : char16, ICharacter, IHashable, IIsNaN
|
||||||
{
|
{
|
||||||
const int UNICODE_PLANE00_END = 0x00ffff;
|
const int UNICODE_PLANE00_END = 0x00ffff;
|
||||||
// The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.
|
// The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace System
|
namespace System
|
||||||
{
|
{
|
||||||
struct Char32 : char32, IHashable, IIsNaN
|
struct Char32 : char32, ICharacter, IHashable, IIsNaN
|
||||||
{
|
{
|
||||||
public int GetHashCode()
|
public int GetHashCode()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
namespace System
|
namespace System
|
||||||
{
|
{
|
||||||
#unwarn
|
#unwarn
|
||||||
struct Char8 : char8, IHashable, IIsNaN
|
struct Char8 : char8, ICharacter, IHashable, IIsNaN
|
||||||
{
|
{
|
||||||
bool IIsNaN.IsNaN
|
bool IIsNaN.IsNaN
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace System.Collections
|
||||||
{
|
{
|
||||||
public TKey mKey; // Key of entry
|
public TKey mKey; // Key of entry
|
||||||
public TValue mValue; // Value of entry
|
public TValue mValue; // Value of entry
|
||||||
public int32 mHashCode; // Lower 31 bits of hash code, -1 if unused
|
public int_cosize mHashCode; // some bits of hash code, -1 if unused
|
||||||
public int_cosize mNext; // Index of next entry, -1 if last
|
public int_cosize mNext; // Index of next entry, -1 if last
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ namespace System.Collections
|
||||||
Entry* mEntries;
|
Entry* mEntries;
|
||||||
int_cosize mAllocSize;
|
int_cosize mAllocSize;
|
||||||
int_cosize mCount;
|
int_cosize mCount;
|
||||||
int_cosize mFreeList;
|
int_cosize mFreeList;
|
||||||
int_cosize mFreeCount;
|
int_cosize mFreeCount;
|
||||||
#if VERSION_DICTIONARY
|
#if VERSION_DICTIONARY
|
||||||
private int32 mVersion;
|
private int32 mVersion;
|
||||||
|
@ -258,21 +258,9 @@ namespace System.Collections
|
||||||
|
|
||||||
public bool ContainsValue(TValue value)
|
public bool ContainsValue(TValue value)
|
||||||
{
|
{
|
||||||
if (value == null)
|
for (int_cosize i = 0; i < mCount; i++)
|
||||||
{
|
{
|
||||||
for (int_cosize i = 0; i < mCount; i++)
|
if (mEntries[i].mHashCode >= 0 && mEntries[i].mValue == value) return true;
|
||||||
{
|
|
||||||
if (mEntries[i].mHashCode >= 0 && mEntries[i].mValue == null) return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//TODO: IMPORTANT!
|
|
||||||
/*EqualityComparer<TValue> c = EqualityComparer<TValue>.Default;
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (entries[i].hashCode >= 0 && c.Equals(entries[i].value, value)) return true;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -289,6 +277,19 @@ namespace System.Collections
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ContainsAlt<TAltKey>((TAltKey key, TValue value) kvPair) where TAltKey : IHashable where bool : operator TKey == TAltKey
|
||||||
|
{
|
||||||
|
TValue value;
|
||||||
|
if (TryGetValueAlt(kvPair.key, out value))
|
||||||
|
{
|
||||||
|
return value == kvPair.value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void CopyTo(Span<KeyValuePair> kvPair)
|
public void CopyTo(Span<KeyValuePair> kvPair)
|
||||||
{
|
{
|
||||||
|
@ -306,12 +307,21 @@ namespace System.Collections
|
||||||
return Enumerator(this, Enumerator.[Friend]KeyValuePair);
|
return Enumerator(this, Enumerator.[Friend]KeyValuePair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int_cosize GetKeyHash(int hashCode)
|
||||||
|
{
|
||||||
|
if (sizeof(int) == 4)
|
||||||
|
return (int32)hashCode & 0x7FFFFFFF;
|
||||||
|
if (sizeof(int_cosize) == 8)
|
||||||
|
return (int_cosize)(hashCode & 0x7FFFFFFF'FFFFFFFFL);
|
||||||
|
return ((int32)hashCode ^ (int32)((int64)hashCode >> 33)) & 0x7FFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
[DisableObjectAccessChecks]
|
[DisableObjectAccessChecks]
|
||||||
private int FindEntry(TKey key)
|
private int FindEntry(TKey key)
|
||||||
{
|
{
|
||||||
if (mBuckets != null)
|
if (mBuckets != null)
|
||||||
{
|
{
|
||||||
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
|
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||||
for (int i = mBuckets[hashCode % mAllocSize]; i >= 0; i = mEntries[i].mNext)
|
for (int i = mBuckets[hashCode % mAllocSize]; i >= 0; i = mEntries[i].mNext)
|
||||||
{
|
{
|
||||||
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key)) return i;
|
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key)) return i;
|
||||||
|
@ -329,7 +339,7 @@ namespace System.Collections
|
||||||
{
|
{
|
||||||
if (mBuckets != null)
|
if (mBuckets != null)
|
||||||
{
|
{
|
||||||
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
|
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||||
for (int_cosize i = mBuckets[hashCode % mAllocSize]; i >= 0; i = mEntries[i].mNext)
|
for (int_cosize i = mBuckets[hashCode % mAllocSize]; i >= 0; i = mEntries[i].mNext)
|
||||||
{
|
{
|
||||||
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key)) return i;
|
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key)) return i;
|
||||||
|
@ -350,10 +360,10 @@ namespace System.Collections
|
||||||
private void Insert(TKey key, TValue value, bool add)
|
private void Insert(TKey key, TValue value, bool add)
|
||||||
{
|
{
|
||||||
if (mBuckets == null) Initialize(0);
|
if (mBuckets == null) Initialize(0);
|
||||||
int32 hashCode = (int32)key.GetHashCode() & 0x7FFFFFFF;
|
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||||
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
|
int targetBucket = hashCode % mAllocSize;
|
||||||
|
|
||||||
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
|
for (int i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
|
||||||
{
|
{
|
||||||
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key))
|
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key))
|
||||||
{
|
{
|
||||||
|
@ -402,7 +412,7 @@ namespace System.Collections
|
||||||
private bool Insert(TKey key, bool add, out TKey* keyPtr, out TValue* valuePtr, Entry** outOldData)
|
private bool Insert(TKey key, bool add, out TKey* keyPtr, out TValue* valuePtr, Entry** outOldData)
|
||||||
{
|
{
|
||||||
if (mBuckets == null) Initialize(0);
|
if (mBuckets == null) Initialize(0);
|
||||||
int32 hashCode = (int32)key.GetHashCode() & 0x7FFFFFFF;
|
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||||
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
|
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
|
||||||
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
|
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
|
||||||
{
|
{
|
||||||
|
@ -458,9 +468,9 @@ namespace System.Collections
|
||||||
private bool InsertAlt<TAltKey>(TAltKey key, bool add, out TKey* keyPtr, out TValue* valuePtr, Entry** outOldData) where TAltKey : IHashable where bool : operator TKey == TAltKey
|
private bool InsertAlt<TAltKey>(TAltKey key, bool add, out TKey* keyPtr, out TValue* valuePtr, Entry** outOldData) where TAltKey : IHashable where bool : operator TKey == TAltKey
|
||||||
{
|
{
|
||||||
if (mBuckets == null) Initialize(0);
|
if (mBuckets == null) Initialize(0);
|
||||||
int32 hashCode = (int32)key.GetHashCode() & 0x7FFFFFFF;
|
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||||
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
|
int targetBucket = hashCode % (int_cosize)mAllocSize;
|
||||||
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
|
for (int i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
|
||||||
{
|
{
|
||||||
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key))
|
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key))
|
||||||
{
|
{
|
||||||
|
@ -541,7 +551,7 @@ namespace System.Collections
|
||||||
{
|
{
|
||||||
if (newEntries[i].mHashCode != -1)
|
if (newEntries[i].mHashCode != -1)
|
||||||
{
|
{
|
||||||
newEntries[i].mHashCode = (int32)newEntries[i].mKey.GetHashCode() & 0x7FFFFFFF;
|
newEntries[i].mHashCode = GetKeyHash(newEntries[i].mKey.GetHashCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,7 +582,7 @@ namespace System.Collections
|
||||||
{
|
{
|
||||||
if (mBuckets != null)
|
if (mBuckets != null)
|
||||||
{
|
{
|
||||||
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
|
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||||
int bucket = hashCode % (int_cosize)mAllocSize;
|
int bucket = hashCode % (int_cosize)mAllocSize;
|
||||||
int last = -1;
|
int last = -1;
|
||||||
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
||||||
|
@ -609,7 +619,7 @@ namespace System.Collections
|
||||||
{
|
{
|
||||||
if (mBuckets != null)
|
if (mBuckets != null)
|
||||||
{
|
{
|
||||||
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
|
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||||
int bucket = hashCode % (int_cosize)mAllocSize;
|
int bucket = hashCode % (int_cosize)mAllocSize;
|
||||||
int last = -1;
|
int last = -1;
|
||||||
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
||||||
|
@ -653,8 +663,8 @@ namespace System.Collections
|
||||||
if (mBuckets != null)
|
if (mBuckets != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
|
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||||
int_cosize bucket = hashCode % (int_cosize)mAllocSize;
|
int bucket = hashCode % (int_cosize)mAllocSize;
|
||||||
int_cosize last = -1;
|
int_cosize last = -1;
|
||||||
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
||||||
{
|
{
|
||||||
|
@ -694,8 +704,8 @@ namespace System.Collections
|
||||||
if (mBuckets != null)
|
if (mBuckets != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
|
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||||
int_cosize bucket = hashCode % (int_cosize)mAllocSize;
|
int bucket = hashCode % (int_cosize)mAllocSize;
|
||||||
int_cosize last = -1;
|
int_cosize last = -1;
|
||||||
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
||||||
{
|
{
|
||||||
|
@ -742,6 +752,18 @@ namespace System.Collections
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetValueAlt<TAltKey>(TAltKey key, out TValue value) where TAltKey : IHashable where bool : operator TKey == TAltKey
|
||||||
|
{
|
||||||
|
int_cosize i = (int_cosize)FindEntryAlt<TAltKey>(key);
|
||||||
|
if (i >= 0)
|
||||||
|
{
|
||||||
|
value = mEntries[i].mValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
value = default(TValue);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryGet(TKey key, out TKey matchKey, out TValue value)
|
public bool TryGet(TKey key, out TKey matchKey, out TValue value)
|
||||||
{
|
{
|
||||||
int_cosize i = (int_cosize)FindEntry(key);
|
int_cosize i = (int_cosize)FindEntry(key);
|
||||||
|
@ -876,6 +898,16 @@ namespace System.Collections
|
||||||
mDictionary.mEntries[mCurrentIndex].mValue = value;
|
mDictionary.mEntries[mCurrentIndex].mValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Remove() mut
|
||||||
|
{
|
||||||
|
int_cosize curIdx = mIndex - 1;
|
||||||
|
mDictionary.Remove(mDictionary.mEntries[curIdx].mKey);
|
||||||
|
#if VERSION_DICTIONARY
|
||||||
|
mVersion = mDictionary.mVersion;
|
||||||
|
#endif
|
||||||
|
mIndex = curIdx;
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset() mut
|
public void Reset() mut
|
||||||
{
|
{
|
||||||
#if VERSION_DICTIONARY
|
#if VERSION_DICTIONARY
|
||||||
|
@ -1017,6 +1049,16 @@ namespace System.Collections
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Remove() mut
|
||||||
|
{
|
||||||
|
int_cosize curIdx = mIndex - 1;
|
||||||
|
mDictionary.Remove(mDictionary.mEntries[curIdx].mKey);
|
||||||
|
#if VERSION_DICTIONARY
|
||||||
|
mVersion = mDictionary.mVersion;
|
||||||
|
#endif
|
||||||
|
mIndex = curIdx;
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset() mut
|
public void Reset() mut
|
||||||
{
|
{
|
||||||
#if VERSION_DICTIONARY
|
#if VERSION_DICTIONARY
|
||||||
|
@ -1113,6 +1155,16 @@ namespace System.Collections
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Remove() mut
|
||||||
|
{
|
||||||
|
int_cosize curIdx = mIndex - 1;
|
||||||
|
mDictionary.Remove(mDictionary.mEntries[curIdx].mKey);
|
||||||
|
#if VERSION_DICTIONARY
|
||||||
|
mVersion = mDictionary.mVersion;
|
||||||
|
#endif
|
||||||
|
mIndex = curIdx;
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset() mut
|
public void Reset() mut
|
||||||
{
|
{
|
||||||
#if VERSION_DICTIONARY
|
#if VERSION_DICTIONARY
|
||||||
|
|
|
@ -196,7 +196,13 @@ namespace System.Collections
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Method renamed to ContainsAlt", false)]
|
||||||
public bool ContainsWith<TAltKey>(TAltKey item) where TAltKey : IHashable where bool : operator T == TAltKey
|
public bool ContainsWith<TAltKey>(TAltKey item) where TAltKey : IHashable where bool : operator T == TAltKey
|
||||||
|
{
|
||||||
|
return ContainsAlt(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsAlt<TAltKey>(TAltKey item) where TAltKey : IHashable where bool : operator T == TAltKey
|
||||||
{
|
{
|
||||||
if (mBuckets != null)
|
if (mBuckets != null)
|
||||||
{
|
{
|
||||||
|
@ -346,6 +352,11 @@ namespace System.Collections
|
||||||
return Add(item, out entryPtr);
|
return Add(item, out entryPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryAddAlt<TAltKey>(TAltKey item, out T* entryPtr) where TAltKey : IHashable where bool : operator T == TAltKey
|
||||||
|
{
|
||||||
|
return AddAlt(item, out entryPtr);
|
||||||
|
}
|
||||||
|
|
||||||
public void CopyTo(T[] array) { CopyTo(array, 0, mCount); }
|
public void CopyTo(T[] array) { CopyTo(array, 0, mCount); }
|
||||||
|
|
||||||
public void CopyTo(T[] array, int32 arrayIndex, int32 count)
|
public void CopyTo(T[] array, int32 arrayIndex, int32 count)
|
||||||
|
@ -632,6 +643,71 @@ namespace System.Collections
|
||||||
mVersion++;
|
mVersion++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE
|
||||||
|
if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(m_comparer)) {
|
||||||
|
m_comparer = (IEqualityComparer<T>) HashHelpers.GetRandomizedEqualityComparer(m_comparer);
|
||||||
|
SetCapacity(m_buckets.Length, true);
|
||||||
|
}
|
||||||
|
#endif // FEATURE_RANDOMIZED_STRING_HASHING
|
||||||
|
|
||||||
|
entryPtr = &mSlots[index].mValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds value to HashSet if not contained already
|
||||||
|
/// @return true if added and false if already present
|
||||||
|
/// @param value value to find
|
||||||
|
/// @param entryPtr ponter to entry
|
||||||
|
public bool AddAlt<TAltKey>(TAltKey value, out T* entryPtr) where TAltKey : IHashable where bool : operator T == TAltKey
|
||||||
|
{
|
||||||
|
if (mBuckets == null)
|
||||||
|
{
|
||||||
|
Initialize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 hashCode = (int32)InternalGetHashCodeAlt(value);
|
||||||
|
int32 bucket = hashCode % (int32)mBuckets.Count;
|
||||||
|
#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE
|
||||||
|
int collisionCount = 0;
|
||||||
|
#endif
|
||||||
|
for (int32 i = mBuckets[hashCode % mBuckets.Count] - 1; i >= 0; i = mSlots[i].mNext)
|
||||||
|
{
|
||||||
|
if (mSlots[i].mHashCode == hashCode && /*m_comparer.Equals*/(mSlots[i].mValue == value))
|
||||||
|
{
|
||||||
|
entryPtr = &mSlots[i].mValue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE
|
||||||
|
collisionCount++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 index;
|
||||||
|
if (mFreeList >= 0)
|
||||||
|
{
|
||||||
|
index = mFreeList;
|
||||||
|
mFreeList = mSlots[index].mNext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mLastIndex == mSlots.Count)
|
||||||
|
{
|
||||||
|
IncreaseCapacity();
|
||||||
|
// this will change during resize
|
||||||
|
bucket = hashCode % (int32)mBuckets.Count;
|
||||||
|
}
|
||||||
|
index = mLastIndex;
|
||||||
|
mLastIndex++;
|
||||||
|
}
|
||||||
|
mSlots[index].mHashCode = hashCode;
|
||||||
|
//mSlots[index].mValue = value;
|
||||||
|
mSlots[index].mNext = mBuckets[bucket] - 1;
|
||||||
|
mBuckets[bucket] = index + 1;
|
||||||
|
mCount++;
|
||||||
|
#if VERSION_HASHSET
|
||||||
|
mVersion++;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE
|
#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE
|
||||||
if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(m_comparer)) {
|
if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(m_comparer)) {
|
||||||
m_comparer = (IEqualityComparer<T>) HashHelpers.GetRandomizedEqualityComparer(m_comparer);
|
m_comparer = (IEqualityComparer<T>) HashHelpers.GetRandomizedEqualityComparer(m_comparer);
|
||||||
|
@ -1071,6 +1147,15 @@ namespace System.Collections
|
||||||
return item.GetHashCode() & Lower31BitMask;
|
return item.GetHashCode() & Lower31BitMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int InternalGetHashCodeAlt<TAltKey>(TAltKey item) where TAltKey : IHashable
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return item.GetHashCode() & Lower31BitMask;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// used for set checking operations (using enumerables) that rely on counting
|
// used for set checking operations (using enumerables) that rely on counting
|
||||||
|
|
|
@ -148,6 +148,7 @@ namespace System.Collections
|
||||||
|
|
||||||
public int Count
|
public int Count
|
||||||
{
|
{
|
||||||
|
[Inline]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return mSize;
|
return mSize;
|
||||||
|
@ -210,6 +211,76 @@ namespace System.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref T this[Index index]
|
||||||
|
{
|
||||||
|
[Checked]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mSize - offset;
|
||||||
|
}
|
||||||
|
Runtime.Assert((uint)idx < (uint)mSize);
|
||||||
|
return ref mItems[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mSize - offset;
|
||||||
|
}
|
||||||
|
return ref mItems[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Checked]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mSize - offset;
|
||||||
|
}
|
||||||
|
Runtime.Assert((uint)idx < (uint)mSize);
|
||||||
|
mItems[idx] = value;
|
||||||
|
#if VERSION_LIST
|
||||||
|
mVersion++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mSize - offset;
|
||||||
|
}
|
||||||
|
mItems[idx] = value;
|
||||||
|
#if VERSION_LIST
|
||||||
|
mVersion++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Span<T> this[IndexRange range]
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
[Inline]
|
||||||
|
#endif
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Span<T>(mItems, mSize)[range];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ref T Front
|
public ref T Front
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -534,7 +605,7 @@ namespace System.Collections
|
||||||
if (mSize == AllocSize) EnsureCapacity(mSize + 1, true);
|
if (mSize == AllocSize) EnsureCapacity(mSize + 1, true);
|
||||||
if (index < mSize)
|
if (index < mSize)
|
||||||
{
|
{
|
||||||
Internal.MemCpy(mItems + index + 1, mItems + index, (mSize - index) * strideof(T), alignof(T));
|
Internal.MemMove(mItems + index + 1, mItems + index, (mSize - index) * strideof(T), alignof(T));
|
||||||
}
|
}
|
||||||
mItems[index] = item;
|
mItems[index] = item;
|
||||||
mSize++;
|
mSize++;
|
||||||
|
@ -553,7 +624,7 @@ namespace System.Collections
|
||||||
if (mSize + addCount > AllocSize) EnsureCapacity(mSize + addCount, true);
|
if (mSize + addCount > AllocSize) EnsureCapacity(mSize + addCount, true);
|
||||||
if (index < mSize)
|
if (index < mSize)
|
||||||
{
|
{
|
||||||
Internal.MemCpy(mItems + index + addCount, mItems + index, (mSize - index) * strideof(T), alignof(T));
|
Internal.MemMove(mItems + index + addCount, mItems + index, (mSize - index) * strideof(T), alignof(T));
|
||||||
}
|
}
|
||||||
Internal.MemCpy(mItems + index, items.Ptr, addCount * strideof(T));
|
Internal.MemCpy(mItems + index, items.Ptr, addCount * strideof(T));
|
||||||
mSize += (int_cosize)addCount;
|
mSize += (int_cosize)addCount;
|
||||||
|
@ -567,7 +638,7 @@ namespace System.Collections
|
||||||
Debug.Assert((uint)index < (uint)mSize);
|
Debug.Assert((uint)index < (uint)mSize);
|
||||||
if (index < mSize - 1)
|
if (index < mSize - 1)
|
||||||
{
|
{
|
||||||
Internal.MemCpy(mItems + index, mItems + index + 1, (mSize - index - 1) * strideof(T), alignof(T));
|
Internal.MemMove(mItems + index, mItems + index + 1, (mSize - index - 1) * strideof(T), alignof(T));
|
||||||
}
|
}
|
||||||
mSize--;
|
mSize--;
|
||||||
#if VERSION_LIST
|
#if VERSION_LIST
|
||||||
|
@ -930,6 +1001,59 @@ namespace System.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension List<T> where T : String
|
||||||
|
{
|
||||||
|
public bool Contains(T item, StringComparison comparison)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
if (mItems[i] == null)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
if (mItems[i].Equals(item, comparison))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int IndexOf(T item, StringComparison comparison)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mSize; i++)
|
||||||
|
if (mItems[i].Equals(item, comparison))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int IndexOf(T item, int index, StringComparison comparison)
|
||||||
|
{
|
||||||
|
for (int i = index; i < mSize; i++)
|
||||||
|
if (mItems[i].Equals(item, comparison))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int IndexOf(T item, int index, int count, StringComparison comparison)
|
||||||
|
{
|
||||||
|
for (int i = index; i < index + count; i++)
|
||||||
|
if (mItems[i].Equals(item, comparison))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int LastIndexOf(T item, StringComparison comparison)
|
||||||
|
{
|
||||||
|
for (int i = mSize - 1; i >= 0; i--)
|
||||||
|
if (mItems[i].Equals(item, comparison))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ListWithAlloc<T> : List<T>
|
class ListWithAlloc<T> : List<T>
|
||||||
{
|
{
|
||||||
IRawAllocator mAlloc;
|
IRawAllocator mAlloc;
|
||||||
|
|
|
@ -18,6 +18,12 @@ namespace System
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Options
|
||||||
|
{
|
||||||
|
[LinkName("#AllocStackCount")]
|
||||||
|
public static extern int32 AllocStackCount;
|
||||||
|
}
|
||||||
|
|
||||||
[LinkName("#CallerLineNum")]
|
[LinkName("#CallerLineNum")]
|
||||||
public static extern int CallerLineNum;
|
public static extern int CallerLineNum;
|
||||||
|
|
||||||
|
@ -37,7 +43,7 @@ namespace System
|
||||||
public static extern String CallerProject;
|
public static extern String CallerProject;
|
||||||
|
|
||||||
[LinkName("#CallerExpression")]
|
[LinkName("#CallerExpression")]
|
||||||
public static extern String[Int32.MaxValue] CallerExpression;
|
public static extern String[0x0FFFFFFF] CallerExpression;
|
||||||
|
|
||||||
[LinkName("#ProjectName")]
|
[LinkName("#ProjectName")]
|
||||||
public static extern String ProjectName;
|
public static extern String ProjectName;
|
||||||
|
|
|
@ -7,6 +7,12 @@ namespace System
|
||||||
{
|
{
|
||||||
public static class Console
|
public static class Console
|
||||||
{
|
{
|
||||||
|
public enum CancelKind
|
||||||
|
{
|
||||||
|
CtrlC,
|
||||||
|
CtrlBreak
|
||||||
|
}
|
||||||
|
|
||||||
static Encoding InputEncoding = Encoding.ASCII;
|
static Encoding InputEncoding = Encoding.ASCII;
|
||||||
static Encoding OutputEncoding = Encoding.ASCII;
|
static Encoding OutputEncoding = Encoding.ASCII;
|
||||||
|
|
||||||
|
@ -16,6 +22,9 @@ namespace System
|
||||||
static readonly ConsoleColor sOriginalForegroundColor = sForegroundColor;
|
static readonly ConsoleColor sOriginalForegroundColor = sForegroundColor;
|
||||||
static readonly ConsoleColor sOriginalBackgroundColor = sBackgroundColor;
|
static readonly ConsoleColor sOriginalBackgroundColor = sBackgroundColor;
|
||||||
|
|
||||||
|
static Event<delegate void (CancelKind cancelKind, ref bool terminate)> sOnCancel ~ _.Dispose();
|
||||||
|
static bool sCancelEventRegistered;
|
||||||
|
|
||||||
public static ConsoleColor ForegroundColor
|
public static ConsoleColor ForegroundColor
|
||||||
{
|
{
|
||||||
get { return sForegroundColor; }
|
get { return sForegroundColor; }
|
||||||
|
@ -42,16 +51,57 @@ namespace System
|
||||||
public uint16[2] mMaximumWindowSize;
|
public uint16[2] mMaximumWindowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CLink, CallingConvention(.Stdcall)]
|
[CRepr]
|
||||||
static extern int SetConsoleTextAttribute(void* hConsoleOutput, uint16 wAttributes);
|
struct COORD : this(int16 X, int16 Y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[CLink, CallingConvention(.Stdcall)]
|
public static ref Event<delegate void (CancelKind cancelKind, ref bool terminate)> OnCancel
|
||||||
static extern int GetConsoleScreenBufferInfo(void* hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
|
{
|
||||||
|
get
|
||||||
[CLink, CallingConvention(.Stdcall)]
|
{
|
||||||
static extern void* GetStdHandle(uint32 nStdHandle);
|
if (!sCancelEventRegistered)
|
||||||
|
{
|
||||||
|
sCancelEventRegistered = true;
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
SetConsoleCtrlHandler(=> ConsoleCtrlHandler, true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return ref sOnCancel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if BF_PLATFORM_WINDOWS
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
[CallingConvention(.Stdcall)]
|
||||||
|
public static Windows.IntBool ConsoleCtrlHandler(int32 ctrlType)
|
||||||
|
{
|
||||||
|
bool terminate = true;
|
||||||
|
if ((ctrlType == 0) || (ctrlType == 1))
|
||||||
|
sOnCancel((.)ctrlType, ref terminate);
|
||||||
|
return terminate ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
|
static extern Windows.IntBool SetConsoleTextAttribute(Windows.Handle hConsoleOutput, uint16 wAttributes);
|
||||||
|
|
||||||
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
|
static extern Windows.IntBool GetConsoleScreenBufferInfo(Windows.Handle hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
|
||||||
|
|
||||||
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
|
static extern Windows.Handle GetStdHandle(uint32 nStdHandle);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall)]
|
||||||
|
function Windows.IntBool ConsoleCtrlHandler(int32 ctrlType);
|
||||||
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
|
static extern Windows.IntBool SetConsoleCtrlHandler(ConsoleCtrlHandler handler, Windows.IntBool addHandler);
|
||||||
|
|
||||||
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
|
static extern Windows.IntBool FillConsoleOutputCharacterW(Windows.Handle hConsoleOutput, char16 cCharacter, uint32 nLength, COORD dwWriteCoord, uint32* lpNumberOfCharsWritten);
|
||||||
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
|
static extern Windows.IntBool FillConsoleOutputAttribute(Windows.Handle hConsoleOutput, uint16 wAttribute, uint32 nLength, COORD dwWriteCoord, uint32* lpNumberOfAttrsWritten);
|
||||||
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
|
static extern Windows.IntBool SetConsoleCursorPosition(Windows.Handle hConsoleOutput, COORD dwCursorPosition);
|
||||||
|
|
||||||
public static this()
|
public static this()
|
||||||
{
|
{
|
||||||
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
@ -219,6 +269,49 @@ namespace System
|
||||||
#else
|
#else
|
||||||
Write("\x1B[{}m", ForegroundColor.AnsiCode);
|
Write("\x1B[{}m", ForegroundColor.AnsiCode);
|
||||||
Write("\x1B[{}m", BackgroundColor.AnsiCode + 10);
|
Write("\x1B[{}m", BackgroundColor.AnsiCode + 10);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Clear()
|
||||||
|
{
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
Windows.Handle hStdOut;
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
|
uint32 count;
|
||||||
|
uint32 cellCount;
|
||||||
|
COORD homeCoords = .(0, 0);
|
||||||
|
|
||||||
|
hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
|
||||||
|
if (hStdOut == .InvalidHandle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Get the number of cells in the current buffer */
|
||||||
|
if (!GetConsoleScreenBufferInfo( hStdOut, out csbi ))
|
||||||
|
return;
|
||||||
|
cellCount = csbi.mSize[0] * csbi.mSize[1];
|
||||||
|
|
||||||
|
/* Fill the entire buffer with spaces */
|
||||||
|
if (!FillConsoleOutputCharacterW(
|
||||||
|
hStdOut,
|
||||||
|
' ',
|
||||||
|
cellCount,
|
||||||
|
homeCoords,
|
||||||
|
&count
|
||||||
|
)) return;
|
||||||
|
|
||||||
|
/* Fill the entire buffer with the current colors and attributes */
|
||||||
|
if (!FillConsoleOutputAttribute(
|
||||||
|
hStdOut,
|
||||||
|
csbi.mAttributes,
|
||||||
|
cellCount,
|
||||||
|
homeCoords,
|
||||||
|
&count
|
||||||
|
)) return;
|
||||||
|
|
||||||
|
/* Move the cursor home */
|
||||||
|
SetConsoleCursorPosition( hStdOut, homeCoords );
|
||||||
|
#else
|
||||||
|
Write("\x1B[H\x1B[J");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace System.Diagnostics
|
||||||
private char8[] char8Buffer;
|
private char8[] char8Buffer;
|
||||||
// Record the number of valid bytes in the byteBuffer, for a few checks.
|
// Record the number of valid bytes in the byteBuffer, for a few checks.
|
||||||
|
|
||||||
// This is the maximum number of char8s we can get from one call to
|
// This is the maximum number of chars we can get from one call to
|
||||||
// ReadBuffer. Used so ReadBuffer can tell when to copy data into
|
// ReadBuffer. Used so ReadBuffer can tell when to copy data into
|
||||||
// a user's char8[] directly, instead of our internal char8[].
|
// a user's char8[] directly, instead of our internal char8[].
|
||||||
private int32 mMaxCharsPerBuffer;
|
private int32 mMaxCharsPerBuffer;
|
||||||
|
@ -194,7 +194,7 @@ namespace System.Diagnostics
|
||||||
int lineStart = 0;
|
int lineStart = 0;
|
||||||
int len = sb.Length;
|
int len = sb.Length;
|
||||||
|
|
||||||
// skip a beginning '\n' char8acter of new block if last block ended
|
// skip a beginning '\n' character of new block if last block ended
|
||||||
// with '\r'
|
// with '\r'
|
||||||
if (bLastCarriageReturn && (len > 0) && sb[0] == '\n')
|
if (bLastCarriageReturn && (len > 0) && sb[0] == '\n')
|
||||||
{
|
{
|
||||||
|
@ -206,7 +206,7 @@ namespace System.Diagnostics
|
||||||
while (currentIndex < len)
|
while (currentIndex < len)
|
||||||
{
|
{
|
||||||
char8 ch = sb[currentIndex];
|
char8 ch = sb[currentIndex];
|
||||||
// Note the following common line feed char8s:
|
// Note the following common line feed chars:
|
||||||
// \n - UNIX \r\n - DOS \r - Mac
|
// \n - UNIX \r\n - DOS \r - Mac
|
||||||
if (ch == '\r' || ch == '\n')
|
if (ch == '\r' || ch == '\n')
|
||||||
{
|
{
|
||||||
|
@ -214,7 +214,7 @@ namespace System.Diagnostics
|
||||||
s.Append(sb, lineStart, currentIndex - lineStart);
|
s.Append(sb, lineStart, currentIndex - lineStart);
|
||||||
|
|
||||||
lineStart = currentIndex + 1;
|
lineStart = currentIndex + 1;
|
||||||
// skip the "\n" char8acter following "\r" char8acter
|
// skip the "\n" character following "\r" character
|
||||||
if ((ch == '\r') && (lineStart < len) && (sb[lineStart] == '\n'))
|
if ((ch == '\r') && (lineStart < len) && (sb[lineStart] == '\n'))
|
||||||
{
|
{
|
||||||
lineStart++;
|
lineStart++;
|
||||||
|
@ -232,7 +232,7 @@ namespace System.Diagnostics
|
||||||
{
|
{
|
||||||
bLastCarriageReturn = true;
|
bLastCarriageReturn = true;
|
||||||
}
|
}
|
||||||
// Keep the rest char8acaters which can't form a new line in string builder.
|
// Keep the rest characaters which can't form a new line in string builder.
|
||||||
if (lineStart < len)
|
if (lineStart < len)
|
||||||
{
|
{
|
||||||
if (lineStart == 0)
|
if (lineStart == 0)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace System.Diagnostics
|
namespace System.Diagnostics
|
||||||
{
|
{
|
||||||
class Check
|
static class Check
|
||||||
{
|
{
|
||||||
|
|
||||||
[Unchecked, SkipCall]
|
[Unchecked, SkipCall]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace System.Diagnostics.Contracts
|
namespace System.Diagnostics.Contracts
|
||||||
{
|
{
|
||||||
class Contract
|
static class Contract
|
||||||
{
|
{
|
||||||
public enum ContractFailureKind
|
public enum ContractFailureKind
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace System.Diagnostics
|
namespace System.Diagnostics
|
||||||
{
|
{
|
||||||
class Debug
|
static class Debug
|
||||||
{
|
{
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
[SkipCall]
|
[SkipCall]
|
||||||
|
@ -44,6 +44,11 @@ namespace System.Diagnostics
|
||||||
Write(line.Ptr, line.Length);
|
Write(line.Ptr, line.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Write(StringView sv)
|
||||||
|
{
|
||||||
|
Write(sv.[Friend]mPtr, sv.[Friend]mLength);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Write(String fmt, params Object[] args)
|
public static void Write(String fmt, params Object[] args)
|
||||||
{
|
{
|
||||||
String str = scope String(4096);
|
String str = scope String(4096);
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace System
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(T compareDelegate, bool deleteDelegate = false) mut
|
public Result<void> Remove(T compareDelegate, bool deleteDelegate = false) mut
|
||||||
{
|
{
|
||||||
Object data = Target;
|
Object data = Target;
|
||||||
|
|
||||||
|
@ -150,9 +150,7 @@ namespace System
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
{
|
return .Err;
|
||||||
Runtime.FatalError("Not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deleteDelegate)
|
if (deleteDelegate)
|
||||||
delete list[idx];
|
delete list[idx];
|
||||||
|
@ -177,18 +175,14 @@ namespace System
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
T dlgMember = (T)data;
|
T dlgMember = (T)data;
|
||||||
if (Delegate.Equals(compareDelegate, dlgMember))
|
if (!Delegate.Equals(compareDelegate, dlgMember))
|
||||||
{
|
return .Err;
|
||||||
if (deleteDelegate)
|
if (deleteDelegate)
|
||||||
delete dlgMember;
|
delete dlgMember;
|
||||||
Target = null;
|
Target = null;
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Runtime.FatalError("Not found");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
public rettype(T) Invoke(params T p) mut
|
public rettype(T) Invoke(params T p) mut
|
||||||
|
|
|
@ -175,6 +175,17 @@ namespace System
|
||||||
{
|
{
|
||||||
char8 c = val.Ptr[i];
|
char8 c = val.Ptr[i];
|
||||||
|
|
||||||
|
//Exponent prefix used in scientific notation. E.g. 1.2E5
|
||||||
|
if ((c == 'e') || (c == 'E'))
|
||||||
|
{
|
||||||
|
//Error if there are no numbers after the prefix
|
||||||
|
if(i == val.Length - 1)
|
||||||
|
return .Err;
|
||||||
|
var exponent = Try!(int32.Parse(val.Substring(i + 1)));
|
||||||
|
result *= Math.Pow(10, (double)exponent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (c == '.')
|
if (c == '.')
|
||||||
{
|
{
|
||||||
if (decimalMultiplier != 0)
|
if (decimalMultiplier != 0)
|
||||||
|
|
|
@ -173,6 +173,10 @@ namespace System
|
||||||
// or the memory would already be registered with the GC
|
// or the memory would already be registered with the GC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static mixin Mark<T>(T val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public static mixin Mark<TSizedArray, T, Size>(TSizedArray val) where Size : const int where TSizedArray : SizedArray<T, Size>
|
public static mixin Mark<TSizedArray, T, Size>(TSizedArray val) where Size : const int where TSizedArray : SizedArray<T, Size>
|
||||||
{
|
{
|
||||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace System.Globalization
|
||||||
|
|
||||||
// cache for the invariant culture.
|
// cache for the invariant culture.
|
||||||
// invariantInfo is constant irrespective of your current culture.
|
// invariantInfo is constant irrespective of your current culture.
|
||||||
private static volatile DateTimeFormatInfo invariantInfo;
|
private static volatile DateTimeFormatInfo invariantInfo ~ delete _;
|
||||||
|
|
||||||
// an index which points to a record in Culture Data Table.
|
// an index which points to a record in Culture Data Table.
|
||||||
private CultureData m_cultureData;
|
private CultureData m_cultureData;
|
||||||
|
@ -139,6 +139,8 @@ namespace System.Globalization
|
||||||
List<Object> ownedObjects = new .() ~ DeleteContainerAndItems!(_);
|
List<Object> ownedObjects = new .() ~ DeleteContainerAndItems!(_);
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
|
: this(CultureInfo.InvariantCulture.[Friend]m_cultureData,
|
||||||
|
GregorianCalendar.[Friend]GetDefaultInstance())
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace System.Globalization {
|
||||||
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
|
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
|
||||||
) ~ delete _;
|
) ~ delete _;
|
||||||
|
|
||||||
private static volatile Calendar s_defaultInstance;
|
private static volatile Calendar s_defaultInstance ~ delete _;
|
||||||
|
|
||||||
|
|
||||||
#region Serialization
|
#region Serialization
|
||||||
|
|
|
@ -23,6 +23,10 @@ namespace System
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ICharacter
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[Obsolete("Consider operator constraint such as `where bool : operator T == T`", false)]
|
[Obsolete("Consider operator constraint such as `where bool : operator T == T`", false)]
|
||||||
interface IOpEquals
|
interface IOpEquals
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace System.IO
|
||||||
|
|
||||||
public override Result<int> TryRead(Span<uint8> data)
|
public override Result<int> TryRead(Span<uint8> data)
|
||||||
{
|
{
|
||||||
int spaceLeft = (.)(mBufferEnd - mPos);
|
int64 spaceLeft = (.)(mBufferEnd - mPos);
|
||||||
if (mPos < mBufferPos)
|
if (mPos < mBufferPos)
|
||||||
spaceLeft = 0;
|
spaceLeft = 0;
|
||||||
if (data.Length <= spaceLeft)
|
if (data.Length <= spaceLeft)
|
||||||
|
@ -83,19 +83,17 @@ namespace System.IO
|
||||||
var data;
|
var data;
|
||||||
if (spaceLeft > 0)
|
if (spaceLeft > 0)
|
||||||
{
|
{
|
||||||
Internal.MemCpy(data.Ptr, mBuffer.Ptr + (mPos - mBufferPos), spaceLeft);
|
Internal.MemCpy(data.Ptr, mBuffer.Ptr + (mPos - mBufferPos), (.)spaceLeft);
|
||||||
mPos += spaceLeft;
|
mPos += spaceLeft;
|
||||||
data.RemoveFromStart(spaceLeft);
|
data.RemoveFromStart((.)spaceLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mWriteDirtyPos >= 0)
|
Try!(Flush());
|
||||||
Try!(Flush());
|
|
||||||
|
|
||||||
if ((mBuffer == null) || (data.Length > mBuffer.Count))
|
if ((mBuffer == null) || (data.Length > mBuffer.Count))
|
||||||
{
|
{
|
||||||
var result = TryReadUnderlying(mPos, data);
|
let len = Try!(TryReadUnderlying(mPos, data));
|
||||||
if (result case .Ok(let len))
|
mPos += len;
|
||||||
mPos += len;
|
|
||||||
return (.)(mPos - readStart);
|
return (.)(mPos - readStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,10 +146,9 @@ namespace System.IO
|
||||||
|
|
||||||
if ((mBuffer == null) || (data.Length > mBuffer.Count))
|
if ((mBuffer == null) || (data.Length > mBuffer.Count))
|
||||||
{
|
{
|
||||||
var result = TryWriteUnderlying(mPos, data);
|
let len = Try!(TryWriteUnderlying(mPos, data));
|
||||||
if (result case .Ok(let len))
|
mPos += len;
|
||||||
mPos += len;
|
writeCount += len;
|
||||||
writeCount += result;
|
|
||||||
return writeCount;
|
return writeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,7 @@ namespace System.IO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileEnumerator : IEnumerator<FileFindEntry>
|
struct FileEnumerator : IEnumerator<FileFindEntry>, IDisposable
|
||||||
{
|
{
|
||||||
String mSearchStr;
|
String mSearchStr;
|
||||||
Platform.BfpFindFileData* mFindFileData;
|
Platform.BfpFindFileData* mFindFileData;
|
||||||
|
|
|
@ -15,6 +15,11 @@ namespace System.IO
|
||||||
mOwnsData = true;
|
mOwnsData = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public this(List<uint8> data)
|
||||||
|
{
|
||||||
|
mData = data;
|
||||||
|
}
|
||||||
|
|
||||||
public uint8* Ptr
|
public uint8* Ptr
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -112,4 +117,100 @@ namespace System.IO
|
||||||
mData.RemoveRange(0, count);
|
mData.RemoveRange(0, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DynMemStreamSequential : Stream
|
||||||
|
{
|
||||||
|
List<uint8> mData ~ { if (mOwnsData) delete _; };
|
||||||
|
bool mOwnsData;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
mData = new .();
|
||||||
|
mOwnsData = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(List<uint8> data)
|
||||||
|
{
|
||||||
|
mData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint8* Ptr
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mData.Ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Span<uint8> Content
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int64 Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mData.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Runtime.FatalError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int64 Length
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mData.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanWrite
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<uint8> TakeOwnership()
|
||||||
|
{
|
||||||
|
Debug.Assert(mOwnsData);
|
||||||
|
mOwnsData = false;
|
||||||
|
return mData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Result<int> TryRead(Span<uint8> data)
|
||||||
|
{
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Result<int> TryWrite(Span<uint8> data)
|
||||||
|
{
|
||||||
|
let count = data.Length;
|
||||||
|
if (count == 0)
|
||||||
|
return .Ok(0);
|
||||||
|
Internal.MemCpy(mData.GrowUnitialized(count), data.Ptr, count);
|
||||||
|
return .Ok(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Result<void> Close()
|
||||||
|
{
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace System.IO
|
||||||
case FileReadError(FileReadError);
|
case FileReadError(FileReadError);
|
||||||
}
|
}
|
||||||
|
|
||||||
class File
|
static class File
|
||||||
{
|
{
|
||||||
public static Result<void, FileError> ReadAll(StringView path, List<uint8> outData)
|
public static Result<void, FileError> ReadAll(StringView path, List<uint8> outData)
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,7 @@ namespace System.IO
|
||||||
|
|
||||||
public static Result<void> WriteAll(StringView path, Span<uint8> data, bool doAppend = false)
|
public static Result<void> WriteAll(StringView path, Span<uint8> data, bool doAppend = false)
|
||||||
{
|
{
|
||||||
FileStream fs = scope FileStream();
|
UnbufferedFileStream fs = scope UnbufferedFileStream();
|
||||||
var result = fs.Open(path, doAppend ? .Append : .Create, .Write);
|
var result = fs.Open(path, doAppend ? .Append : .Create, .Write);
|
||||||
if (result case .Err)
|
if (result case .Err)
|
||||||
return .Err;
|
return .Err;
|
||||||
|
@ -76,7 +76,7 @@ namespace System.IO
|
||||||
|
|
||||||
public static Result<void> WriteAllText(StringView path, StringView text, bool doAppend = false)
|
public static Result<void> WriteAllText(StringView path, StringView text, bool doAppend = false)
|
||||||
{
|
{
|
||||||
FileStream fs = scope FileStream();
|
UnbufferedFileStream fs = scope UnbufferedFileStream();
|
||||||
var result = fs.Open(path, doAppend ? .Append : .Create, .Write);
|
var result = fs.Open(path, doAppend ? .Append : .Create, .Write);
|
||||||
if (result case .Err)
|
if (result case .Err)
|
||||||
return .Err;
|
return .Err;
|
||||||
|
@ -87,7 +87,7 @@ namespace System.IO
|
||||||
|
|
||||||
public static Result<void> WriteAllText(StringView path, StringView text, Encoding encoding)
|
public static Result<void> WriteAllText(StringView path, StringView text, Encoding encoding)
|
||||||
{
|
{
|
||||||
FileStream fs = scope FileStream();
|
UnbufferedFileStream fs = scope UnbufferedFileStream();
|
||||||
|
|
||||||
int len = encoding.GetEncodedSize(text);
|
int len = encoding.GetEncodedSize(text);
|
||||||
uint8* data = new uint8[len]*;
|
uint8* data = new uint8[len]*;
|
||||||
|
|
|
@ -17,16 +17,16 @@ namespace System.IO
|
||||||
/// Opens an existing file. Fails if the file does not exist.
|
/// Opens an existing file. Fails if the file does not exist.
|
||||||
Open = 3,
|
Open = 3,
|
||||||
|
|
||||||
// Opens the file if it exists. Otherwise, creates a new file.
|
/// Opens the file if it exists. Otherwise, creates a new file.
|
||||||
OpenOrCreate = 4,
|
OpenOrCreate = 4,
|
||||||
|
|
||||||
// Opens an existing file. Once opened, the file is truncated so that its
|
/// Opens an existing file. Once opened, the file is truncated so that its
|
||||||
// size is zero bytes. The calling process must open the file with at least
|
/// size is zero bytes. The calling process must open the file with at least
|
||||||
// WRITE access. Fails if the file does not exist.
|
/// WRITE access. Fails if the file does not exist.
|
||||||
Truncate = 5,
|
Truncate = 5,
|
||||||
|
|
||||||
// Opens the file if it exists and seeks to the end. Otherwise,
|
/// Opens the file if it exists and seeks to the end. Otherwise,
|
||||||
// creates a new file.
|
/// creates a new file.
|
||||||
Append = 6,
|
Append = 6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,16 @@ namespace System.IO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int Handle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (mBfpFile == null)
|
||||||
|
return 0;
|
||||||
|
return Platform.BfpFile_GetSystemHandle(mBfpFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
{
|
{
|
||||||
Delete();
|
Delete();
|
||||||
|
@ -165,12 +175,13 @@ namespace System.IO
|
||||||
createKind = .CreateIfNotExists;
|
createKind = .CreateIfNotExists;
|
||||||
case .Create:
|
case .Create:
|
||||||
createKind = .CreateAlways;
|
createKind = .CreateAlways;
|
||||||
|
createFlags |= .Truncate;
|
||||||
case .Open:
|
case .Open:
|
||||||
createKind = .OpenExisting;
|
createKind = .OpenExisting;
|
||||||
case .OpenOrCreate:
|
case .OpenOrCreate:
|
||||||
createKind = .CreateAlways;
|
createKind = .OpenAlways;
|
||||||
case .Truncate:
|
case .Truncate:
|
||||||
createKind = .CreateAlways;
|
createKind = .OpenExisting;
|
||||||
createFlags |= .Truncate;
|
createFlags |= .Truncate;
|
||||||
case .Append:
|
case .Append:
|
||||||
createKind = .CreateAlways;
|
createKind = .CreateAlways;
|
||||||
|
@ -225,6 +236,32 @@ namespace System.IO
|
||||||
return .Err;
|
return .Err;
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Result<void> SetLength(int64 length)
|
||||||
|
{
|
||||||
|
int64 pos = Position;
|
||||||
|
|
||||||
|
if (pos != length)
|
||||||
|
Seek(length);
|
||||||
|
|
||||||
|
Platform.BfpFileResult result = .Ok;
|
||||||
|
Platform.BfpFile_Truncate(mBfpFile, &result);
|
||||||
|
if (result != .Ok)
|
||||||
|
{
|
||||||
|
Seek(pos);
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos != length)
|
||||||
|
{
|
||||||
|
if (pos < length)
|
||||||
|
Seek(pos);
|
||||||
|
else
|
||||||
|
Seek(0, .FromEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BufferedFileStream : BufferedStream
|
class BufferedFileStream : BufferedStream
|
||||||
|
@ -233,6 +270,32 @@ namespace System.IO
|
||||||
protected int64 mBfpFilePos;
|
protected int64 mBfpFilePos;
|
||||||
FileAccess mFileAccess;
|
FileAccess mFileAccess;
|
||||||
|
|
||||||
|
public int Handle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (mBfpFile == null)
|
||||||
|
return 0;
|
||||||
|
return Platform.BfpFile_GetSystemHandle(mBfpFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mFileAccess.HasFlag(FileAccess.Read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanWrite
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mFileAccess.HasFlag(FileAccess.Write);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -254,22 +317,6 @@ namespace System.IO
|
||||||
mFileAccess = access;
|
mFileAccess = access;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanRead
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mFileAccess.HasFlag(FileAccess.Read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanWrite
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mFileAccess.HasFlag(FileAccess.Write);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<void, FileOpenError> Create(StringView path, FileAccess access = .ReadWrite, FileShare share = .None, int bufferSize = 4096, FileOptions options = .None, SecurityAttributes* secAttrs = null)
|
public Result<void, FileOpenError> Create(StringView path, FileAccess access = .ReadWrite, FileShare share = .None, int bufferSize = 4096, FileOptions options = .None, SecurityAttributes* secAttrs = null)
|
||||||
{
|
{
|
||||||
return Open(path, FileMode.Create, access, share, bufferSize, options, secAttrs);
|
return Open(path, FileMode.Create, access, share, bufferSize, options, secAttrs);
|
||||||
|
@ -317,7 +364,7 @@ namespace System.IO
|
||||||
case .Open:
|
case .Open:
|
||||||
createKind = .OpenExisting;
|
createKind = .OpenExisting;
|
||||||
case .OpenOrCreate:
|
case .OpenOrCreate:
|
||||||
createKind = .CreateAlways;
|
createKind = .OpenAlways;
|
||||||
case .Truncate:
|
case .Truncate:
|
||||||
createKind = .CreateAlways;
|
createKind = .CreateAlways;
|
||||||
createFlags |= .Truncate;
|
createFlags |= .Truncate;
|
||||||
|
@ -386,15 +433,20 @@ namespace System.IO
|
||||||
mUnderlyingLength = Platform.BfpFile_GetFileSize(mBfpFile);
|
mUnderlyingLength = Platform.BfpFile_GetFileSize(mBfpFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Result<void> SeekUnderlying(int64 offset, Platform.BfpFileSeekKind seekKind = .Absolute)
|
||||||
|
{
|
||||||
|
int64 newPos = Platform.BfpFile_Seek(mBfpFile, offset, seekKind);
|
||||||
|
Result<void> result = ((seekKind == .Absolute) && (newPos != offset)) ? .Err : .Ok;
|
||||||
|
if (result case .Ok)
|
||||||
|
mBfpFilePos = newPos;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
protected override Result<int> TryReadUnderlying(int64 pos, Span<uint8> data)
|
protected override Result<int> TryReadUnderlying(int64 pos, Span<uint8> data)
|
||||||
{
|
{
|
||||||
if (mBfpFilePos != pos)
|
if (mBfpFilePos != pos)
|
||||||
{
|
Try!(SeekUnderlying(pos));
|
||||||
int64 newPos = Platform.BfpFile_Seek(mBfpFile, pos, .Absolute);
|
|
||||||
if (newPos != pos)
|
|
||||||
return .Err;
|
|
||||||
mBfpFilePos = pos;
|
|
||||||
}
|
|
||||||
Platform.BfpFileResult result = .Ok;
|
Platform.BfpFileResult result = .Ok;
|
||||||
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, -1, &result);
|
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, -1, &result);
|
||||||
if ((result != .Ok) && (result != .PartialData))
|
if ((result != .Ok) && (result != .PartialData))
|
||||||
|
@ -406,12 +458,8 @@ namespace System.IO
|
||||||
protected override Result<int> TryWriteUnderlying(int64 pos, Span<uint8> data)
|
protected override Result<int> TryWriteUnderlying(int64 pos, Span<uint8> data)
|
||||||
{
|
{
|
||||||
if (mBfpFilePos != pos)
|
if (mBfpFilePos != pos)
|
||||||
{
|
Try!(SeekUnderlying(pos));
|
||||||
int64 newPos = Platform.BfpFile_Seek(mBfpFile, pos, .Absolute);
|
|
||||||
if (newPos != pos)
|
|
||||||
return .Err;
|
|
||||||
mBfpFilePos = pos;
|
|
||||||
}
|
|
||||||
Platform.BfpFileResult result = .Ok;
|
Platform.BfpFileResult result = .Ok;
|
||||||
int numBytesRead = Platform.BfpFile_Write(mBfpFile, data.Ptr, data.Length, -1, &result);
|
int numBytesRead = Platform.BfpFile_Write(mBfpFile, data.Ptr, data.Length, -1, &result);
|
||||||
if ((result != .Ok) && (result != .PartialData))
|
if ((result != .Ok) && (result != .PartialData))
|
||||||
|
@ -423,12 +471,7 @@ namespace System.IO
|
||||||
public Result<int> TryRead(Span<uint8> data, int timeoutMS)
|
public Result<int> TryRead(Span<uint8> data, int timeoutMS)
|
||||||
{
|
{
|
||||||
if (mBfpFilePos != mPos)
|
if (mBfpFilePos != mPos)
|
||||||
{
|
Try!(SeekUnderlying(mPos));
|
||||||
int64 newPos = Platform.BfpFile_Seek(mBfpFile, mPos, .Absolute);
|
|
||||||
if (newPos != mPos)
|
|
||||||
return .Err;
|
|
||||||
mBfpFilePos = mPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
Platform.BfpFileResult result = .Ok;
|
Platform.BfpFileResult result = .Ok;
|
||||||
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, timeoutMS, &result);
|
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, timeoutMS, &result);
|
||||||
|
@ -436,6 +479,40 @@ namespace System.IO
|
||||||
return .Err;
|
return .Err;
|
||||||
return numBytesRead;
|
return numBytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Result<void> SetLength(int64 length)
|
||||||
|
{
|
||||||
|
Try!(Flush());
|
||||||
|
|
||||||
|
int64 pos = Position;
|
||||||
|
|
||||||
|
if (pos != length || pos != mBfpFilePos)
|
||||||
|
{
|
||||||
|
Try!(SeekUnderlying(length));
|
||||||
|
mPos = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform.BfpFileResult result = .Ok;
|
||||||
|
Platform.BfpFile_Truncate(mBfpFile, &result);
|
||||||
|
if (result != .Ok)
|
||||||
|
{
|
||||||
|
Try!(SeekUnderlying(pos));
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mUnderlyingLength = length;
|
||||||
|
mPos = Math.Min(pos, Length);
|
||||||
|
|
||||||
|
if (pos != length)
|
||||||
|
{
|
||||||
|
if (pos < length)
|
||||||
|
Try!(SeekUnderlying(pos));
|
||||||
|
else
|
||||||
|
Try!(SeekUnderlying(0, .FromEnd));
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileStream : BufferedFileStream
|
class FileStream : BufferedFileStream
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace System.IO
|
||||||
{
|
{
|
||||||
class MemoryStream : Stream
|
class MemoryStream : Stream
|
||||||
{
|
{
|
||||||
List<uint8> mMemory = new List<uint8>() ~ delete _;
|
List<uint8> mMemory ~ delete _;
|
||||||
int mPosition = 0;
|
int mPosition = 0;
|
||||||
|
|
||||||
public override int64 Position
|
public override int64 Position
|
||||||
|
@ -44,6 +44,16 @@ namespace System.IO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
mMemory = new List<uint8>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(List<uint8> memory)
|
||||||
|
{
|
||||||
|
mMemory = memory;
|
||||||
|
}
|
||||||
|
|
||||||
public override Result<int> TryRead(Span<uint8> data)
|
public override Result<int> TryRead(Span<uint8> data)
|
||||||
{
|
{
|
||||||
let count = data.Length;
|
let count = data.Length;
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace System.IO
|
||||||
public const char8 DirectorySeparatorChar = '/';
|
public const char8 DirectorySeparatorChar = '/';
|
||||||
#endif //BF_PLATFORM_WINDOWS
|
#endif //BF_PLATFORM_WINDOWS
|
||||||
|
|
||||||
// Platform specific alternate directory separator char8acter.
|
// Platform specific alternate directory separator character.
|
||||||
// This is backslash ('\') on Unix, and slash ('/') on Windows
|
// This is backslash ('\') on Unix, and slash ('/') on Windows
|
||||||
// and MacOS.
|
// and MacOS.
|
||||||
//
|
//
|
||||||
|
@ -25,7 +25,7 @@ namespace System.IO
|
||||||
public const char8 AltDirectorySeparatorChar = '\\';
|
public const char8 AltDirectorySeparatorChar = '\\';
|
||||||
#endif //BF_PLATFORM_WINDOWS
|
#endif //BF_PLATFORM_WINDOWS
|
||||||
|
|
||||||
// Platform specific volume separator char8acter. This is colon (':')
|
// Platform specific volume separator character. This is colon (':')
|
||||||
// on Windows and MacOS, and slash ('/') on Unix. This is mostly
|
// on Windows and MacOS, and slash ('/') on Unix. This is mostly
|
||||||
// useful for parsing paths like "c:\windows" or "MacVolume:System Folder".
|
// useful for parsing paths like "c:\windows" or "MacVolume:System Folder".
|
||||||
//
|
//
|
||||||
|
@ -37,7 +37,7 @@ namespace System.IO
|
||||||
|
|
||||||
// Make this public sometime.
|
// Make this public sometime.
|
||||||
// The max total path is 260, and the max individual component length is 255.
|
// The max total path is 260, and the max individual component length is 255.
|
||||||
// For example, D:\<256 char8 file name> isn't legal, even though it's under 260 char8s.
|
// For example, D:\<256 char file name> isn't legal, even though it's under 260 chars.
|
||||||
protected const int32 MaxPath = 260;
|
protected const int32 MaxPath = 260;
|
||||||
private const int32 MaxDirectoryLength = 255;
|
private const int32 MaxDirectoryLength = 255;
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ namespace System.IO
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InternalCombine(String target, params String[] components)
|
public static void InternalCombine(String target, params StringView[] components)
|
||||||
{
|
{
|
||||||
for (var component in components)
|
for (var component in components)
|
||||||
{
|
{
|
||||||
|
|
|
@ -97,25 +97,32 @@ namespace System.IO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read sized string from stream
|
/// Read sized string from stream
|
||||||
public Result<void> ReadStrSized32(int64 size, String output)
|
public Result<void> ReadStrSized32(int size, String output)
|
||||||
{
|
{
|
||||||
if (size <= 0)
|
if (size < 0)
|
||||||
return .Err;
|
return .Err;
|
||||||
|
|
||||||
for (int64 i = 0; i < size; i++)
|
int prevLen = output.Length;
|
||||||
|
char8* buf = output.PrepareBuffer(size);
|
||||||
|
switch (TryRead(.((uint8*)buf, size)))
|
||||||
{
|
{
|
||||||
Result<char8> char = Read<char8>();
|
case .Ok(let readLen):
|
||||||
if (char == .Err)
|
if (readLen < size)
|
||||||
return .Err;
|
output.Length = prevLen + readLen;
|
||||||
|
return .Ok;
|
||||||
output.Append(char);
|
case .Err:
|
||||||
|
return .Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Reads null terminated ASCII string from the stream. Null terminator is read from stream but isn't appended to output string
|
public Result<void> ReadStrSized32(String output)
|
||||||
|
{
|
||||||
|
int size = Try!(Read<int32>());
|
||||||
|
return ReadStrSized32(size, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads null terminated ASCII string from the stream. Null terminator is read from stream but isn't appended to output string
|
||||||
public Result<void> ReadStrC(String output)
|
public Result<void> ReadStrC(String output)
|
||||||
{
|
{
|
||||||
Result<char8> char0;
|
Result<char8> char0;
|
||||||
|
@ -197,6 +204,11 @@ namespace System.IO
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual Result<void> SetLength(int64 length)
|
||||||
|
{
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
public void Align(int alignSize)
|
public void Align(int alignSize)
|
||||||
{
|
{
|
||||||
int64 pos = Length;
|
int64 pos = Length;
|
||||||
|
|
|
@ -256,7 +256,7 @@ namespace System.IO
|
||||||
{
|
{
|
||||||
char8 ch = tmpCharBuffer[i];
|
char8 ch = tmpCharBuffer[i];
|
||||||
|
|
||||||
// Note the following common line feed char8s:
|
// Note the following common line feed chars:
|
||||||
// \n - UNIX \r\n - DOS \r - Mac
|
// \n - UNIX \r\n - DOS \r - Mac
|
||||||
if (ch == '\r' || ch == '\n')
|
if (ch == '\r' || ch == '\n')
|
||||||
{
|
{
|
||||||
|
@ -481,7 +481,7 @@ namespace System.IO
|
||||||
}
|
}
|
||||||
while (mCharLen == 0);
|
while (mCharLen == 0);
|
||||||
|
|
||||||
//Console.WriteLine("ReadBuffer called. char8s: "+char8Len);
|
//Console.WriteLine("ReadBuffer called. chars: "+char8Len);
|
||||||
return mCharLen;
|
return mCharLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,7 +522,7 @@ namespace System.IO
|
||||||
repeat
|
repeat
|
||||||
{
|
{
|
||||||
char8 ch = mCharBuffer[i];
|
char8 ch = mCharBuffer[i];
|
||||||
// Note the following common line feed char8s:
|
// Note the following common line feed chars:
|
||||||
// \n - UNIX \r\n - DOS \r - Mac
|
// \n - UNIX \r\n - DOS \r - Mac
|
||||||
if (ch == '\r' || ch == '\n')
|
if (ch == '\r' || ch == '\n')
|
||||||
{
|
{
|
||||||
|
|
|
@ -243,6 +243,7 @@ namespace System
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AlwaysInclude]
|
||||||
public static String[] CreateParamsArray()
|
public static String[] CreateParamsArray()
|
||||||
{
|
{
|
||||||
char8* cmdLine = GetCommandLineArgs();
|
char8* cmdLine = GetCommandLineArgs();
|
||||||
|
@ -347,6 +348,7 @@ namespace System
|
||||||
return strVals;
|
return strVals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AlwaysInclude]
|
||||||
public static void DeleteStringArray(String[] arr)
|
public static void DeleteStringArray(String[] arr)
|
||||||
{
|
{
|
||||||
for (var str in arr)
|
for (var str in arr)
|
||||||
|
|
|
@ -24,7 +24,9 @@ namespace System
|
||||||
|
|
||||||
private static float[7] sRoundPower10Single = .(
|
private static float[7] sRoundPower10Single = .(
|
||||||
1E0f, 1E1f, 1E2f, 1E3f, 1E4f, 1E5f, 1E6f);
|
1E0f, 1E1f, 1E2f, 1E3f, 1E4f, 1E5f, 1E6f);
|
||||||
|
|
||||||
|
private static float sMachineEpsilonFloat = GetMachineEpsilonFloat();
|
||||||
|
|
||||||
public const double PI_d = 3.14159265358979323846;
|
public const double PI_d = 3.14159265358979323846;
|
||||||
public const double E_d = 2.7182818284590452354;
|
public const double E_d = 2.7182818284590452354;
|
||||||
public const float PI_f = 3.14159265358979323846f;
|
public const float PI_f = 3.14159265358979323846f;
|
||||||
|
@ -48,6 +50,33 @@ namespace System
|
||||||
public static extern float Floor(float f);
|
public static extern float Floor(float f);
|
||||||
public static extern double Floor(double d);
|
public static extern double Floor(double d);
|
||||||
|
|
||||||
|
public static bool WithinEpsilon(float a, float b)
|
||||||
|
{
|
||||||
|
return Math.Abs(a - b) < sMachineEpsilonFloat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find the current machine's Epsilon for the float data type.
|
||||||
|
/// (That is, the largest float, e, where e == 0.0f is true.)
|
||||||
|
/// </summary>
|
||||||
|
private static float GetMachineEpsilonFloat()
|
||||||
|
{
|
||||||
|
float machineEpsilon = 1.0f;
|
||||||
|
float comparison;
|
||||||
|
|
||||||
|
/* Keep halving the working value of machineEpsilon until we get a number that
|
||||||
|
* when added to 1.0f will still evaluate as equal to 1.0f.
|
||||||
|
*/
|
||||||
|
repeat
|
||||||
|
{
|
||||||
|
machineEpsilon *= 0.5f;
|
||||||
|
comparison = 1.0f + machineEpsilon;
|
||||||
|
}
|
||||||
|
while (comparison > 1.0f);
|
||||||
|
|
||||||
|
return machineEpsilon;
|
||||||
|
}
|
||||||
|
|
||||||
private static float InternalRound(float value, int32 digits, MidpointRounding mode)
|
private static float InternalRound(float value, int32 digits, MidpointRounding mode)
|
||||||
{
|
{
|
||||||
if (Abs(value) < cSingleRoundLimit)
|
if (Abs(value) < cSingleRoundLimit)
|
||||||
|
@ -476,5 +505,125 @@ namespace System
|
||||||
{
|
{
|
||||||
return ((val) + (align - 1)) & ~(align - 1);
|
return ((val) + (align - 1)) & ~(align - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Interpolates between two values using a cubic equation.
|
||||||
|
/// @param name Source value.
|
||||||
|
/// @param name Source value.
|
||||||
|
/// @param name Weighting value.
|
||||||
|
/// @returns Interpolated value.
|
||||||
|
public static float SmoothStep(float value1, float value2, float amount)
|
||||||
|
{
|
||||||
|
/* It is expected that 0 < amount < 1.
|
||||||
|
* If amount < 0, return value1.
|
||||||
|
* If amount > 1, return value2.
|
||||||
|
*/
|
||||||
|
float result = Clamp(amount, 0f, 1f);
|
||||||
|
result = Hermite(value1, 0f, value2, 0f, result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs a Hermite spline interpolation.
|
||||||
|
/// @param value1 Source position.
|
||||||
|
/// @param tangent1 Source tangent.
|
||||||
|
/// @param value2 Source position.
|
||||||
|
/// @param tangent2 Source tangent.
|
||||||
|
/// @param amount Weighting factor.
|
||||||
|
/// @returns The result of the Hermite spline interpolation.
|
||||||
|
public static float Hermite(
|
||||||
|
float value1,
|
||||||
|
float tangent1,
|
||||||
|
float value2,
|
||||||
|
float tangent2,
|
||||||
|
float amount
|
||||||
|
) {
|
||||||
|
/* All transformed to double not to lose precision
|
||||||
|
* Otherwise, for high numbers of param:amount the result is NaN instead
|
||||||
|
* of Infinity.
|
||||||
|
*/
|
||||||
|
double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount;
|
||||||
|
double result;
|
||||||
|
double sCubed = s * s * s;
|
||||||
|
double sSquared = s * s;
|
||||||
|
|
||||||
|
if (WithinEpsilon(amount, 0f))
|
||||||
|
{
|
||||||
|
result = value1;
|
||||||
|
}
|
||||||
|
else if (WithinEpsilon(amount, 1f))
|
||||||
|
{
|
||||||
|
result = value2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = (
|
||||||
|
((2 * v1 - 2 * v2 + t2 + t1) * sCubed) +
|
||||||
|
((3 * v2 - 3 * v1 - 2 * t1 - t2) * sSquared) +
|
||||||
|
(t1 * s) +
|
||||||
|
v1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (float) result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the Cartesian coordinate for one axis of a point that is defined by a
|
||||||
|
/// given triangle and two normalized barycentric (areal) coordinates.
|
||||||
|
/// <param name="value1">
|
||||||
|
/// The coordinate on one axis of vertex 1 of the defining triangle.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="value2">
|
||||||
|
/// The coordinate on the same axis of vertex 2 of the defining triangle.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="value3">
|
||||||
|
/// The coordinate on the same axis of vertex 3 of the defining triangle.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="amount1">
|
||||||
|
/// The normalized barycentric (areal) coordinate b2, equal to the weighting factor
|
||||||
|
/// for vertex 2, the coordinate of which is specified in value2.
|
||||||
|
/// </param>
|
||||||
|
/// @param amount2
|
||||||
|
/// The normalized barycentric (areal) coordinate b3, equal to the weighting factor
|
||||||
|
/// for vertex 3, the coordinate of which is specified in value3.
|
||||||
|
/// </param>
|
||||||
|
/// @returns Cartesian coordinate of the specified point with respect to the axis being used.
|
||||||
|
public static float Barycentric(
|
||||||
|
float value1,
|
||||||
|
float value2,
|
||||||
|
float value3,
|
||||||
|
float amount1,
|
||||||
|
float amount2
|
||||||
|
) {
|
||||||
|
return value1 + (value2 - value1) * amount1 + (value3 - value1) * amount2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs a Catmull-Rom interpolation using the specified positions.
|
||||||
|
/// @param value1 The first position in the interpolation.
|
||||||
|
/// @param value2">The second position in the interpolation.
|
||||||
|
/// @param value3">The third position in the interpolation.
|
||||||
|
/// @param value4">The fourth position in the interpolation.
|
||||||
|
/// @param name="amount">Weighting factor.
|
||||||
|
/// @returns A position that is the result of the Catmull-Rom interpolation.
|
||||||
|
public static float CatmullRom(
|
||||||
|
float value1,
|
||||||
|
float value2,
|
||||||
|
float value3,
|
||||||
|
float value4,
|
||||||
|
float amount
|
||||||
|
) {
|
||||||
|
/* Using formula from http://www.mvps.org/directx/articles/catmull/
|
||||||
|
* Internally using doubles not to lose precision.
|
||||||
|
*/
|
||||||
|
double amountSquared = amount * amount;
|
||||||
|
double amountCubed = amountSquared * amount;
|
||||||
|
return (float) (
|
||||||
|
0.5 *
|
||||||
|
(
|
||||||
|
((2.0 * value2 + (value3 - value1) * amount) +
|
||||||
|
((2.0 * value1 - 5.0 * value2 + 4.0 * value3 - value4) * amountSquared) +
|
||||||
|
(3.0 * value2 - value1 - 3.0 * value3 + value4) * amountCubed)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace System.Net
|
||||||
{
|
{
|
||||||
class Socket
|
class Socket
|
||||||
{
|
{
|
||||||
|
const uint16 WINSOCK_VERSION = 0x0202;
|
||||||
const int32 WSAENETRESET = 10052;
|
const int32 WSAENETRESET = 10052;
|
||||||
const int32 WSAECONNABORTED = 10053;
|
const int32 WSAECONNABORTED = 10053;
|
||||||
const int32 WSAECONNRESET = 10054;
|
const int32 WSAECONNRESET = 10054;
|
||||||
|
@ -169,12 +170,22 @@ namespace System.Net
|
||||||
#if BF_PLATFORM_WINDOWS
|
#if BF_PLATFORM_WINDOWS
|
||||||
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
|
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||||
static extern int32 WSAStartup(uint16 versionRequired, WSAData* wsaData);
|
static extern int32 WSAStartup(uint16 versionRequired, WSAData* wsaData);
|
||||||
|
|
||||||
|
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||||
|
static extern int32 WSACleanup();
|
||||||
|
|
||||||
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
|
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||||
static extern int32 WSAGetLastError();
|
static extern int32 WSAGetLastError();
|
||||||
|
#elif BF_PLATFORM_LINUX
|
||||||
|
[LinkName("__errno_location")]
|
||||||
|
static extern int32* _errno();
|
||||||
|
#elif BF_PLATFORM_MACOS
|
||||||
|
[LinkName("__error")]
|
||||||
|
static extern int32* _errno();
|
||||||
#else
|
#else
|
||||||
[CLink]
|
[CLink]
|
||||||
static int32 errno;
|
static int32 errno;
|
||||||
|
static int32* _errno() => &errno;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[CLink, CallingConvention(.Stdcall)]
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
|
@ -230,11 +241,22 @@ namespace System.Net
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Init()
|
public static int32 Init(uint16 versionRequired = WINSOCK_VERSION)
|
||||||
{
|
{
|
||||||
#if BF_PLATFORM_WINDOWS
|
#if BF_PLATFORM_WINDOWS
|
||||||
WSAData wsaData = default;
|
WSAData wsaData = default;
|
||||||
WSAStartup(0x202, &wsaData);
|
return WSAStartup(versionRequired, &wsaData);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int32 Uninit()
|
||||||
|
{
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
return WSACleanup();
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +265,7 @@ namespace System.Net
|
||||||
#if BF_PLATFORM_WINDOWS
|
#if BF_PLATFORM_WINDOWS
|
||||||
return WSAGetLastError();
|
return WSAGetLastError();
|
||||||
#else
|
#else
|
||||||
return errno;
|
return *_errno();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2675,7 +2675,7 @@ namespace System
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int i = sb.Length + (end - start);
|
int i = sb.Length + (end - start);
|
||||||
sb.Length = i;
|
sb.PrepareBuffer(i);
|
||||||
|
|
||||||
var end;
|
var end;
|
||||||
var start;
|
var start;
|
||||||
|
|
|
@ -271,6 +271,7 @@ namespace System
|
||||||
CreateAlways,
|
CreateAlways,
|
||||||
CreateIfNotExists,
|
CreateIfNotExists,
|
||||||
OpenExisting,
|
OpenExisting,
|
||||||
|
OpenAlways,
|
||||||
};
|
};
|
||||||
|
|
||||||
public enum BfpFileCreateFlags : int32
|
public enum BfpFileCreateFlags : int32
|
||||||
|
@ -337,6 +338,8 @@ namespace System
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
public static extern BfpFile* BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult);
|
public static extern BfpFile* BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult);
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
public static extern int BfpFile_GetSystemHandle(BfpFile* file);
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
public static extern void BfpFile_Release(BfpFile* file);
|
public static extern void BfpFile_Release(BfpFile* file);
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
public static extern int BfpFile_Write(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult);
|
public static extern int BfpFile_Write(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult);
|
||||||
|
@ -349,7 +352,7 @@ namespace System
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
public static extern int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind);
|
public static extern int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind);
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
public static extern void BfpFile_Truncate(BfpFile* file);
|
public static extern void BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult);
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
public static extern BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path);
|
public static extern BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path);
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
@ -410,7 +413,8 @@ namespace System
|
||||||
AppData_LocalLow,
|
AppData_LocalLow,
|
||||||
AppData_Roaming,
|
AppData_Roaming,
|
||||||
Programs,
|
Programs,
|
||||||
Programs_Common
|
Programs_Common,
|
||||||
|
Documents
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Result<void, Platform.Result> GetStrHelper(String outStr, delegate void (char8* outPtr, int32* outSize, Result* outResult) func)
|
public static Result<void, Platform.Result> GetStrHelper(String outStr, delegate void (char8* outPtr, int32* outSize, Result* outResult) func)
|
||||||
|
|
468
BeefLibs/corlib/src/Range.bf
Normal file
468
BeefLibs/corlib/src/Range.bf
Normal file
|
@ -0,0 +1,468 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace System
|
||||||
|
{
|
||||||
|
interface RangeExpression
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Index
|
||||||
|
{
|
||||||
|
case FromFront(int offset);
|
||||||
|
case FromEnd(int offset);
|
||||||
|
|
||||||
|
public override void ToString(String strBuffer)
|
||||||
|
{
|
||||||
|
switch (this)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset):
|
||||||
|
offset.ToString(strBuffer);
|
||||||
|
case .FromEnd(let offset):
|
||||||
|
strBuffer.Append('^');
|
||||||
|
offset.ToString(strBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Range : RangeExpression, IEnumerable<int>
|
||||||
|
{
|
||||||
|
protected int mStart;
|
||||||
|
protected int mEnd;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
mStart = 0;
|
||||||
|
mEnd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public this(int start, int end)
|
||||||
|
{
|
||||||
|
Debug.Assert(end >= start);
|
||||||
|
mStart = start;
|
||||||
|
mEnd = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Length
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mEnd - mStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mEnd = mStart + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Start
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mStart = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int End
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mEnd = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEmpty
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mEnd == mStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReverseEnumerator Reversed
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ReverseEnumerator(mEnd - 1, mStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(int idx)
|
||||||
|
{
|
||||||
|
return (idx >= mStart) && (idx < mEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(Range val)
|
||||||
|
{
|
||||||
|
return (val.[Friend]mStart >= mStart) && (val.[Friend]mEnd <= mEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(ClosedRange val)
|
||||||
|
{
|
||||||
|
return (val.[Friend]mStart >= mStart) && (val.[Friend]mEnd <= mEnd - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear() mut
|
||||||
|
{
|
||||||
|
mStart = 0;
|
||||||
|
mEnd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static operator IndexRange(Range list)
|
||||||
|
{
|
||||||
|
return .(.FromFront(list.mStart), .FromFront(list.mEnd), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public Enumerator GetEnumerator()
|
||||||
|
{
|
||||||
|
return Enumerator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ToString(String strBuffer)
|
||||||
|
{
|
||||||
|
strBuffer.AppendF($"{mStart}..<{mEnd}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Enumerator : IEnumerator<int>
|
||||||
|
{
|
||||||
|
private int mEnd;
|
||||||
|
private int mIndex;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public this(Range range)
|
||||||
|
{
|
||||||
|
mIndex = range.mStart - 1;
|
||||||
|
mEnd = range.mEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref int Index
|
||||||
|
{
|
||||||
|
get mut
|
||||||
|
{
|
||||||
|
return ref mIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int End => mEnd;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public Result<int> GetNext() mut
|
||||||
|
{
|
||||||
|
if (mIndex + 1 >= mEnd)
|
||||||
|
return .Err;
|
||||||
|
return ++mIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ReverseEnumerator : IEnumerator<int>
|
||||||
|
{
|
||||||
|
private int mEnd;
|
||||||
|
private int mIndex;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public this(int start, int end)
|
||||||
|
{
|
||||||
|
mIndex = start + 1;
|
||||||
|
mEnd = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref int Index
|
||||||
|
{
|
||||||
|
get mut
|
||||||
|
{
|
||||||
|
return ref mIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int End => mEnd;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public Result<int> GetNext() mut
|
||||||
|
{
|
||||||
|
if (mIndex <= mEnd)
|
||||||
|
return .Err;
|
||||||
|
return --mIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IndexRange : RangeExpression
|
||||||
|
{
|
||||||
|
protected Index mStart;
|
||||||
|
protected Index mEnd;
|
||||||
|
protected bool mIsClosed;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
this = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public this(Index start, Index end, bool isClosed=true)
|
||||||
|
{
|
||||||
|
mStart = start;
|
||||||
|
mEnd = end;
|
||||||
|
mIsClosed = isClosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public this(int start, Index end, bool isClosed=true)
|
||||||
|
{
|
||||||
|
mStart = .FromFront(start);
|
||||||
|
mEnd = end;
|
||||||
|
mIsClosed = isClosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public this(Index start, int end, bool isClosed=true)
|
||||||
|
{
|
||||||
|
mStart = start;
|
||||||
|
mEnd = .FromFront(end);
|
||||||
|
mIsClosed = isClosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public this(int start, int end, bool isClosed=true)
|
||||||
|
{
|
||||||
|
mStart = .FromFront(start);
|
||||||
|
mEnd = .FromFront(end);
|
||||||
|
mIsClosed = isClosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Index Start
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mStart = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Index End
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mEnd = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsClosed
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mIsClosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mIsClosed = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ToString(String strBuffer)
|
||||||
|
{
|
||||||
|
mStart.ToString(strBuffer);
|
||||||
|
if (mIsClosed)
|
||||||
|
strBuffer.Append("...");
|
||||||
|
else
|
||||||
|
strBuffer.Append("..<");
|
||||||
|
mEnd.ToString(strBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ClosedRange : RangeExpression, IEnumerable<int>
|
||||||
|
{
|
||||||
|
protected int mStart;
|
||||||
|
protected int mEnd;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
mStart = 0;
|
||||||
|
mEnd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public this(int start, int end)
|
||||||
|
{
|
||||||
|
Debug.Assert(end >= start);
|
||||||
|
mStart = start;
|
||||||
|
mEnd = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Length
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mEnd - mStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mEnd = mStart + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Start
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mStart = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int End
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mEnd = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEmpty
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mEnd == mStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Range.ReverseEnumerator Reversed
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Range.ReverseEnumerator(mEnd, mStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(int idx)
|
||||||
|
{
|
||||||
|
return (idx >= mStart) && (idx <= mEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(Range val)
|
||||||
|
{
|
||||||
|
return (val.[Friend]mStart >= mStart) && (val.[Friend]mEnd - 1 <= mEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(ClosedRange val)
|
||||||
|
{
|
||||||
|
return (val.[Friend]mStart >= mStart) && (val.[Friend]mEnd <= mEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear() mut
|
||||||
|
{
|
||||||
|
mStart = 0;
|
||||||
|
mEnd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static operator IndexRange(ClosedRange list)
|
||||||
|
{
|
||||||
|
return .(.FromFront(list.mStart), .FromFront(list.mEnd), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public Enumerator GetEnumerator()
|
||||||
|
{
|
||||||
|
return Enumerator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ToString(String strBuffer)
|
||||||
|
{
|
||||||
|
strBuffer.AppendF($"{mStart}...{mEnd}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Enumerator : IEnumerator<int>
|
||||||
|
{
|
||||||
|
private int mEnd;
|
||||||
|
private int mIndex;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public this(ClosedRange range)
|
||||||
|
{
|
||||||
|
mIndex = range.mStart - 1;
|
||||||
|
mEnd = range.mEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref int Index
|
||||||
|
{
|
||||||
|
get mut
|
||||||
|
{
|
||||||
|
return ref mIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int End => mEnd;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public Result<int> GetNext() mut
|
||||||
|
{
|
||||||
|
if (mIndex >= mEnd)
|
||||||
|
return .Err;
|
||||||
|
return ++mIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,6 +92,9 @@ namespace System.Reflection
|
||||||
.Double:
|
.Double:
|
||||||
let attrData = Decode!<int64>(data);
|
let attrData = Decode!<int64>(data);
|
||||||
args[argIdx] = scope:AttrBlock box attrData;
|
args[argIdx] = scope:AttrBlock box attrData;
|
||||||
|
case (TypeCode)51: //BfConstType_TypeOf
|
||||||
|
let argTypeId = Decode!<int32>(data);
|
||||||
|
args[argIdx] = Type.[Friend]GetType((.)argTypeId);
|
||||||
case (TypeCode)255:
|
case (TypeCode)255:
|
||||||
let stringId = Decode!<int32>(data);
|
let stringId = Decode!<int32>(data);
|
||||||
String str = String.[Friend]sIdStringLiterals[stringId];
|
String str = String.[Friend]sIdStringLiterals[stringId];
|
||||||
|
|
|
@ -29,8 +29,8 @@ namespace System.Reflection
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (Compiler.IsComptime)
|
if (Compiler.IsComptime)
|
||||||
Type.[Friend]Comptime_Method_GetName(mNativeMethodInstance);
|
return Type.[Friend]Comptime_Method_GetName(mNativeMethodInstance);
|
||||||
return "";
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public int ParamCount
|
public int ParamCount
|
||||||
|
|
|
@ -20,53 +20,13 @@ namespace System.Reflection
|
||||||
mFieldData = fieldData;
|
mFieldData = fieldData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int32 MemberOffset
|
public TypeInstance DeclaringType => mTypeInstance;
|
||||||
{
|
public int32 MemberOffset => (int32)mFieldData.mData;
|
||||||
get
|
public Type FieldType => Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
||||||
{
|
public bool IsConst => mFieldData.mFlags.HasFlag(.Const);
|
||||||
return (int32)mFieldData.mData;
|
public bool IsStatic => mFieldData.mFlags.HasFlag(.Static);
|
||||||
}
|
public bool IsInstanceField => !mFieldData.mFlags.HasFlag(.Static) && !mFieldData.mFlags.HasFlag(.Const);
|
||||||
}
|
public StringView Name => mFieldData.mName;
|
||||||
|
|
||||||
public Type FieldType
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsConst
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mFieldData.mFlags.HasFlag(.Const);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsStatic
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mFieldData.mFlags.HasFlag(.Static);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsInstanceField
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return !mFieldData.mFlags.HasFlag(.Static) && !mFieldData.mFlags.HasFlag(.Const);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringView Name
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mFieldData.mName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<void, Error> SetValue(Object obj, Object value)
|
public Result<void, Error> SetValue(Object obj, Object value)
|
||||||
{
|
{
|
||||||
|
@ -525,7 +485,15 @@ namespace System.Reflection
|
||||||
{
|
{
|
||||||
mIdx++;
|
mIdx++;
|
||||||
if (mIdx == mTypeInstance.[Friend]mFieldDataCount)
|
if (mIdx == mTypeInstance.[Friend]mFieldDataCount)
|
||||||
return false;
|
{
|
||||||
|
if (mBindingFlags.HasFlag(.DeclaredOnly))
|
||||||
|
return false;
|
||||||
|
if (mTypeInstance.[Friend]mBaseType == 0)
|
||||||
|
return false;
|
||||||
|
mTypeInstance = Type.[Friend]GetType(mTypeInstance.[Friend]mBaseType) as TypeInstance;
|
||||||
|
mIdx = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var fieldData = &mTypeInstance.[Friend]mFieldDataPtr[mIdx];
|
var fieldData = &mTypeInstance.[Friend]mFieldDataPtr[mIdx];
|
||||||
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (fieldData.mFlags.HasFlag(FieldFlags.Static)));
|
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (fieldData.mFlags.HasFlag(FieldFlags.Static)));
|
||||||
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!fieldData.mFlags.HasFlag(FieldFlags.Static)));
|
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!fieldData.mFlags.HasFlag(FieldFlags.Static)));
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace System.Reflection
|
||||||
mMethodData = methodData;
|
mMethodData = methodData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TypeInstance DeclaringType => mTypeInstance;
|
||||||
public bool IsInitialized => mMethodData != null;
|
public bool IsInitialized => mMethodData != null;
|
||||||
public StringView Name => mMethodData.[Friend]mName;
|
public StringView Name => mMethodData.[Friend]mName;
|
||||||
public int ParamCount => mMethodData.[Friend]mParamCount;
|
public int ParamCount => mMethodData.[Friend]mParamCount;
|
||||||
|
@ -37,11 +38,22 @@ namespace System.Reflection
|
||||||
return mMethodData.mParamData[paramIdx].mName;
|
return mMethodData.mParamData[paramIdx].mName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result<T> GetParamCustomAttribute<T>(int paramIdx) where T : Attribute
|
||||||
|
{
|
||||||
|
Debug.Assert((uint)paramIdx < (uint)mMethodData.mParamCount);
|
||||||
|
return mTypeInstance.[Friend]GetCustomAttribute<T>(mMethodData.mParamData[paramIdx].mCustomAttributesIdx);
|
||||||
|
}
|
||||||
|
|
||||||
public Result<T> GetCustomAttribute<T>() where T : Attribute
|
public Result<T> GetCustomAttribute<T>() where T : Attribute
|
||||||
{
|
{
|
||||||
return mTypeInstance.[Friend]GetCustomAttribute<T>(mMethodData.mCustomAttributesIdx);
|
return mTypeInstance.[Friend]GetCustomAttribute<T>(mMethodData.mCustomAttributesIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result<T> GetReturnCustomAttribute<T>() where T : Attribute
|
||||||
|
{
|
||||||
|
return mTypeInstance.[Friend]GetCustomAttribute<T>(mMethodData.mReturnCustomAttributesIdx);
|
||||||
|
}
|
||||||
|
|
||||||
public enum CallError
|
public enum CallError
|
||||||
{
|
{
|
||||||
case None;
|
case None;
|
||||||
|
@ -777,7 +789,15 @@ namespace System.Reflection
|
||||||
{
|
{
|
||||||
mIdx++;
|
mIdx++;
|
||||||
if (mIdx == mTypeInstance.[Friend]mMethodDataCount)
|
if (mIdx == mTypeInstance.[Friend]mMethodDataCount)
|
||||||
return false;
|
{
|
||||||
|
if (mBindingFlags.HasFlag(.DeclaredOnly))
|
||||||
|
return false;
|
||||||
|
if (mTypeInstance.[Friend]mBaseType == 0)
|
||||||
|
return false;
|
||||||
|
mTypeInstance = Type.[Friend]GetType(mTypeInstance.[Friend]mBaseType) as TypeInstance;
|
||||||
|
mIdx = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var methodData = &mTypeInstance.[Friend]mMethodDataPtr[mIdx];
|
var methodData = &mTypeInstance.[Friend]mMethodDataPtr[mIdx];
|
||||||
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (methodData.mFlags.HasFlag(.Static)));
|
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (methodData.mFlags.HasFlag(.Static)));
|
||||||
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!methodData.mFlags.HasFlag(.Static)));
|
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!methodData.mFlags.HasFlag(.Static)));
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace System
|
||||||
if (matched.[Friend]mMethodData != null)
|
if (matched.[Friend]mMethodData != null)
|
||||||
return .Err(.MultipleResults);
|
return .Err(.MultipleResults);
|
||||||
else
|
else
|
||||||
matched = methodInfo;
|
matched = methodInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,26 @@ namespace System
|
||||||
return .Ok(matched);
|
return .Ok(matched);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Comptime]
|
||||||
|
public virtual Result<ComptimeMethodInfo, MethodError> GetMethod(StringView methodName, BindingFlags bindingFlags = cDefaultLookup)
|
||||||
|
{
|
||||||
|
ComptimeMethodInfo matched = default;
|
||||||
|
for (let methodInfo in ComptimeMethodInfo.Enumerator(this as TypeInstance, bindingFlags))
|
||||||
|
{
|
||||||
|
if (methodInfo.Name == methodName)
|
||||||
|
{
|
||||||
|
if (matched.mNativeMethodInstance != 0)
|
||||||
|
return .Err(.MultipleResults);
|
||||||
|
else
|
||||||
|
matched = methodInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched.mNativeMethodInstance == 0)
|
||||||
|
return .Err(.NoResults);
|
||||||
|
return .Ok(matched);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual Result<MethodInfo, MethodError> GetMethod(int methodIdx)
|
public virtual Result<MethodInfo, MethodError> GetMethod(int methodIdx)
|
||||||
{
|
{
|
||||||
return .Err(.NoResults);
|
return .Err(.NoResults);
|
||||||
|
@ -123,7 +143,10 @@ namespace System.Reflection
|
||||||
let objType = typeof(Object) as TypeInstance;
|
let objType = typeof(Object) as TypeInstance;
|
||||||
|
|
||||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||||
obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, mInstSize, mInstAlign, 1);
|
int32 stackCount = Compiler.Options.AllocStackCount;
|
||||||
|
if (mAllocStackCountOverride != 0)
|
||||||
|
stackCount = mAllocStackCountOverride;
|
||||||
|
obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, mInstSize, mInstAlign, stackCount);
|
||||||
#else
|
#else
|
||||||
void* mem = new [Align(16)] uint8[mInstSize]* (?);
|
void* mem = new [Align(16)] uint8[mInstSize]* (?);
|
||||||
obj = Internal.UnsafeCastToObject(mem);
|
obj = Internal.UnsafeCastToObject(mem);
|
||||||
|
|
|
@ -20,22 +20,26 @@ namespace System
|
||||||
|
|
||||||
public T Value
|
public T Value
|
||||||
{
|
{
|
||||||
|
[Inline]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Unwrap();
|
return Unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public static implicit operator Result<T>(T value)
|
public static implicit operator Result<T>(T value)
|
||||||
{
|
{
|
||||||
return .Ok(value);
|
return .Ok(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public static implicit operator T(Result<T> result)
|
public static implicit operator T(Result<T> result)
|
||||||
{
|
{
|
||||||
return result.Unwrap();
|
return result.Unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public void IgnoreError()
|
public void IgnoreError()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ using System.Threading;
|
||||||
|
|
||||||
namespace System
|
namespace System
|
||||||
{
|
{
|
||||||
[StaticInitPriority(100)]
|
[StaticInitPriority(101)]
|
||||||
class Runtime
|
static class Runtime
|
||||||
{
|
{
|
||||||
const int32 cVersion = 8;
|
const int32 cVersion = 8;
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ namespace System
|
||||||
function void* (int size) mAlloc;
|
function void* (int size) mAlloc;
|
||||||
function void (void* ptr) mFree;
|
function void (void* ptr) mFree;
|
||||||
function void (Object obj) mObject_Delete;
|
function void (Object obj) mObject_Delete;
|
||||||
function void (Object obj, String str) mObject_ToString;
|
void* mUnused0;
|
||||||
function Type (Object obj) mObject_GetType;
|
function Type (Object obj) mObject_GetType;
|
||||||
function void (Object obj) mObject_GCMarkMembers;
|
function void (Object obj) mObject_GCMarkMembers;
|
||||||
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
|
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
|
||||||
|
@ -141,13 +141,6 @@ namespace System
|
||||||
delete obj;
|
delete obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Object_ToString(Object obj, String str)
|
|
||||||
{
|
|
||||||
#if BF_DBG_RUNTIME
|
|
||||||
obj.ToString(str);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static Type Object_GetType(Object obj)
|
static Type Object_GetType(Object obj)
|
||||||
{
|
{
|
||||||
#if BF_DBG_RUNTIME
|
#if BF_DBG_RUNTIME
|
||||||
|
@ -241,7 +234,6 @@ namespace System
|
||||||
mAlloc = => Alloc;
|
mAlloc = => Alloc;
|
||||||
mFree = => Free;
|
mFree = => Free;
|
||||||
mObject_Delete = => Object_Delete;
|
mObject_Delete = => Object_Delete;
|
||||||
mObject_ToString = => Object_ToString;
|
|
||||||
mObject_GetType = => Object_GetType;
|
mObject_GetType = => Object_GetType;
|
||||||
mObject_GCMarkMembers = => Object_GCMarkMembers;
|
mObject_GCMarkMembers = => Object_GCMarkMembers;
|
||||||
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
|
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
|
||||||
|
|
|
@ -1,5 +1,35 @@
|
||||||
namespace System.Security.Cryptography
|
namespace System.Security.Cryptography
|
||||||
{
|
{
|
||||||
|
struct HashEncode
|
||||||
|
{
|
||||||
|
// Only 63 chars - skip zero
|
||||||
|
const char8[?] cHash64bToChar = .( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
|
||||||
|
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F',
|
||||||
|
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
|
||||||
|
'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_' );
|
||||||
|
public static void HashEncode64(uint64 val, String outStr)
|
||||||
|
{
|
||||||
|
var val;
|
||||||
|
if ((int64)val < 0)
|
||||||
|
{
|
||||||
|
uint64 flippedNum = (uint64)-(int64)val;
|
||||||
|
// Only flip if the encoded result would actually be shorter
|
||||||
|
if (flippedNum <= 0x00FFFFFFFFFFFFFFL)
|
||||||
|
{
|
||||||
|
val = flippedNum;
|
||||||
|
outStr.Append('_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
int charIdx = (int)((val >> (i * 6)) & 0x3F) - 1;
|
||||||
|
if (charIdx != -1)
|
||||||
|
outStr.Append(cHash64bToChar[charIdx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct MD5Hash
|
struct MD5Hash
|
||||||
{
|
{
|
||||||
public uint8[16] mHash;
|
public uint8[16] mHash;
|
||||||
|
@ -50,6 +80,14 @@ namespace System.Security.Cryptography
|
||||||
val.ToString(strBuffer, "X2", null);
|
val.ToString(strBuffer, "X2", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Encode(String outStr)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
HashEncode.HashEncode64(((uint64*)&mHash)[0], outStr);
|
||||||
|
#unwarn
|
||||||
|
HashEncode.HashEncode64(((uint64*)&mHash)[1], outStr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MD5
|
class MD5
|
||||||
|
|
|
@ -16,18 +16,35 @@ namespace System
|
||||||
|
|
||||||
public this(T[] array)
|
public this(T[] array)
|
||||||
{
|
{
|
||||||
|
if (array == null)
|
||||||
|
{
|
||||||
|
this = default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
mPtr = &array.[Friend]GetRef(0);
|
mPtr = &array.[Friend]GetRef(0);
|
||||||
mLength = array.[Friend]mLength;
|
mLength = array.[Friend]mLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public this(T[] array, int index)
|
public this(T[] array, int index)
|
||||||
{
|
{
|
||||||
|
if (array == null)
|
||||||
|
{
|
||||||
|
Debug.Assert(index == 0);
|
||||||
|
this = default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
mPtr = &array[index];
|
mPtr = &array[index];
|
||||||
mLength = array.[Friend]mLength - index;
|
mLength = array.[Friend]mLength - index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public this(T[] array, int index, int length)
|
public this(T[] array, int index, int length)
|
||||||
{
|
{
|
||||||
|
if (array == null)
|
||||||
|
{
|
||||||
|
Debug.Assert(index == 0 && length == 0);
|
||||||
|
this = default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
mPtr = null;
|
mPtr = null;
|
||||||
else
|
else
|
||||||
|
@ -110,13 +127,95 @@ namespace System
|
||||||
|
|
||||||
public ref T this[int index]
|
public ref T this[int index]
|
||||||
{
|
{
|
||||||
[Inline]
|
[Checked]
|
||||||
get
|
get
|
||||||
|
{
|
||||||
|
Runtime.Assert((uint)index < (uint)mLength);
|
||||||
|
return ref mPtr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
get
|
||||||
{
|
{
|
||||||
return ref mPtr[index];
|
return ref mPtr[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref T this[Index index]
|
||||||
|
{
|
||||||
|
[Checked]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
Runtime.Assert((uint)idx < (uint)mLength);
|
||||||
|
return ref mPtr[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
return ref mPtr[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Span<T> this[IndexRange range]
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
[Inline]
|
||||||
|
#endif
|
||||||
|
get
|
||||||
|
{
|
||||||
|
T* start;
|
||||||
|
switch (range.[Friend]mStart)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset):
|
||||||
|
Debug.Assert((uint)offset <= (uint)mLength);
|
||||||
|
start = mPtr + offset;
|
||||||
|
case .FromEnd(let offset):
|
||||||
|
Debug.Assert((uint)offset <= (uint)mLength);
|
||||||
|
start = mPtr + mLength - offset;
|
||||||
|
}
|
||||||
|
T* end;
|
||||||
|
if (range.[Friend]mIsClosed)
|
||||||
|
{
|
||||||
|
switch (range.[Friend]mEnd)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset):
|
||||||
|
Debug.Assert((uint)offset < (uint)mLength);
|
||||||
|
end = mPtr + offset + 1;
|
||||||
|
case .FromEnd(let offset):
|
||||||
|
Debug.Assert((uint)(offset - 1) <= (uint)mLength);
|
||||||
|
end = mPtr + mLength - offset + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (range.[Friend]mEnd)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset):
|
||||||
|
Debug.Assert((uint)offset <= (uint)mLength);
|
||||||
|
end = mPtr + offset;
|
||||||
|
case .FromEnd(let offset):
|
||||||
|
Debug.Assert((uint)offset <= (uint)mLength);
|
||||||
|
end = mPtr + mLength - offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .(start, end - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Span<T> Slice(int index)
|
public Span<T> Slice(int index)
|
||||||
{
|
{
|
||||||
Debug.Assert((uint)index <= (uint)mLength);
|
Debug.Assert((uint)index <= (uint)mLength);
|
||||||
|
@ -200,6 +299,8 @@ namespace System
|
||||||
return Enumerator(this);
|
return Enumerator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReverseEnumerator Reversed => ReverseEnumerator(this);
|
||||||
|
|
||||||
public override void ToString(String strBuffer)
|
public override void ToString(String strBuffer)
|
||||||
{
|
{
|
||||||
strBuffer.Append("(");
|
strBuffer.Append("(");
|
||||||
|
@ -281,6 +382,95 @@ namespace System
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Result<T> GetNext() mut
|
||||||
|
{
|
||||||
|
if (!MoveNext())
|
||||||
|
return .Err;
|
||||||
|
return Current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<T*> GetNextRef() mut
|
||||||
|
{
|
||||||
|
if (!MoveNext())
|
||||||
|
return .Err;
|
||||||
|
return &CurrentRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ReverseEnumerator : IEnumerator<T>, IRefEnumerator<T*>
|
||||||
|
{
|
||||||
|
private Span<T> mList;
|
||||||
|
private int mIndex;
|
||||||
|
private T* mCurrent;
|
||||||
|
|
||||||
|
public this(Span<T> list)
|
||||||
|
{
|
||||||
|
mList = list;
|
||||||
|
mIndex = list.mLength - 1;
|
||||||
|
mCurrent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext() mut
|
||||||
|
{
|
||||||
|
if (mIndex >= 0)
|
||||||
|
{
|
||||||
|
mCurrent = &mList.mPtr[mIndex];
|
||||||
|
mIndex--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return MoveNextRare();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool MoveNextRare() mut
|
||||||
|
{
|
||||||
|
mIndex = mList.mLength + 1;
|
||||||
|
mCurrent = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Current
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return *mCurrent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref T CurrentRef
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ref *mCurrent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Index
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mIndex + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Length
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mList.mLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset() mut
|
||||||
|
{
|
||||||
|
mIndex = 0;
|
||||||
|
mCurrent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Result<T> GetNext() mut
|
public Result<T> GetNext() mut
|
||||||
{
|
{
|
||||||
if (!MoveNext())
|
if (!MoveNext())
|
||||||
|
|
|
@ -329,7 +329,7 @@ namespace System
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert((uint)mLength <= (uint)value);
|
Debug.Assert((uint)value <= (uint)mLength);
|
||||||
mLength = (int_strsize)value;
|
mLength = (int_strsize)value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1010,17 +1010,95 @@ namespace System
|
||||||
|
|
||||||
public ref char8 this[int index]
|
public ref char8 this[int index]
|
||||||
{
|
{
|
||||||
|
[Checked]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
Debug.Assert((uint)index < (uint)mLength);
|
Debug.Assert((uint)index < (uint)mLength);
|
||||||
return ref Ptr[index];
|
return ref Ptr[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ref Ptr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Checked]
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert((uint)index < (uint)mLength);
|
Debug.Assert((uint)index < (uint)mLength);
|
||||||
Ptr[index] = value;
|
Ptr[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Ptr[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref char8 this[Index index]
|
||||||
|
{
|
||||||
|
[Checked]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
Debug.Assert((uint)idx < (uint)mLength);
|
||||||
|
return ref Ptr[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
return ref Ptr[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Checked]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
Debug.Assert((uint)idx < (uint)mLength);
|
||||||
|
Ptr[idx] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
Ptr[idx] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView this[IndexRange range]
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
[Inline]
|
||||||
|
#endif
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return StringView(Ptr, Length)[range];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Concat(params Object[] objects)
|
public void Concat(params Object[] objects)
|
||||||
|
@ -1351,12 +1429,7 @@ namespace System
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains(String str)
|
public bool Contains(StringView str, bool ignoreCase = false)
|
||||||
{
|
|
||||||
return IndexOf(str) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Contains(String str, bool ignoreCase)
|
|
||||||
{
|
{
|
||||||
return IndexOf(str, ignoreCase) != -1;
|
return IndexOf(str, ignoreCase) != -1;
|
||||||
}
|
}
|
||||||
|
@ -1542,7 +1615,7 @@ namespace System
|
||||||
mLength = newLength;
|
mLength = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Insert(int_strsize idx, char8 c)
|
public void Insert(int idx, char8 c)
|
||||||
{
|
{
|
||||||
Contract.Requires(idx >= 0);
|
Contract.Requires(idx >= 0);
|
||||||
|
|
||||||
|
@ -1557,7 +1630,7 @@ namespace System
|
||||||
mLength = newLength;
|
mLength = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Insert(int_strsize idx, char8 c, int count)
|
public void Insert(int idx, char8 c, int count)
|
||||||
{
|
{
|
||||||
Contract.Requires(idx >= 0);
|
Contract.Requires(idx >= 0);
|
||||||
|
|
||||||
|
@ -1576,7 +1649,7 @@ namespace System
|
||||||
mLength = newLength;
|
mLength = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Insert(int_strsize idx, char32 c)
|
public void Insert(int idx, char32 c)
|
||||||
{
|
{
|
||||||
Contract.Requires(idx >= 0);
|
Contract.Requires(idx >= 0);
|
||||||
|
|
||||||
|
@ -1625,7 +1698,7 @@ namespace System
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Insert(int_strsize idx, char32 c, int count)
|
public void Insert(int idx, char32 c, int count)
|
||||||
{
|
{
|
||||||
Contract.Requires(idx >= 0);
|
Contract.Requires(idx >= 0);
|
||||||
|
|
||||||
|
@ -1700,7 +1773,7 @@ namespace System
|
||||||
|
|
||||||
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
|
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
|
||||||
|
|
||||||
// uppercase both char8s - notice that we need just one compare per char8
|
// uppercase both chars - notice that we need just one compare per char
|
||||||
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
|
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
|
||||||
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
|
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
|
||||||
|
|
||||||
|
@ -1708,7 +1781,7 @@ namespace System
|
||||||
if (charA != charB)
|
if (charA != charB)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Next char8
|
// Next char
|
||||||
curA++;curB++;
|
curA++;curB++;
|
||||||
curLength--;
|
curLength--;
|
||||||
}
|
}
|
||||||
|
@ -1733,7 +1806,7 @@ namespace System
|
||||||
|
|
||||||
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
|
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
|
||||||
|
|
||||||
// uppercase both char8s - notice that we need just one compare per char8
|
// uppercase both chars - notice that we need just one compare per char
|
||||||
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
|
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
|
||||||
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
|
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
|
||||||
|
|
||||||
|
@ -1741,7 +1814,7 @@ namespace System
|
||||||
if (charA != charB)
|
if (charA != charB)
|
||||||
return charA - charB;
|
return charA - charB;
|
||||||
|
|
||||||
// Next char8
|
// Next char
|
||||||
a++;b++;
|
a++;b++;
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
|
@ -1761,7 +1834,7 @@ namespace System
|
||||||
int_strsize charB = (int_strsize)*b;
|
int_strsize charB = (int_strsize)*b;
|
||||||
|
|
||||||
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
|
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
|
||||||
// uppercase both char8s - notice that we need just one compare per char8
|
// uppercase both chars - notice that we need just one compare per char
|
||||||
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
|
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
|
||||||
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
|
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
|
||||||
|
|
||||||
|
@ -1769,7 +1842,7 @@ namespace System
|
||||||
if (charA != charB)
|
if (charA != charB)
|
||||||
return charA - charB;
|
return charA - charB;
|
||||||
|
|
||||||
// Next char8
|
// Next char
|
||||||
a++;b++;
|
a++;b++;
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
|
@ -2130,6 +2203,82 @@ namespace System
|
||||||
TrimEnd();
|
TrimEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TrimEnd(char32 trimChar)
|
||||||
|
{
|
||||||
|
let ptr = Ptr;
|
||||||
|
for (int i = mLength - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
char8 c = ptr[i];
|
||||||
|
if (c >= (char8)0x80)
|
||||||
|
{
|
||||||
|
var (c32, idx, len) = GetChar32WithBacktrack(i);
|
||||||
|
if (c32 != trimChar)
|
||||||
|
{
|
||||||
|
if (i < mLength - 1)
|
||||||
|
RemoveToEnd(i + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i = idx;
|
||||||
|
}
|
||||||
|
else if ((char32)c != trimChar)
|
||||||
|
{
|
||||||
|
if (i < mLength - 1)
|
||||||
|
RemoveToEnd(i + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrimEnd(char8 trimChar)
|
||||||
|
{
|
||||||
|
TrimEnd((char32)trimChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrimStart(char32 trimChar)
|
||||||
|
{
|
||||||
|
let ptr = Ptr;
|
||||||
|
for (int i = 0; i < mLength; i++)
|
||||||
|
{
|
||||||
|
char8 c = ptr[i];
|
||||||
|
if (c >= (char8)0x80)
|
||||||
|
{
|
||||||
|
var (c32, len) = GetChar32(i);
|
||||||
|
if (c32 != trimChar)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
Remove(0, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i += len - 1;
|
||||||
|
}
|
||||||
|
else if ((char32)c != trimChar)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
Remove(0, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrimStart(char8 trimChar)
|
||||||
|
{
|
||||||
|
TrimStart((char32)trimChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trim(char32 trimChar)
|
||||||
|
{
|
||||||
|
TrimStart(trimChar);
|
||||||
|
TrimEnd(trimChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trim(char8 trimChar)
|
||||||
|
{
|
||||||
|
TrimStart((.)trimChar);
|
||||||
|
TrimEnd((.)trimChar);
|
||||||
|
}
|
||||||
|
|
||||||
public void Join(StringView sep, IEnumerator<String> enumerable)
|
public void Join(StringView sep, IEnumerator<String> enumerable)
|
||||||
{
|
{
|
||||||
bool isFirst = true;
|
bool isFirst = true;
|
||||||
|
@ -2271,6 +2420,7 @@ namespace System
|
||||||
|
|
||||||
public RawEnumerator RawChars
|
public RawEnumerator RawChars
|
||||||
{
|
{
|
||||||
|
[Inline]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return RawEnumerator(Ptr, 0, mLength);
|
return RawEnumerator(Ptr, 0, mLength);
|
||||||
|
@ -2279,6 +2429,7 @@ namespace System
|
||||||
|
|
||||||
public UTF8Enumerator DecodedChars
|
public UTF8Enumerator DecodedChars
|
||||||
{
|
{
|
||||||
|
[Inline]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return UTF8Enumerator(Ptr, 0, mLength);
|
return UTF8Enumerator(Ptr, 0, mLength);
|
||||||
|
@ -2440,6 +2591,7 @@ namespace System
|
||||||
int_strsize mIdx;
|
int_strsize mIdx;
|
||||||
int_strsize mLength;
|
int_strsize mLength;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public this(char8* ptr, int idx, int length)
|
public this(char8* ptr, int idx, int length)
|
||||||
{
|
{
|
||||||
mPtr = ptr;
|
mPtr = ptr;
|
||||||
|
@ -2449,11 +2601,13 @@ namespace System
|
||||||
|
|
||||||
public char8 Current
|
public char8 Current
|
||||||
{
|
{
|
||||||
|
[Inline]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return mPtr[mIdx];
|
return mPtr[mIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
mPtr[mIdx] = value;
|
mPtr[mIdx] = value;
|
||||||
|
@ -2462,6 +2616,7 @@ namespace System
|
||||||
|
|
||||||
public ref char8 CurrentRef
|
public ref char8 CurrentRef
|
||||||
{
|
{
|
||||||
|
[Inline]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ref mPtr[mIdx];
|
return ref mPtr[mIdx];
|
||||||
|
@ -2470,6 +2625,7 @@ namespace System
|
||||||
|
|
||||||
public int Index
|
public int Index
|
||||||
{
|
{
|
||||||
|
[Inline]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return mIdx;
|
return mIdx;
|
||||||
|
@ -2478,42 +2634,29 @@ namespace System
|
||||||
|
|
||||||
public int Length
|
public int Length
|
||||||
{
|
{
|
||||||
|
[Inline]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return mLength;
|
return mLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
[Inline]
|
||||||
{
|
public Result<char8> GetNext() mut
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool MoveNext() mut
|
|
||||||
{
|
{
|
||||||
++mIdx;
|
++mIdx;
|
||||||
if (mIdx >= mLength)
|
if (mIdx >= mLength)
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<char8> GetNext() mut
|
|
||||||
{
|
|
||||||
if (!MoveNext())
|
|
||||||
return .Err;
|
return .Err;
|
||||||
return Current;
|
return mPtr[mIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public Result<char8*> GetNextRef() mut
|
public Result<char8*> GetNextRef() mut
|
||||||
{
|
{
|
||||||
if (!MoveNext())
|
++mIdx;
|
||||||
|
if (mIdx >= mLength)
|
||||||
return .Err;
|
return .Err;
|
||||||
return &CurrentRef;
|
return &mPtr[mIdx];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2669,6 +2812,14 @@ namespace System
|
||||||
return mMatchPos;
|
return mMatchPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int32 MatchIndex
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mCurCount - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool HasMore
|
public bool HasMore
|
||||||
{
|
{
|
||||||
|
@ -2821,6 +2972,97 @@ namespace System
|
||||||
mLength = length;
|
mLength = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref char8 this[int index]
|
||||||
|
{
|
||||||
|
[Checked]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Runtime.Assert((uint)index < (uint)mLength);
|
||||||
|
return ref mPtr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ref mPtr[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref char8 this[Index index]
|
||||||
|
{
|
||||||
|
[Checked]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
Runtime.Assert((uint)idx < (uint)mLength);
|
||||||
|
return ref mPtr[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Unchecked, Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset): idx = offset;
|
||||||
|
case .FromEnd(let offset): idx = mLength - offset;
|
||||||
|
}
|
||||||
|
return ref mPtr[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView this[IndexRange range]
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
[Inline]
|
||||||
|
#endif
|
||||||
|
get
|
||||||
|
{
|
||||||
|
char8* start;
|
||||||
|
switch (range.[Friend]mStart)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset):
|
||||||
|
Debug.Assert((uint)offset <= (uint)mLength);
|
||||||
|
start = mPtr + offset;
|
||||||
|
case .FromEnd(let offset):
|
||||||
|
Debug.Assert((uint)offset <= (uint)mLength);
|
||||||
|
start = mPtr + mLength - offset;
|
||||||
|
}
|
||||||
|
char8* end;
|
||||||
|
if (range.[Friend]mIsClosed)
|
||||||
|
{
|
||||||
|
switch (range.[Friend]mEnd)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset):
|
||||||
|
Debug.Assert((uint)offset < (uint)mLength);
|
||||||
|
end = mPtr + offset + 1;
|
||||||
|
case .FromEnd(let offset):
|
||||||
|
Debug.Assert((uint)(offset - 1) <= (uint)mLength);
|
||||||
|
end = mPtr + mLength - offset + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (range.[Friend]mEnd)
|
||||||
|
{
|
||||||
|
case .FromFront(let offset):
|
||||||
|
Debug.Assert((uint)offset <= (uint)mLength);
|
||||||
|
end = mPtr + offset;
|
||||||
|
case .FromEnd(let offset):
|
||||||
|
Debug.Assert((uint)offset <= (uint)mLength);
|
||||||
|
end = mPtr + mLength - offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .(start, end - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String.RawEnumerator RawChars
|
public String.RawEnumerator RawChars
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -2914,6 +3156,13 @@ namespace System
|
||||||
return String.[Friend]CompareOrdinalHelper(val1.mPtr, val1.mLength, val2.mPtr, val2.mLength);
|
return String.[Friend]CompareOrdinalHelper(val1.mPtr, val1.mLength, val2.mPtr, val2.mLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int CompareTo(StringView strB, bool ignoreCase = false)
|
||||||
|
{
|
||||||
|
if (ignoreCase)
|
||||||
|
return String.[Friend]CompareOrdinalIgnoreCaseHelper(Ptr, Length, strB.Ptr, strB.Length);
|
||||||
|
return String.[Friend]CompareOrdinalHelper(Ptr, Length, strB.Ptr, strB.Length);
|
||||||
|
}
|
||||||
|
|
||||||
public bool Equals(StringView str)
|
public bool Equals(StringView str)
|
||||||
{
|
{
|
||||||
if (mLength != str.[Friend]mLength)
|
if (mLength != str.[Friend]mLength)
|
||||||
|
@ -3037,9 +3286,9 @@ namespace System
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains(StringView stringView)
|
public bool Contains(StringView stringView, bool ignoreCase = false)
|
||||||
{
|
{
|
||||||
return IndexOf(stringView) != -1;
|
return IndexOf(stringView, ignoreCase) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool StartsWith(StringView b, StringComparison comparisonType = StringComparison.Ordinal)
|
public bool StartsWith(StringView b, StringComparison comparisonType = StringComparison.Ordinal)
|
||||||
|
@ -3130,6 +3379,92 @@ namespace System
|
||||||
TrimEnd();
|
TrimEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TrimEnd(char32 trimChar) mut
|
||||||
|
{
|
||||||
|
let ptr = Ptr;
|
||||||
|
for (int i = mLength - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
char8 c = ptr[i];
|
||||||
|
if (c >= (char8)0x80)
|
||||||
|
{
|
||||||
|
var (c32, idx, len) = GetChar32WithBacktrack(i);
|
||||||
|
if (c32 != trimChar)
|
||||||
|
{
|
||||||
|
if (i < mLength - 1)
|
||||||
|
{
|
||||||
|
mLength = i + 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i = idx;
|
||||||
|
}
|
||||||
|
else if (c != (char32)trimChar)
|
||||||
|
{
|
||||||
|
if (i < mLength - 1)
|
||||||
|
{
|
||||||
|
mLength = i + 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrimEnd(char8 trimChar) mut
|
||||||
|
{
|
||||||
|
TrimEnd((char32)trimChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrimStart(char32 trimChar) mut
|
||||||
|
{
|
||||||
|
let ptr = Ptr;
|
||||||
|
for (int i = 0; i < mLength; i++)
|
||||||
|
{
|
||||||
|
char8 c = ptr[i];
|
||||||
|
if (c >= (char8)0x80)
|
||||||
|
{
|
||||||
|
var (c32, len) = GetChar32(i);
|
||||||
|
if (c32 != trimChar)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
mPtr += i;
|
||||||
|
mLength -= i;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i += len - 1;
|
||||||
|
}
|
||||||
|
else if (c != (char32)trimChar)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
mPtr += i;
|
||||||
|
mLength -= i;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrimStart(char8 trimChar) mut
|
||||||
|
{
|
||||||
|
TrimStart((char32)trimChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trim(char32 trimChar) mut
|
||||||
|
{
|
||||||
|
TrimStart(trimChar);
|
||||||
|
TrimEnd(trimChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trim(char8 trimChar) mut
|
||||||
|
{
|
||||||
|
TrimStart((.)trimChar);
|
||||||
|
TrimEnd((.)trimChar);
|
||||||
|
}
|
||||||
|
|
||||||
public bool StartsWith(char8 c)
|
public bool StartsWith(char8 c)
|
||||||
{
|
{
|
||||||
if (mLength == 0)
|
if (mLength == 0)
|
||||||
|
@ -3137,6 +3472,15 @@ namespace System
|
||||||
return Ptr[0] == c;
|
return Ptr[0] == c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool StartsWith(char32 c)
|
||||||
|
{
|
||||||
|
if (c < '\x80')
|
||||||
|
return StartsWith((char8)c);
|
||||||
|
if (mLength == 0)
|
||||||
|
return false;
|
||||||
|
return UTF8.Decode(Ptr, mLength).c == c;
|
||||||
|
}
|
||||||
|
|
||||||
public bool EndsWith(char8 c)
|
public bool EndsWith(char8 c)
|
||||||
{
|
{
|
||||||
if (mLength == 0)
|
if (mLength == 0)
|
||||||
|
@ -3144,6 +3488,19 @@ namespace System
|
||||||
return Ptr[mLength - 1] == c;
|
return Ptr[mLength - 1] == c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool EndsWith(char32 c)
|
||||||
|
{
|
||||||
|
if (c < '\x80')
|
||||||
|
return EndsWith((char8)c);
|
||||||
|
if (mLength == 0)
|
||||||
|
return false;
|
||||||
|
char8* ptr = Ptr;
|
||||||
|
int idx = mLength - 1;
|
||||||
|
while ((idx > 0) && ((uint8)ptr[idx] & 0xC0 == 0x80))
|
||||||
|
idx--;
|
||||||
|
return UTF8.Decode(ptr + idx, mLength - idx).c == c;
|
||||||
|
}
|
||||||
|
|
||||||
public void QuoteString(String outString)
|
public void QuoteString(String outString)
|
||||||
{
|
{
|
||||||
String.QuoteString(Ptr, Length, outString);
|
String.QuoteString(Ptr, Length, outString);
|
||||||
|
@ -3226,6 +3583,34 @@ namespace System
|
||||||
return StringSplitEnumerator(Ptr, Length, separators, count, options);
|
return StringSplitEnumerator(Ptr, Length, separators, count, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String Intern()
|
||||||
|
{
|
||||||
|
using (String.[Friend]sMonitor.Enter())
|
||||||
|
{
|
||||||
|
bool needsLiteralPass = String.[Friend]sInterns.Count == 0;
|
||||||
|
String* internalLinkPtr = *((String**)(String.[Friend]sStringLiterals));
|
||||||
|
if (internalLinkPtr != String.[Friend]sPrevInternLinkPtr)
|
||||||
|
{
|
||||||
|
String.[Friend]sPrevInternLinkPtr = internalLinkPtr;
|
||||||
|
needsLiteralPass = true;
|
||||||
|
}
|
||||||
|
if (needsLiteralPass)
|
||||||
|
String.[Friend]CheckLiterals(String.[Friend]sStringLiterals);
|
||||||
|
|
||||||
|
String* entryPtr;
|
||||||
|
if (String.[Friend]sInterns.TryAddAlt(this, out entryPtr))
|
||||||
|
{
|
||||||
|
String result = new String(mLength + 1);
|
||||||
|
result.Append(this);
|
||||||
|
result.EnsureNullTerminator();
|
||||||
|
*entryPtr = result;
|
||||||
|
String.[Friend]sOwnedInterns.Add(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return *entryPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static operator StringView (String str)
|
public static operator StringView (String str)
|
||||||
{
|
{
|
||||||
StringView sv;
|
StringView sv;
|
||||||
|
|
|
@ -227,6 +227,26 @@ static
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static mixin DeleteContainerAndDisposeItems(var container)
|
||||||
|
{
|
||||||
|
if (container != null)
|
||||||
|
{
|
||||||
|
for (var value in container)
|
||||||
|
value.Dispose();
|
||||||
|
delete container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static mixin ClearAndDisposeItems(var container)
|
||||||
|
{
|
||||||
|
if (container != null)
|
||||||
|
{
|
||||||
|
for (var value in container)
|
||||||
|
value.Dispose();
|
||||||
|
container.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static mixin DeleteAndNullify(var val)
|
public static mixin DeleteAndNullify(var val)
|
||||||
{
|
{
|
||||||
delete val;
|
delete val;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
namespace System.Text
|
namespace System.Text
|
||||||
{
|
{
|
||||||
|
[StaticInitPriority(100)]
|
||||||
abstract class Encoding
|
abstract class Encoding
|
||||||
{
|
{
|
||||||
public enum DecodeError
|
public enum DecodeError
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
namespace System.Text
|
namespace System.Text
|
||||||
{
|
{
|
||||||
public class UTF16
|
public static class UTF16
|
||||||
{
|
{
|
||||||
public enum EncodeError
|
public enum EncodeError
|
||||||
{
|
{
|
||||||
|
@ -140,10 +140,10 @@ namespace System.Text
|
||||||
|
|
||||||
public static int GetMaxEncodedLen(int utf8Len)
|
public static int GetMaxEncodedLen(int utf8Len)
|
||||||
{
|
{
|
||||||
// Consider all incoming char8s are < \u80, each incoming char88 equals one outgoing char816 (utfLen * 1)
|
// Consider all incoming chars are < \u80, each incoming char8 equals one outgoing char16 (utfLen * 1)
|
||||||
// For char8s from \u80 to \u7FF, then two incoming char88 equals one outgoing char816 (utfLen * 0.5)
|
// For chars from \u80 to \u7FF, then two incoming char8 equals one outgoing char16 (utfLen * 0.5)
|
||||||
// For char8s from \u800 to \u7FFF, then three incoming char88 equals one or two char816s (utfLen * 0.33) to (utfLen * 0.67)
|
// For chars from \u800 to \u7FFF, then three incoming char8 equals one or two char16s (utfLen * 0.33) to (utfLen * 0.67)
|
||||||
// For char8s from \u1000 to \u10FFFF, then four incoming char88 equals two outgoing char816s (utfLen * 0.5)
|
// For chars from \u1000 to \u10FFFF, then four incoming char8 equals two outgoing char16s (utfLen * 0.5)
|
||||||
return utf8Len;
|
return utf8Len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ namespace System.Text
|
||||||
if (c <= '\u{FFFF}')
|
if (c <= '\u{FFFF}')
|
||||||
{
|
{
|
||||||
#if BF_UTF_PEDANTIC
|
#if BF_UTF_PEDANTIC
|
||||||
// Illegal UTF16 char8?
|
// Illegal UTF16 char?
|
||||||
Debug.Assert((c <= '\u{D7FF}') || (c >= '\u{E000}'));
|
Debug.Assert((c <= '\u{D7FF}') || (c >= '\u{E000}'));
|
||||||
#endif
|
#endif
|
||||||
EncodeChar((char16)c);
|
EncodeChar((char16)c);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
namespace System.Text
|
namespace System.Text
|
||||||
{
|
{
|
||||||
class UTF8
|
static class UTF8
|
||||||
{
|
{
|
||||||
public const int8[256] sTrailingBytesForUTF8 =
|
public const int8[256] sTrailingBytesForUTF8 =
|
||||||
.(
|
.(
|
||||||
|
|
|
@ -8,10 +8,11 @@ namespace System.Threading
|
||||||
public delegate void ThreadStart();
|
public delegate void ThreadStart();
|
||||||
public delegate void ParameterizedThreadStart(Object obj);
|
public delegate void ParameterizedThreadStart(Object obj);
|
||||||
|
|
||||||
|
[StaticInitPriority(100)]
|
||||||
public sealed class Thread
|
public sealed class Thread
|
||||||
{
|
{
|
||||||
private int mInternalThread;
|
private int mInternalThread;
|
||||||
private int32 mPriority;
|
private ThreadPriority mPriority = .Normal;
|
||||||
public int32 mMaxStackSize;
|
public int32 mMaxStackSize;
|
||||||
private String mName ~ delete _;
|
private String mName ~ delete _;
|
||||||
private Delegate mDelegate;
|
private Delegate mDelegate;
|
||||||
|
@ -21,7 +22,7 @@ namespace System.Threading
|
||||||
bool mAutoDelete;
|
bool mAutoDelete;
|
||||||
public static Thread sMainThread = new Thread() ~ delete _;
|
public static Thread sMainThread = new Thread() ~ delete _;
|
||||||
|
|
||||||
[StaticInitPriority(101)]
|
[StaticInitPriority(102)]
|
||||||
struct RuntimeThreadInit
|
struct RuntimeThreadInit
|
||||||
{
|
{
|
||||||
static Object Thread_Alloc()
|
static Object Thread_Alloc()
|
||||||
|
@ -67,6 +68,8 @@ namespace System.Threading
|
||||||
|
|
||||||
if (thread.mName != null)
|
if (thread.mName != null)
|
||||||
thread.InformThreadNameChange(thread.mName);
|
thread.InformThreadNameChange(thread.mName);
|
||||||
|
if (thread.mPriority != .Normal)
|
||||||
|
thread.SetPriorityNative((.)thread.mPriority);
|
||||||
|
|
||||||
int32 stackStart = 0;
|
int32 stackStart = 0;
|
||||||
thread.SetStackStart((void*)&stackStart);
|
thread.SetStackStart((void*)&stackStart);
|
||||||
|
@ -219,8 +222,18 @@ namespace System.Threading
|
||||||
|
|
||||||
public ThreadPriority Priority
|
public ThreadPriority Priority
|
||||||
{
|
{
|
||||||
get { return (ThreadPriority)GetPriorityNative(); }
|
get
|
||||||
set { SetPriorityNative((int32)value); }
|
{
|
||||||
|
if (mInternalThread != 0)
|
||||||
|
return (ThreadPriority)GetPriorityNative();
|
||||||
|
return mPriority;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mPriority = value;
|
||||||
|
if (mInternalThread != 0)
|
||||||
|
SetPriorityNative((int32)value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
[CallingConvention(.Cdecl)]
|
[CallingConvention(.Cdecl)]
|
||||||
private extern int32 GetPriorityNative();
|
private extern int32 GetPriorityNative();
|
||||||
|
|
|
@ -253,7 +253,10 @@ namespace System {
|
||||||
if (rule != null)
|
if (rule != null)
|
||||||
rule = rule.Clone();
|
rule = rule.Clone();
|
||||||
oneYearLocFromUtc = new OffsetAndRule(year, currentYear.BaseUtcOffset, rule);
|
oneYearLocFromUtc = new OffsetAndRule(year, currentYear.BaseUtcOffset, rule);
|
||||||
m_oneYearLocalFromUtc = oneYearLocFromUtc;
|
if (Interlocked.CompareExchange(ref m_oneYearLocalFromUtc, null, oneYearLocFromUtc) != null) {
|
||||||
|
delete oneYearLocFromUtc;
|
||||||
|
oneYearLocFromUtc = m_oneYearLocalFromUtc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return oneYearLocFromUtc;
|
return oneYearLocFromUtc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,14 @@ namespace System
|
||||||
|
|
||||||
protected const BindingFlags cDefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
|
protected const BindingFlags cDefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
|
||||||
|
|
||||||
protected int32 mSize;
|
protected int32 mSize;
|
||||||
protected TypeId mTypeId;
|
protected TypeId mTypeId;
|
||||||
protected TypeId mBoxedType;
|
protected TypeId mBoxedType;
|
||||||
protected TypeFlags mTypeFlags;
|
protected TypeFlags mTypeFlags;
|
||||||
protected int32 mMemberDataOffset;
|
protected int32 mMemberDataOffset;
|
||||||
protected TypeCode mTypeCode;
|
protected TypeCode mTypeCode;
|
||||||
protected uint8 mAlign;
|
protected uint8 mAlign;
|
||||||
|
protected uint8 mAllocStackCountOverride;
|
||||||
|
|
||||||
public static TypeId TypeIdEnd
|
public static TypeId TypeIdEnd
|
||||||
{
|
{
|
||||||
|
@ -683,13 +684,7 @@ namespace System
|
||||||
|
|
||||||
namespace System.Reflection
|
namespace System.Reflection
|
||||||
{
|
{
|
||||||
public struct TypeId : int32
|
public struct TypeId : int32 {}
|
||||||
{
|
|
||||||
public Type ToType()
|
|
||||||
{
|
|
||||||
return Type.[Friend]sTypes[(int32)this];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Ordered, AlwaysInclude(AssumeInstantiated=true)]
|
[Ordered, AlwaysInclude(AssumeInstantiated=true)]
|
||||||
public class TypeInstance : Type
|
public class TypeInstance : Type
|
||||||
|
@ -724,6 +719,7 @@ namespace System.Reflection
|
||||||
public int32 mMethodIdx;
|
public int32 mMethodIdx;
|
||||||
public int32 mVirtualIdx;
|
public int32 mVirtualIdx;
|
||||||
public int32 mCustomAttributesIdx;
|
public int32 mCustomAttributesIdx;
|
||||||
|
public int32 mReturnCustomAttributesIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ParamFlags : int16
|
public enum ParamFlags : int16
|
||||||
|
@ -740,6 +736,7 @@ namespace System.Reflection
|
||||||
public TypeId mType;
|
public TypeId mType;
|
||||||
public ParamFlags mParamFlags;
|
public ParamFlags mParamFlags;
|
||||||
public int32 mDefaultIdx;
|
public int32 mDefaultIdx;
|
||||||
|
public int32 mCustomAttributesIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct InterfaceData
|
public struct InterfaceData
|
||||||
|
@ -1137,7 +1134,7 @@ namespace System.Reflection
|
||||||
|
|
||||||
public Type GetGenericArg(int argIdx)
|
public Type GetGenericArg(int argIdx)
|
||||||
{
|
{
|
||||||
return mResolvedTypeRefs[argIdx].ToType();
|
return Type.GetType(mResolvedTypeRefs[argIdx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void GetFullName(String strBuffer)
|
public override void GetFullName(String strBuffer)
|
||||||
|
@ -1191,7 +1188,10 @@ namespace System.Reflection
|
||||||
let genericType = GetGenericArg(0);
|
let genericType = GetGenericArg(0);
|
||||||
let arraySize = [Friend]mInstSize - genericType.Size + genericType.Stride * count;
|
let arraySize = [Friend]mInstSize - genericType.Size + genericType.Stride * count;
|
||||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||||
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, 1);
|
int32 stackCount = Compiler.Options.AllocStackCount;
|
||||||
|
if (mAllocStackCountOverride != 0)
|
||||||
|
stackCount = mAllocStackCountOverride;
|
||||||
|
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount);
|
||||||
#else
|
#else
|
||||||
void* mem = new [Align(16)] uint8[arraySize]* (?);
|
void* mem = new [Align(16)] uint8[arraySize]* (?);
|
||||||
obj = Internal.UnsafeCastToObject(mem);
|
obj = Internal.UnsafeCastToObject(mem);
|
||||||
|
|
|
@ -48,8 +48,8 @@ namespace System
|
||||||
public struct VTable
|
public struct VTable
|
||||||
{
|
{
|
||||||
public function HResult(COM_IUnknown* self, ref Guid riid, void** result) QueryInterface;
|
public function HResult(COM_IUnknown* self, ref Guid riid, void** result) QueryInterface;
|
||||||
public function HResult(COM_IUnknown* self) AddRef;
|
public function uint32(COM_IUnknown* self) AddRef;
|
||||||
public function HResult(COM_IUnknown* self) Release;
|
public function uint32(COM_IUnknown* self) Release;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum HResult : int32
|
public enum HResult : int32
|
||||||
|
|
|
@ -876,7 +876,7 @@ namespace CURL
|
||||||
static extern int curl_easy_perform(void* curl);
|
static extern int curl_easy_perform(void* curl);
|
||||||
|
|
||||||
[CLink, CallingConvention(.Stdcall)]
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
static extern void* curl_easy_getinfo(void* curl, Option option, void* ptr);
|
static extern void* curl_easy_getinfo(void* curl, CurlInfo info, void* ptr);
|
||||||
|
|
||||||
[CLink, CallingConvention(.Stdcall)]
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
static extern void* curl_easy_reset(void* curl);
|
static extern void* curl_easy_reset(void* curl);
|
||||||
|
@ -917,6 +917,12 @@ namespace CURL
|
||||||
return WrapResult((ReturnCode)curl_easy_setopt(mCURL, (int)option, (int)(void*)val.CStr()));
|
return WrapResult((ReturnCode)curl_easy_setopt(mCURL, (int)option, (int)(void*)val.CStr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result<void, ReturnCode> SetOpt(Option option, StringView val)
|
||||||
|
{
|
||||||
|
Debug.Assert((int)option / 10000 == 1);
|
||||||
|
return WrapResult((ReturnCode)curl_easy_setopt(mCURL, (int)option, (int)(void*)scope String(4096)..Append(val).CStr()));
|
||||||
|
}
|
||||||
|
|
||||||
public Result<void, ReturnCode> SetOpt(Option option, int val)
|
public Result<void, ReturnCode> SetOpt(Option option, int val)
|
||||||
{
|
{
|
||||||
Debug.Assert(((int)option / 10000 == 0) || ((int)option / 10000 == 3));
|
Debug.Assert(((int)option / 10000 == 0) || ((int)option / 10000 == 3));
|
||||||
|
@ -935,6 +941,16 @@ namespace CURL
|
||||||
return WrapResult((ReturnCode)curl_easy_setopt(mCURL, (int)option, (int)funcPtr));
|
return WrapResult((ReturnCode)curl_easy_setopt(mCURL, (int)option, (int)funcPtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result<void> GetInfo(CurlInfo info, String val)
|
||||||
|
{
|
||||||
|
char8* ptr = null;
|
||||||
|
curl_easy_getinfo(mCURL, info, &ptr);
|
||||||
|
if (ptr == null)
|
||||||
|
return .Err;
|
||||||
|
val.Append(ptr);
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
public Result<void, ReturnCode> Perform()
|
public Result<void, ReturnCode> Perform()
|
||||||
{
|
{
|
||||||
return WrapResult((ReturnCode)curl_easy_perform(mCURL));
|
return WrapResult((ReturnCode)curl_easy_perform(mCURL));
|
||||||
|
|
|
@ -8,7 +8,8 @@ namespace CURL
|
||||||
{
|
{
|
||||||
class Transfer
|
class Transfer
|
||||||
{
|
{
|
||||||
CURL.Easy mCurl = new CURL.Easy() ~ delete _;
|
CURL.Easy mCurl;
|
||||||
|
bool mOwns;
|
||||||
bool mCancelling = false;
|
bool mCancelling = false;
|
||||||
List<uint8> mData = new List<uint8>() ~ delete _;
|
List<uint8> mData = new List<uint8>() ~ delete _;
|
||||||
Stopwatch mStatsTimer = new Stopwatch() ~ delete _;
|
Stopwatch mStatsTimer = new Stopwatch() ~ delete _;
|
||||||
|
@ -59,7 +60,13 @@ namespace CURL
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
|
mCurl = new CURL.Easy();
|
||||||
|
mOwns = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(CURL.Easy curl)
|
||||||
|
{
|
||||||
|
mCurl = curl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
|
@ -67,6 +74,9 @@ namespace CURL
|
||||||
mCancelling = true;
|
mCancelling = true;
|
||||||
if (mRunning)
|
if (mRunning)
|
||||||
mDoneEvent.WaitFor();
|
mDoneEvent.WaitFor();
|
||||||
|
|
||||||
|
if (mOwns)
|
||||||
|
delete mCurl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetCurBytesPerSecond()
|
int GetCurBytesPerSecond()
|
||||||
|
@ -119,7 +129,7 @@ namespace CURL
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(String url)
|
public void Init(StringView url)
|
||||||
{
|
{
|
||||||
function int(void *p, int dltotal, int dlnow, int ultotal, int ulnow) callback = => Callback;
|
function int(void *p, int dltotal, int dlnow, int ultotal, int ulnow) callback = => Callback;
|
||||||
mCurl.SetOptFunc(.XferInfoFunction, (void*)callback);
|
mCurl.SetOptFunc(.XferInfoFunction, (void*)callback);
|
||||||
|
@ -133,6 +143,13 @@ namespace CURL
|
||||||
mCurl.SetOpt(.URL, url);
|
mCurl.SetOpt(.URL, url);
|
||||||
mCurl.SetOpt(.NoProgress, false);
|
mCurl.SetOpt(.NoProgress, false);
|
||||||
mCurl.SetOpt(.IPResolve, (int)CURL.Easy.IPResolve.V4);
|
mCurl.SetOpt(.IPResolve, (int)CURL.Easy.IPResolve.V4);
|
||||||
|
mCurl.SetOpt(.HTTPGet, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InitPost(String url, String param)
|
||||||
|
{
|
||||||
|
Init(url);
|
||||||
|
mCurl.SetOpt(.Postfields, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result<Span<uint8>> Perform()
|
public Result<Span<uint8>> Perform()
|
||||||
|
@ -178,6 +195,11 @@ namespace CURL
|
||||||
return mResult;
|
return mResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GetContentType(String outContentType)
|
||||||
|
{
|
||||||
|
mCurl.GetInfo(.ContentType, outContentType);
|
||||||
|
}
|
||||||
|
|
||||||
public void Cancel(bool wait = false)
|
public void Cancel(bool wait = false)
|
||||||
{
|
{
|
||||||
mCancelling = true;
|
mCancelling = true;
|
||||||
|
|
|
@ -421,8 +421,13 @@ void BFGC::RawShutdown()
|
||||||
gDbgErrorString = errorStr;
|
gDbgErrorString = errorStr;
|
||||||
gDbgErrorString += "\n";
|
gDbgErrorString += "\n";
|
||||||
|
|
||||||
|
int passLeakCount = 0;
|
||||||
|
|
||||||
for (auto& rawLeak : mSweepInfo.mRawLeaks)
|
for (auto& rawLeak : mSweepInfo.mRawLeaks)
|
||||||
{
|
{
|
||||||
|
if (passLeakCount == 20000) // Only display so many...
|
||||||
|
break;
|
||||||
|
|
||||||
Beefy::String typeName;
|
Beefy::String typeName;
|
||||||
if (rawLeak.mRawAllocData->mType != NULL)
|
if (rawLeak.mRawAllocData->mType != NULL)
|
||||||
typeName = rawLeak.mRawAllocData->mType->GetFullName() + "*";
|
typeName = rawLeak.mRawAllocData->mType->GetFullName() + "*";
|
||||||
|
@ -451,6 +456,8 @@ void BFGC::RawShutdown()
|
||||||
|
|
||||||
if (gDbgErrorString.length() < 256)
|
if (gDbgErrorString.length() < 256)
|
||||||
gDbgErrorString += StrFormat(" %s\n", leakStr.c_str());
|
gDbgErrorString += StrFormat(" %s\n", leakStr.c_str());
|
||||||
|
|
||||||
|
passLeakCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_ASSERT(mSweepInfo.mLeakCount > 0);
|
BF_ASSERT(mSweepInfo.mLeakCount > 0);
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace bf
|
||||||
void*(*Alloc)(intptr size);
|
void*(*Alloc)(intptr size);
|
||||||
void(*Free)(void* ptr);
|
void(*Free)(void* ptr);
|
||||||
void(*Object_Delete)(bf::System::Object* obj);
|
void(*Object_Delete)(bf::System::Object* obj);
|
||||||
void(*Object_ToString)(bf::System::Object* obj, bf::System::String* str);
|
void* mUnused0;
|
||||||
bf::System::Type* (*Object_GetType)(bf::System::Object* obj);
|
bf::System::Type* (*Object_GetType)(bf::System::Object* obj);
|
||||||
void(*Object_GCMarkMembers)(bf::System::Object* obj);
|
void(*Object_GCMarkMembers)(bf::System::Object* obj);
|
||||||
bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId);
|
bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId);
|
||||||
|
|
|
@ -84,8 +84,7 @@ namespace bf
|
||||||
BFRT_EXPORT static Object* UnsafeCastToObject(void* inPtr);
|
BFRT_EXPORT static Object* UnsafeCastToObject(void* inPtr);
|
||||||
BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj);
|
BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj);
|
||||||
BFRT_EXPORT static void ObjectDynCheck(Object* object, int typeId, bool allowNull);
|
BFRT_EXPORT static void ObjectDynCheck(Object* object, int typeId, bool allowNull);
|
||||||
BFRT_EXPORT static void ObjectDynCheckFailed(Object* object, int typeId);
|
BFRT_EXPORT static void ObjectDynCheckFailed(Object* object, int typeId);
|
||||||
BFRT_EXPORT static void Throw(Exception* ex);
|
|
||||||
BFRT_EXPORT static void ThrowIndexOutOfRange(intptr stackOffset);
|
BFRT_EXPORT static void ThrowIndexOutOfRange(intptr stackOffset);
|
||||||
BFRT_EXPORT static void FatalError(String* error, intptr stackOffset = 0);
|
BFRT_EXPORT static void FatalError(String* error, intptr stackOffset = 0);
|
||||||
BFRT_EXPORT static void MemCpy(void* dest, void* src, intptr length);
|
BFRT_EXPORT static void MemCpy(void* dest, void* src, intptr length);
|
||||||
|
@ -215,18 +214,20 @@ static void TestReadCmd(Beefy::String& str);
|
||||||
|
|
||||||
static void Internal_FatalError(const char* error)
|
static void Internal_FatalError(const char* error)
|
||||||
{
|
{
|
||||||
if (gClientPipe != NULL)
|
if ((gClientPipe != NULL) && (!gTestBreakOnFailure))
|
||||||
{
|
{
|
||||||
Beefy::String str = ":TestFatal\t";
|
Beefy::String str = ":TestFatal\t";
|
||||||
str += error;
|
str += error;
|
||||||
|
str.Replace('\n', '\r');
|
||||||
str += "\n";
|
str += "\n";
|
||||||
TestString(str);
|
TestString(str);
|
||||||
|
|
||||||
Beefy::String result;
|
Beefy::String result;
|
||||||
TestReadCmd(result);
|
TestReadCmd(result);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
BfpSystem_FatalError(error, "BEEF FATAL ERROR");
|
BfpSystem_FatalError(error, "BEEF FATAL ERROR");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" BFRT_EXPORT int BF_CALLTYPE ftoa(float val, char* str)
|
extern "C" BFRT_EXPORT int BF_CALLTYPE ftoa(float val, char* str)
|
||||||
|
@ -395,26 +396,21 @@ void* Internal::UnsafeCastToPtr(Object* obj)
|
||||||
return (void*)obj;
|
return (void*)obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Internal::Throw(Exception* ex)
|
|
||||||
{
|
|
||||||
bf::System::String* exStr = gBfRtCallbacks.String_Alloc();
|
|
||||||
gBfRtCallbacks.Object_ToString(ex, exStr);
|
|
||||||
|
|
||||||
Beefy::String errorStr = StrFormat("FATAL: %s", exStr->CStr());
|
|
||||||
SETUP_ERROR(errorStr.c_str(), 1);
|
|
||||||
BF_DEBUG_BREAK();
|
|
||||||
gBfRtCallbacks.DebugMessageData_Fatal();
|
|
||||||
|
|
||||||
printf("Thrown: %s", errorStr.c_str());
|
|
||||||
//TODO: What about capturing callstack?
|
|
||||||
|
|
||||||
exit(3);
|
|
||||||
|
|
||||||
//throw ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Internal::ThrowIndexOutOfRange(intptr stackOffset)
|
void Internal::ThrowIndexOutOfRange(intptr stackOffset)
|
||||||
{
|
{
|
||||||
|
if (gClientPipe != NULL)
|
||||||
|
{
|
||||||
|
if (gTestBreakOnFailure)
|
||||||
|
{
|
||||||
|
SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
|
||||||
|
BF_DEBUG_BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Beefy::String str = ":TestFail\tIndex out of range\n";
|
||||||
|
TestString(str);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((stackOffset != -1) && (::IsDebuggerPresent()))
|
if ((stackOffset != -1) && (::IsDebuggerPresent()))
|
||||||
{
|
{
|
||||||
SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
|
SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
|
||||||
|
@ -426,6 +422,22 @@ void Internal::ThrowIndexOutOfRange(intptr stackOffset)
|
||||||
|
|
||||||
void Internal::FatalError(bf::System::String* error, intptr stackOffset)
|
void Internal::FatalError(bf::System::String* error, intptr stackOffset)
|
||||||
{
|
{
|
||||||
|
if (gClientPipe != NULL)
|
||||||
|
{
|
||||||
|
if (gTestBreakOnFailure)
|
||||||
|
{
|
||||||
|
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
|
||||||
|
BF_DEBUG_BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Beefy::String str = ":TestFail\t";
|
||||||
|
str += error->CStr();
|
||||||
|
str.Replace('\n', '\r');
|
||||||
|
str += "\n";
|
||||||
|
TestString(str);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((stackOffset != -1) && (::IsDebuggerPresent()))
|
if ((stackOffset != -1) && (::IsDebuggerPresent()))
|
||||||
{
|
{
|
||||||
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
|
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
|
||||||
|
@ -659,6 +671,7 @@ void Internal::Test_Error(char* error)
|
||||||
{
|
{
|
||||||
Beefy::String str = ":TestFail\t";
|
Beefy::String str = ":TestFail\t";
|
||||||
str += error;
|
str += error;
|
||||||
|
str.Replace('\n', '\r');
|
||||||
str += "\n";
|
str += "\n";
|
||||||
TestString(str);
|
TestString(str);
|
||||||
}
|
}
|
||||||
|
@ -670,12 +683,7 @@ void Internal::Test_Write(char* strPtr)
|
||||||
{
|
{
|
||||||
Beefy::String str = ":TestWrite\t";
|
Beefy::String str = ":TestWrite\t";
|
||||||
str += strPtr;
|
str += strPtr;
|
||||||
for (char& c : str)
|
str.Replace('\n', '\r');
|
||||||
{
|
|
||||||
if (c == '\n')
|
|
||||||
c = '\r';
|
|
||||||
}
|
|
||||||
|
|
||||||
str += "\n";
|
str += "\n";
|
||||||
TestString(str);
|
TestString(str);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,12 +53,12 @@ void Thread::SetJoinOnDelete(bool joinOnDelete)
|
||||||
|
|
||||||
int Thread::GetPriorityNative()
|
int Thread::GetPriorityNative()
|
||||||
{
|
{
|
||||||
return (int)BfpThread_GetPriority(GetInternalThread()->mThreadHandle, NULL);
|
return (int)BfpThread_GetPriority(GetInternalThread()->mThreadHandle, NULL) + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::SetPriorityNative(int priority)
|
void Thread::SetPriorityNative(int priority)
|
||||||
{
|
{
|
||||||
return BfpThread_SetPriority(GetInternalThread()->mThreadHandle, (BfpThreadPriority)priority, NULL);
|
return BfpThread_SetPriority(GetInternalThread()->mThreadHandle, (BfpThreadPriority)(priority - 2), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Thread::GetIsAlive()
|
bool Thread::GetIsAlive()
|
||||||
|
|
|
@ -234,9 +234,8 @@ namespace BeefPerf
|
||||||
mMainFrame = new MainFrame();
|
mMainFrame = new MainFrame();
|
||||||
mDockingFrame = mMainFrame.mDockingFrame;
|
mDockingFrame = mMainFrame.mDockingFrame;
|
||||||
|
|
||||||
BFWindow.Flags windowFlags = BFWindow.Flags.Border | BFWindow.Flags.SysMenu | //| BFWindow.Flags.CaptureMediaKeys |
|
BFWindow.Flags windowFlags = .Border | .SysMenu | .Caption | .Minimize | .Maximize |
|
||||||
BFWindow.Flags.Caption | BFWindow.Flags.Minimize | BFWindow.Flags.QuitOnClose | BFWindowBase.Flags.Resizable |
|
.QuitOnClose | .Resizable | .Menu;
|
||||||
BFWindow.Flags.Menu | BFWindow.Flags.SysMenu;
|
|
||||||
if (mWantsFullscreen)
|
if (mWantsFullscreen)
|
||||||
windowFlags |= BFWindowBase.Flags.Fullscreen;
|
windowFlags |= BFWindowBase.Flags.Fullscreen;
|
||||||
|
|
||||||
|
@ -336,7 +335,7 @@ namespace BeefPerf
|
||||||
|
|
||||||
void SetupTab(TabbedView tabbedView, String label, Widget widget)
|
void SetupTab(TabbedView tabbedView, String label, Widget widget)
|
||||||
{
|
{
|
||||||
var tabButton = tabbedView.AddTab(label, 0, widget, false);
|
var tabButton = tabbedView.AddTab(label, 0, widget, false, 0);
|
||||||
tabButton.mCloseClickedEvent.Add(new () =>
|
tabButton.mCloseClickedEvent.Add(new () =>
|
||||||
{
|
{
|
||||||
var tabbedView = tabButton.mTabbedView;
|
var tabbedView = tabButton.mTabbedView;
|
||||||
|
@ -921,7 +920,7 @@ namespace BeefPerf
|
||||||
TabbedView tabbedView = FindTabbedView(mDockingFrame, -1, 1);
|
TabbedView tabbedView = FindTabbedView(mDockingFrame, -1, 1);
|
||||||
if (tabbedView != null)
|
if (tabbedView != null)
|
||||||
{
|
{
|
||||||
tabButton = tabbedView.AddTab(name, width, tabContent, ownsContent);
|
tabButton = tabbedView.AddTab(name, width, tabContent, ownsContent, 0);
|
||||||
result = ShowTabResult.OpenedNew;
|
result = ShowTabResult.OpenedNew;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,7 +311,7 @@ namespace BeefPerf
|
||||||
{
|
{
|
||||||
var str = scope::String();
|
var str = scope::String();
|
||||||
if (argView.UnQuoteString(str) case .Err)
|
if (argView.UnQuoteString(str) case .Err)
|
||||||
Fail("Failed to unquote string");
|
Fail($"Failed to unquote string: {argView}\nCmd:{cmdLineView}");
|
||||||
args.Add(str);
|
args.Add(str);
|
||||||
isLiteralString = false;
|
isLiteralString = false;
|
||||||
}
|
}
|
||||||
|
@ -322,7 +322,7 @@ namespace BeefPerf
|
||||||
case .Ok(let val):
|
case .Ok(let val):
|
||||||
args.Add(scope:: box val);
|
args.Add(scope:: box val);
|
||||||
case .Err:
|
case .Err:
|
||||||
Fail("Failed to parse float");
|
Fail($"Failed to parse float: {argView}\nCmd:{cmdLineView}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,7 @@ namespace BeefPerf
|
||||||
case .Ok(let val):
|
case .Ok(let val):
|
||||||
args.Add(scope:: box val);
|
args.Add(scope:: box val);
|
||||||
case .Err:
|
case .Err:
|
||||||
Fail("Failed to parse double");
|
Fail($"Failed to parse double: {argView}\nCmd:{cmdLineView}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,7 +344,7 @@ namespace BeefPerf
|
||||||
case .Ok(let val):
|
case .Ok(let val):
|
||||||
args.Add(scope:: box val);
|
args.Add(scope:: box val);
|
||||||
case .Err:
|
case .Err:
|
||||||
Fail("Failed to parse int");
|
Fail($"Failed to parse int: {argView}\nCmd:{cmdLineView}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -610,6 +610,23 @@ BF_EXPORT void BF_CALLTYPE Gfx_DrawQuads(TextureSegment* textureSegment, Default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BF_EXPORT void BF_CALLTYPE Gfx_DrawIndexedVertices(int vertexSize, void* vtxData, int vtxCount, uint16* idxData, int idxCount)
|
||||||
|
{
|
||||||
|
DrawLayer* drawLayer = gBFApp->mRenderDevice->mCurDrawLayer;
|
||||||
|
|
||||||
|
uint16 idxOfs;
|
||||||
|
void* drawBatchVtxPtr;
|
||||||
|
uint16* drawBatchIdxPtr;
|
||||||
|
gBFApp->mRenderDevice->mCurDrawLayer->AllocIndexed(vtxCount, idxCount, (void**)&drawBatchVtxPtr, &drawBatchIdxPtr, &idxOfs);
|
||||||
|
BF_ASSERT(gBFApp->mRenderDevice->mCurDrawLayer->mCurDrawBatch->mVtxSize == vertexSize);
|
||||||
|
|
||||||
|
uint16* idxPtr = idxData;
|
||||||
|
for (int idxIdx = 0; idxIdx < idxCount; idxIdx++)
|
||||||
|
*(drawBatchIdxPtr++) = *(idxPtr++) + idxOfs;
|
||||||
|
|
||||||
|
memcpy(drawBatchVtxPtr, vtxData, vertexSize * vtxCount);
|
||||||
|
}
|
||||||
|
|
||||||
BF_EXPORT void BF_CALLTYPE Gfx_DrawIndexedVertices2D(int vertexSize, void* vtxData, int vtxCount, uint16* idxData, int idxCount, float a, float b, float c, float d, float tx, float ty, float z)
|
BF_EXPORT void BF_CALLTYPE Gfx_DrawIndexedVertices2D(int vertexSize, void* vtxData, int vtxCount, uint16* idxData, int idxCount, float a, float b, float c, float d, float tx, float ty, float z)
|
||||||
{
|
{
|
||||||
DrawLayer* drawLayer = gBFApp->mRenderDevice->mCurDrawLayer;
|
DrawLayer* drawLayer = gBFApp->mRenderDevice->mCurDrawLayer;
|
||||||
|
@ -643,14 +660,14 @@ BF_EXPORT void BF_CALLTYPE Gfx_DrawIndexedVertices2D(int vertexSize, void* vtxDa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_EXPORT void BF_CALLTYPE Gfx_SetShaderConstantData(int slotIdx, void* constData, int size)
|
BF_EXPORT void BF_CALLTYPE Gfx_SetShaderConstantData(int usageIdx, int slotIdx, void* constData, int size)
|
||||||
{
|
{
|
||||||
gBFApp->mRenderDevice->mCurDrawLayer->SetShaderConstantData(slotIdx, constData, size);
|
gBFApp->mRenderDevice->mCurDrawLayer->SetShaderConstantData(usageIdx, slotIdx, constData, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_EXPORT void BF_CALLTYPE Gfx_SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount)
|
BF_EXPORT void BF_CALLTYPE Gfx_SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount)
|
||||||
{
|
{
|
||||||
gBFApp->mRenderDevice->mCurDrawLayer->SetShaderConstantDataTyped(slotIdx, constData, size, typeData, typeCount);
|
gBFApp->mRenderDevice->mCurDrawLayer->SetShaderConstantDataTyped(usageIdx, slotIdx, constData, size, typeData, typeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_EXPORT void BF_CALLTYPE Gfx_QueueRenderCmd(RenderCmd* renderCmd)
|
BF_EXPORT void BF_CALLTYPE Gfx_QueueRenderCmd(RenderCmd* renderCmd)
|
||||||
|
@ -678,6 +695,16 @@ BF_EXPORT void BF_CALLTYPE RenderState_Delete(RenderState* renderState)
|
||||||
delete renderState;
|
delete renderState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BF_EXPORT void BF_CALLTYPE RenderState_SetTexWrap(RenderState* renderState, bool texWrap)
|
||||||
|
{
|
||||||
|
renderState->SetTexWrap(texWrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
BF_EXPORT void BF_CALLTYPE RenderState_SetWireframe(RenderState* renderState, bool wireframe)
|
||||||
|
{
|
||||||
|
renderState->SetWireframe(wireframe);
|
||||||
|
}
|
||||||
|
|
||||||
BF_EXPORT void BF_CALLTYPE RenderState_SetClip(RenderState* renderState, float x, float y, float width, float height)
|
BF_EXPORT void BF_CALLTYPE RenderState_SetClip(RenderState* renderState, float x, float y, float width, float height)
|
||||||
{
|
{
|
||||||
BF_ASSERT((width >= 0) && (height >= 0));
|
BF_ASSERT((width >= 0) && (height >= 0));
|
||||||
|
@ -715,6 +742,11 @@ BF_EXPORT void BF_CALLTYPE RenderState_SetDepthWrite(RenderState* renderState, i
|
||||||
renderState->SetWriteDepthBuffer(depthWrite != 0);
|
renderState->SetWriteDepthBuffer(depthWrite != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BF_EXPORT void BF_CALLTYPE RenderState_SetTopology(RenderState* renderState, int topology)
|
||||||
|
{
|
||||||
|
renderState->SetTopology((Topology3D)topology);
|
||||||
|
}
|
||||||
|
|
||||||
BF_EXPORT Shader* BF_CALLTYPE Gfx_LoadShader(const char* fileName, VertexDefinition* vertexDefinition)
|
BF_EXPORT Shader* BF_CALLTYPE Gfx_LoadShader(const char* fileName, VertexDefinition* vertexDefinition)
|
||||||
{
|
{
|
||||||
return gBFApp->mRenderDevice->LoadShader(fileName, vertexDefinition);
|
return gBFApp->mRenderDevice->LoadShader(fileName, vertexDefinition);
|
||||||
|
|
|
@ -445,6 +445,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
|
||||||
<ClCompile Include="FileStream.cpp" />
|
<ClCompile Include="FileStream.cpp" />
|
||||||
<ClCompile Include="gfx\DrawLayer.cpp" />
|
<ClCompile Include="gfx\DrawLayer.cpp" />
|
||||||
<ClCompile Include="gfx\FTFont.cpp" />
|
<ClCompile Include="gfx\FTFont.cpp" />
|
||||||
|
<ClCompile Include="gfx\glTF.cpp" />
|
||||||
<ClCompile Include="gfx\ModelDef.cpp" />
|
<ClCompile Include="gfx\ModelDef.cpp" />
|
||||||
<ClCompile Include="gfx\ModelInstance.cpp" />
|
<ClCompile Include="gfx\ModelInstance.cpp" />
|
||||||
<ClCompile Include="gfx\RenderCmd.cpp" />
|
<ClCompile Include="gfx\RenderCmd.cpp" />
|
||||||
|
@ -1929,16 +1930,20 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
|
||||||
<ClCompile Include="util\BSpline.cpp" />
|
<ClCompile Include="util\BSpline.cpp" />
|
||||||
<ClCompile Include="util\CatmullRom.cpp" />
|
<ClCompile Include="util\CatmullRom.cpp" />
|
||||||
<ClCompile Include="util\ChunkedDataBuffer.cpp" />
|
<ClCompile Include="util\ChunkedDataBuffer.cpp" />
|
||||||
|
<ClCompile Include="util\Compress.cpp" />
|
||||||
<ClCompile Include="util\CubicFuncSpline.cpp" />
|
<ClCompile Include="util\CubicFuncSpline.cpp" />
|
||||||
<ClCompile Include="util\CubicSpline.cpp" />
|
<ClCompile Include="util\CubicSpline.cpp" />
|
||||||
<ClCompile Include="util\Hash.cpp" />
|
<ClCompile Include="util\Hash.cpp" />
|
||||||
<ClCompile Include="util\Heap.cpp" />
|
<ClCompile Include="util\Heap.cpp" />
|
||||||
|
<ClCompile Include="util\Json.cpp" />
|
||||||
<ClCompile Include="util\MappedFile.cpp" />
|
<ClCompile Include="util\MappedFile.cpp" />
|
||||||
|
<ClCompile Include="util\MathUtils.cpp" />
|
||||||
<ClCompile Include="util\Matrix4.cpp" />
|
<ClCompile Include="util\Matrix4.cpp" />
|
||||||
<ClCompile Include="util\PerfTimer.cpp" />
|
<ClCompile Include="util\PerfTimer.cpp" />
|
||||||
<ClCompile Include="util\Point.cpp" />
|
<ClCompile Include="util\Point.cpp" />
|
||||||
<ClCompile Include="util\PolySpline.cpp" />
|
<ClCompile Include="util\PolySpline.cpp" />
|
||||||
<ClCompile Include="util\Quaternion.cpp" />
|
<ClCompile Include="util\Quaternion.cpp" />
|
||||||
|
<ClCompile Include="util\Sphere.cpp" />
|
||||||
<ClCompile Include="util\StackHelper.cpp" />
|
<ClCompile Include="util\StackHelper.cpp" />
|
||||||
<ClCompile Include="util\String.cpp" />
|
<ClCompile Include="util\String.cpp" />
|
||||||
<ClCompile Include="util\ThreadPool.cpp" />
|
<ClCompile Include="util\ThreadPool.cpp" />
|
||||||
|
@ -1958,6 +1963,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
|
||||||
<ClInclude Include="gfx\DrawLayer.h" />
|
<ClInclude Include="gfx\DrawLayer.h" />
|
||||||
<ClInclude Include="gfx\Font.h" />
|
<ClInclude Include="gfx\Font.h" />
|
||||||
<ClInclude Include="gfx\FTFont.h" />
|
<ClInclude Include="gfx\FTFont.h" />
|
||||||
|
<ClInclude Include="gfx\glTF.h" />
|
||||||
<ClInclude Include="gfx\ModelDef.h" />
|
<ClInclude Include="gfx\ModelDef.h" />
|
||||||
<ClInclude Include="gfx\ModelInstance.h" />
|
<ClInclude Include="gfx\ModelInstance.h" />
|
||||||
<ClInclude Include="gfx\RenderCmd.h" />
|
<ClInclude Include="gfx\RenderCmd.h" />
|
||||||
|
@ -2152,6 +2158,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
|
||||||
<ClInclude Include="util\CatmullRom.h" />
|
<ClInclude Include="util\CatmullRom.h" />
|
||||||
<ClInclude Include="Util\ChunkedDataBuffer.h" />
|
<ClInclude Include="Util\ChunkedDataBuffer.h" />
|
||||||
<ClInclude Include="util\ChunkedVector.h" />
|
<ClInclude Include="util\ChunkedVector.h" />
|
||||||
|
<ClInclude Include="util\Compress.h" />
|
||||||
<ClInclude Include="util\CritSect.h" />
|
<ClInclude Include="util\CritSect.h" />
|
||||||
<ClInclude Include="util\CubicFuncSpline.h" />
|
<ClInclude Include="util\CubicFuncSpline.h" />
|
||||||
<ClInclude Include="util\CubicSpline.h" />
|
<ClInclude Include="util\CubicSpline.h" />
|
||||||
|
@ -2161,7 +2168,9 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
|
||||||
<ClInclude Include="util\Hash.h" />
|
<ClInclude Include="util\Hash.h" />
|
||||||
<ClInclude Include="util\HashSet.h" />
|
<ClInclude Include="util\HashSet.h" />
|
||||||
<ClInclude Include="util\Heap.h" />
|
<ClInclude Include="util\Heap.h" />
|
||||||
|
<ClInclude Include="util\Json.h" />
|
||||||
<ClInclude Include="util\MappedFile.h" />
|
<ClInclude Include="util\MappedFile.h" />
|
||||||
|
<ClInclude Include="util\MathUtils.h" />
|
||||||
<ClInclude Include="util\Matrix4.h" />
|
<ClInclude Include="util\Matrix4.h" />
|
||||||
<ClInclude Include="util\MultiHashSet.h" />
|
<ClInclude Include="util\MultiHashSet.h" />
|
||||||
<ClInclude Include="util\PerfTimer.h" />
|
<ClInclude Include="util\PerfTimer.h" />
|
||||||
|
@ -2172,6 +2181,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
|
||||||
<ClInclude Include="util\Rect.h" />
|
<ClInclude Include="util\Rect.h" />
|
||||||
<ClInclude Include="util\SizedArray.h" />
|
<ClInclude Include="util\SizedArray.h" />
|
||||||
<ClInclude Include="util\SLIList.h" />
|
<ClInclude Include="util\SLIList.h" />
|
||||||
|
<ClInclude Include="util\Sphere.h" />
|
||||||
<ClInclude Include="util\StackHelper.h" />
|
<ClInclude Include="util\StackHelper.h" />
|
||||||
<ClInclude Include="util\String.h" />
|
<ClInclude Include="util\String.h" />
|
||||||
<ClInclude Include="util\ThreadPool.h" />
|
<ClInclude Include="util\ThreadPool.h" />
|
||||||
|
|
|
@ -707,6 +707,21 @@
|
||||||
<ClCompile Include="util\Heap.cpp">
|
<ClCompile Include="util\Heap.cpp">
|
||||||
<Filter>src\util</Filter>
|
<Filter>src\util</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="gfx\glTF.cpp">
|
||||||
|
<Filter>src\gfx</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="util\Json.cpp">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="util\MathUtils.cpp">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="util\Sphere.cpp">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="util\Compress.cpp">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Common.h">
|
<ClInclude Include="Common.h">
|
||||||
|
@ -1075,6 +1090,21 @@
|
||||||
<ClInclude Include="util\Heap.h">
|
<ClInclude Include="util\Heap.h">
|
||||||
<Filter>src\util</Filter>
|
<Filter>src\util</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="gfx\glTF.h">
|
||||||
|
<Filter>src\gfx</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="util\Json.h">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="util\MathUtils.h">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="util\Sphere.h">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="util\Compress.h">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">
|
<CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">
|
||||||
|
|
|
@ -278,6 +278,7 @@ file(GLOB SRC_FILES
|
||||||
util/BSpline.cpp
|
util/BSpline.cpp
|
||||||
util/CatmullRom.cpp
|
util/CatmullRom.cpp
|
||||||
util/ChunkedDataBuffer.cpp
|
util/ChunkedDataBuffer.cpp
|
||||||
|
util/Compress.cpp
|
||||||
util/CubicFuncSpline.cpp
|
util/CubicFuncSpline.cpp
|
||||||
util/CubicSpline.cpp
|
util/CubicSpline.cpp
|
||||||
util/FileEnumerator.cpp
|
util/FileEnumerator.cpp
|
||||||
|
@ -285,11 +286,13 @@ file(GLOB SRC_FILES
|
||||||
util/Heap.cpp
|
util/Heap.cpp
|
||||||
util/Json.cpp
|
util/Json.cpp
|
||||||
util/MappedFile.cpp
|
util/MappedFile.cpp
|
||||||
|
util/MathUtils.cpp
|
||||||
util/Matrix4.cpp
|
util/Matrix4.cpp
|
||||||
util/PerfTimer.cpp
|
util/PerfTimer.cpp
|
||||||
util/Point.cpp
|
util/Point.cpp
|
||||||
util/PolySpline.cpp
|
util/PolySpline.cpp
|
||||||
util/Quaternion.cpp
|
util/Quaternion.cpp
|
||||||
|
util/Sphere.cpp
|
||||||
util/String.cpp
|
util/String.cpp
|
||||||
util/StackHelper.cpp
|
util/StackHelper.cpp
|
||||||
util/ThreadPool.cpp
|
util/ThreadPool.cpp
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "platform/PlatformHelper.h"
|
#include "platform/PlatformHelper.h"
|
||||||
|
|
||||||
#ifndef BF_SMALL
|
#ifndef BF_SMALL
|
||||||
|
#define STB_SPRINTF_DECORATE(name) BF_stbsp_##name
|
||||||
#define STB_SPRINTF_IMPLEMENTATION
|
#define STB_SPRINTF_IMPLEMENTATION
|
||||||
#include "third_party/stb/stb_sprintf.h"
|
#include "third_party/stb/stb_sprintf.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -811,7 +812,7 @@ String Beefy::vformat(const char* fmt, va_list argPtr)
|
||||||
{
|
{
|
||||||
String str;
|
String str;
|
||||||
char buf[STB_SPRINTF_MIN];
|
char buf[STB_SPRINTF_MIN];
|
||||||
stbsp_vsprintfcb(StbspCallback, (void*)&str, buf, fmt, argPtr);
|
BF_stbsp_vsprintfcb(StbspCallback, (void*)&str, buf, fmt, argPtr);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -943,6 +944,21 @@ char* Beefy::LoadTextData(const StringImpl& path, int* size)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Beefy::LoadTextData(const StringImpl& path, StringImpl& str)
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
char* data = LoadTextData(path, &size);
|
||||||
|
if (data == NULL)
|
||||||
|
return false;
|
||||||
|
if ((str.mAllocSizeAndFlags & StringImpl::DynAllocFlag) != 0)
|
||||||
|
str.Release();
|
||||||
|
str.mPtr = data;
|
||||||
|
str.mAllocSizeAndFlags = size | StringImpl::DynAllocFlag | StringImpl::StrPtrFlag;
|
||||||
|
str.mLength = size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef BF_MINGW
|
#ifdef BF_MINGW
|
||||||
unsigned long long __cdecl _byteswap_uint64(unsigned long long _Int64)
|
unsigned long long __cdecl _byteswap_uint64(unsigned long long _Int64)
|
||||||
{
|
{
|
||||||
|
@ -1262,4 +1278,5 @@ bool Beefy::RecursiveDeleteDirectory(const StringImpl& dirPath)
|
||||||
void Beefy::BFFatalError(const char* message, const char* file, int line)
|
void Beefy::BFFatalError(const char* message, const char* file, int line)
|
||||||
{
|
{
|
||||||
BFFatalError(String(message), String(file), line);
|
BFFatalError(String(message), String(file), line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,6 +220,7 @@ int32 GetHighestBitSet(int32 n);
|
||||||
|
|
||||||
uint8* LoadBinaryData(const StringImpl& path, int* size);
|
uint8* LoadBinaryData(const StringImpl& path, int* size);
|
||||||
char* LoadTextData(const StringImpl& path, int* size);
|
char* LoadTextData(const StringImpl& path, int* size);
|
||||||
|
bool LoadTextData(const StringImpl& path, StringImpl& str);
|
||||||
int64 GetFileTimeWrite(const StringImpl& path);
|
int64 GetFileTimeWrite(const StringImpl& path);
|
||||||
String GetFileDir(const StringImpl& path);
|
String GetFileDir(const StringImpl& path);
|
||||||
String GetFileName(const StringImpl& path);
|
String GetFileName(const StringImpl& path);
|
||||||
|
|
|
@ -49,6 +49,14 @@ public:
|
||||||
Read((void*) &val, sizeof(T));
|
Read((void*) &val, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T ReadT()
|
||||||
|
{
|
||||||
|
T val;
|
||||||
|
Read((void*)&val, sizeof(T));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Write(float val);
|
virtual void Write(float val);
|
||||||
virtual void Write(uint8 val);
|
virtual void Write(uint8 val);
|
||||||
virtual void Write(int8 val);
|
virtual void Write(int8 val);
|
||||||
|
|
|
@ -219,7 +219,8 @@ void SysFileStream::SetSizeFast(int size)
|
||||||
|
|
||||||
int curPos = GetPos();
|
int curPos = GetPos();
|
||||||
SetPos(size);
|
SetPos(size);
|
||||||
BfpFile_Truncate(mFile);
|
BfpFileResult result = BfpFileResult_Ok;
|
||||||
|
BfpFile_Truncate(mFile, &result);
|
||||||
SetPos(curPos);
|
SetPos(curPos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ class Span
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
T* mVals;
|
T* mVals;
|
||||||
int mSize;
|
intptr mSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Iterator
|
struct Iterator
|
||||||
|
@ -47,16 +47,17 @@ public:
|
||||||
|
|
||||||
Span()
|
Span()
|
||||||
{
|
{
|
||||||
|
mVals = NULL;
|
||||||
|
mSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span(T* mPtr, int size)
|
Span(T* mPtr, intptr size)
|
||||||
{
|
{
|
||||||
mSize = (int)refVec.size();
|
mVals = mPtr;
|
||||||
mVals = NULL;
|
mSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator[](int idx) const
|
T& operator[](intptr idx) const
|
||||||
{
|
{
|
||||||
return mVals[idx];
|
return mVals[idx];
|
||||||
}
|
}
|
||||||
|
@ -76,7 +77,7 @@ public:
|
||||||
return mVals[mSize - 1];
|
return mVals[mSize - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int size() const
|
intptr size() const
|
||||||
{
|
{
|
||||||
return mSize;
|
return mSize;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +92,7 @@ public:
|
||||||
return mSize == 0;
|
return mSize == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
T Get(int idx)
|
T Get(intptr idx)
|
||||||
{
|
{
|
||||||
if ((idx < 0) || (idx >= mSize))
|
if ((idx < 0) || (idx >= mSize))
|
||||||
return (T)0;
|
return (T)0;
|
||||||
|
@ -99,7 +100,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T2>
|
template <typename T2>
|
||||||
T2 GetAs(int idx)
|
T2 GetAs(intptr idx)
|
||||||
{
|
{
|
||||||
if ((idx < 0) || (idx >= mSize))
|
if ((idx < 0) || (idx >= mSize))
|
||||||
return (T2)0;
|
return (T2)0;
|
||||||
|
@ -120,7 +121,7 @@ public:
|
||||||
return mVals[0];
|
return mVals[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSize(int size)
|
void SetSize(intptr size)
|
||||||
{
|
{
|
||||||
BF_ASSERT(size <= mSize);
|
BF_ASSERT(size <= mSize);
|
||||||
mSize = size;
|
mSize = size;
|
||||||
|
|
|
@ -339,9 +339,9 @@ void DrawLayer::SetTexture(int texIdx, Texture* texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawLayer::SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount)
|
void DrawLayer::SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount)
|
||||||
{
|
{
|
||||||
SetShaderConstantData(slotIdx, constData, size);
|
SetShaderConstantData(usageIdx, slotIdx, constData, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -390,5 +390,6 @@ BF_EXPORT void BF_CALLTYPE DrawLayer_DrawToRenderTarget(DrawLayer* drawLayer, Te
|
||||||
renderDevice->PhysSetRenderState(renderDevice->mDefaultRenderState);
|
renderDevice->PhysSetRenderState(renderDevice->mDefaultRenderState);
|
||||||
renderDevice->PhysSetRenderTarget(textureSegment->mTexture);
|
renderDevice->PhysSetRenderTarget(textureSegment->mTexture);
|
||||||
drawLayer->Draw();
|
drawLayer->Draw();
|
||||||
|
drawLayer->Clear();
|
||||||
renderDevice->mCurRenderTarget = prevTarget;
|
renderDevice->mCurRenderTarget = prevTarget;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,8 +99,8 @@ public:
|
||||||
virtual DrawBatch* AllocateBatch(int minVtxCount, int minIdxCount);
|
virtual DrawBatch* AllocateBatch(int minVtxCount, int minIdxCount);
|
||||||
void QueueRenderCmd(RenderCmd* renderCmd);
|
void QueueRenderCmd(RenderCmd* renderCmd);
|
||||||
virtual RenderCmd* CreateSetTextureCmd(int textureIdx, Texture* texture) = 0;
|
virtual RenderCmd* CreateSetTextureCmd(int textureIdx, Texture* texture) = 0;
|
||||||
virtual void SetShaderConstantData(int slotIdx, void* constData, int size) = 0;
|
virtual void SetShaderConstantData(int usageIdx, int slotIdx, void* constData, int size) = 0;
|
||||||
virtual void SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount);
|
virtual void SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DrawLayer();
|
DrawLayer();
|
||||||
|
|
|
@ -144,7 +144,16 @@ bool FTFont::Load(const StringImpl& fileName, float pointSize)
|
||||||
|
|
||||||
face->mFileName = fileName;
|
face->mFileName = fileName;
|
||||||
FT_Face ftFace = NULL;
|
FT_Face ftFace = NULL;
|
||||||
auto error = FT_New_Face(gFTLibrary, fileName.c_str(), 0, &ftFace);
|
|
||||||
|
String useFileName = fileName;
|
||||||
|
int faceIdx = 0;
|
||||||
|
int atPos = (int)useFileName.IndexOf('@');
|
||||||
|
if (atPos != -1)
|
||||||
|
{
|
||||||
|
faceIdx = atoi(useFileName.c_str() + atPos + 1);
|
||||||
|
useFileName.RemoveToEnd(atPos);
|
||||||
|
}
|
||||||
|
auto error = FT_New_Face(gFTLibrary, useFileName.c_str(), faceIdx, &ftFace);
|
||||||
face->mFTFace = ftFace;
|
face->mFTFace = ftFace;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue