mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-30 21:36:00 +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]
|
||||
Description = "BeefBuild"
|
||||
FileVersion = "0.43.1"
|
||||
FileVersion = "0.43.2"
|
||||
|
||||
[Configs.Debug.Win32]
|
||||
TargetName = ""
|
||||
|
|
|
@ -15,6 +15,9 @@ CLibType = "Static"
|
|||
BeefLibType = "Static"
|
||||
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]
|
||||
OtherLinkFlags = ""
|
||||
PreprocessorMacros = ["RELEASE", "BF32"]
|
||||
|
@ -23,6 +26,9 @@ PreprocessorMacros = ["RELEASE", "BF32"]
|
|||
OtherLinkFlags = "$(LinkFlags) $(ProjectDir)/dist/BeefySysLib64.lib"
|
||||
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.dll\")", "CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.pdb\")"]
|
||||
|
||||
[Configs.Release.Linux64]
|
||||
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/libBeefySysLib.so\")"]
|
||||
|
||||
[Configs.Paranoid.Win32]
|
||||
CLibType = "Static"
|
||||
BeefLibType = "Static"
|
||||
|
@ -38,3 +44,15 @@ BeefLibType = "Static"
|
|||
[Configs.Test.Win64]
|
||||
CLibType = "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, 0, 0, 1);*/
|
||||
|
||||
mGraphics.SetShaderConstantData(0, &mColorMatrix.ValueRef, mColorMatrixDataDef);
|
||||
mGraphics.SetVertexShaderConstantData(0, &mColorMatrix.ValueRef, mColorMatrixDataDef);
|
||||
}
|
||||
window.Draw(mGraphics);
|
||||
window.PostDraw(mGraphics);
|
||||
|
|
|
@ -295,11 +295,13 @@ namespace Beefy
|
|||
|
||||
public static Result<void> WriteTextFile(StringView path, StringView text)
|
||||
{
|
||||
var stream = scope FileStream();
|
||||
if (stream.Create(path) case .Err)
|
||||
{
|
||||
var stream = scope UnbufferedFileStream();
|
||||
if (stream.Open(path, .OpenOrCreate, .Write) case .Err)
|
||||
return .Err;
|
||||
}
|
||||
|
||||
if (stream.SetLength(text.Length) case .Err)
|
||||
return .Err;
|
||||
|
||||
if (stream.WriteStrUnsized(text) case .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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Matrix4 matrix;
|
||||
|
@ -190,25 +203,23 @@ namespace Beefy.geom
|
|||
public static Matrix4 Multiply(Matrix4 m1, Matrix4 m2)
|
||||
{
|
||||
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.m11 = m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31;
|
||||
r.m12 = m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32;
|
||||
r.m13 = m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33;
|
||||
|
||||
r.m20 = m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20 + m1.m23 * m2.m30;
|
||||
r.m21 = m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31;
|
||||
r.m22 = m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32;
|
||||
r.m23 = m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33;
|
||||
|
||||
r.m30 = m1.m30 * m2.m00 + m1.m31 * m2.m10 + m1.m32 * m2.m20 + m1.m33 * m2.m30;
|
||||
r.m31 = m1.m30 * m2.m01 + m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31;
|
||||
r.m32 = m1.m30 * m2.m02 + m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32;
|
||||
r.m33 = m1.m30 * m2.m03 + m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33;
|
||||
r.m00 = (((m1.m00 * m2.m00) + (m1.m10 * m2.m01)) + (m1.m20 * m2.m02)) + (m1.m30 * m2.m03);
|
||||
r.m10 = (((m1.m00 * m2.m10) + (m1.m10 * m2.m11)) + (m1.m20 * m2.m12)) + (m1.m30 * m2.m13);
|
||||
r.m20 = (((m1.m00 * m2.m20) + (m1.m10 * m2.m21)) + (m1.m20 * m2.m22)) + (m1.m30 * m2.m23);
|
||||
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.m11 = (((m1.m01 * m2.m10) + (m1.m11 * m2.m11)) + (m1.m21 * m2.m12)) + (m1.m31 * m2.m13);
|
||||
r.m21 = (((m1.m01 * m2.m20) + (m1.m11 * m2.m21)) + (m1.m21 * m2.m22)) + (m1.m31 * m2.m23);
|
||||
r.m31 = (((m1.m01 * m2.m30) + (m1.m11 * m2.m31)) + (m1.m21 * m2.m32)) + (m1.m31 * 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.m22 = (((m1.m02 * m2.m20) + (m1.m12 * m2.m21)) + (m1.m22 * m2.m22)) + (m1.m32 * m2.m23);
|
||||
r.m32 = (((m1.m02 * m2.m30) + (m1.m12 * m2.m31)) + (m1.m22 * m2.m32)) + (m1.m32 * m2.m33);
|
||||
r.m03 = (((m1.m03 * m2.m00) + (m1.m13 * m2.m01)) + (m1.m23 * m2.m02)) + (m1.m33 * m2.m03);
|
||||
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;
|
||||
}
|
||||
|
@ -489,5 +500,730 @@ namespace Beefy.geom
|
|||
r20, r21, r22, r23,
|
||||
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 Beefy.gfx;
|
||||
|
||||
|
@ -189,42 +192,49 @@ namespace Beefy.geom
|
|||
|
||||
public static void CreateFromRotationMatrix(ref Matrix4 matrix, out Quaternion result)
|
||||
{
|
||||
float num8 = (matrix.m11 + matrix.m22) + matrix.m33;
|
||||
if (num8 > 0f)
|
||||
float sqrt;
|
||||
float half;
|
||||
float scale = matrix.m00 + matrix.m11 + matrix.m22;
|
||||
|
||||
if (scale > 0.0f)
|
||||
{
|
||||
float num = (float)Math.Sqrt((double)(num8 + 1f));
|
||||
result.mW = num * 0.5f;
|
||||
num = 0.5f / num;
|
||||
result.mX = (matrix.m23 - matrix.m32) * num;
|
||||
result.mY = (matrix.m31 - matrix.m13) * num;
|
||||
result.mZ = (matrix.m12 - matrix.m21) * num;
|
||||
sqrt = (float) Math.Sqrt(scale + 1.0f);
|
||||
result.mW = sqrt * 0.5f;
|
||||
sqrt = 0.5f / sqrt;
|
||||
|
||||
result.mX = (matrix.m21 - matrix.m12) * sqrt;
|
||||
result.mY = (matrix.m02 - matrix.m20) * sqrt;
|
||||
result.mZ = (matrix.m10 - matrix.m01) * sqrt;
|
||||
}
|
||||
else if ((matrix.m11 >= matrix.m22) && (matrix.m11 >= matrix.m33))
|
||||
else if ((matrix.m00 >= matrix.m11) && (matrix.m00 >= matrix.m22))
|
||||
{
|
||||
float num7 = (float)Math.Sqrt((double)(((1f + matrix.m11) - matrix.m22) - matrix.m33));
|
||||
float num4 = 0.5f / num7;
|
||||
result.mX = 0.5f * num7;
|
||||
result.mY = (matrix.m12 + matrix.m21) * num4;
|
||||
result.mZ = (matrix.m13 + matrix.m31) * num4;
|
||||
result.mW = (matrix.m23 - matrix.m32) * num4;
|
||||
sqrt = (float) Math.Sqrt(1.0f + matrix.m00 - matrix.m11 - matrix.m22);
|
||||
half = 0.5f / sqrt;
|
||||
|
||||
result.mX = 0.5f * sqrt;
|
||||
result.mY = (matrix.m10 + matrix.m01) * half;
|
||||
result.mZ = (matrix.m20 + matrix.m02) * half;
|
||||
result.mW = (matrix.m21 - matrix.m12) * half;
|
||||
}
|
||||
else if (matrix.m22 > matrix.m33)
|
||||
else if (matrix.m11 > matrix.m22)
|
||||
{
|
||||
float num6 = (float)Math.Sqrt((double)(((1f + matrix.m22) - matrix.m11) - matrix.m33));
|
||||
float num3 = 0.5f / num6;
|
||||
result.mX = (matrix.m21 + matrix.m12) * num3;
|
||||
result.mY = 0.5f * num6;
|
||||
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;
|
||||
|
||||
result.mX = (matrix.m01 + matrix.m10)*half;
|
||||
result.mY = 0.5f*sqrt;
|
||||
result.mZ = (matrix.m12 + matrix.m21)*half;
|
||||
result.mW = (matrix.m02 - matrix.m20)*half;
|
||||
}
|
||||
else
|
||||
{
|
||||
float num5 = (float)Math.Sqrt((double)(((1f + matrix.m33) - matrix.m11) - matrix.m22));
|
||||
float num2 = 0.5f / num5;
|
||||
result.mX = (matrix.m31 + matrix.m13) * num2;
|
||||
result.mY = (matrix.m32 + matrix.m23) * num2;
|
||||
result.mZ = 0.5f * num5;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.Collections;
|
||||
using System.Text;
|
||||
|
@ -131,7 +134,7 @@ namespace Beefy.geom
|
|||
{
|
||||
Vector3 newVec;
|
||||
Normalize(vector, out newVec);
|
||||
return vector;
|
||||
return newVec;
|
||||
}
|
||||
|
||||
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);
|
||||
}*/
|
||||
|
||||
public static Vector3 Transform(Vector3 vec, Matrix4 matrix)
|
||||
public static Vector3 TransformW(Vector3 vec, Matrix4 matrix)
|
||||
{
|
||||
Vector3 result;
|
||||
float fInvW = 1.0f / (matrix.m30 * vec.mX + matrix.m31 * vec.mY + matrix.m32 * vec.mZ + matrix.m33);
|
||||
|
@ -181,6 +184,16 @@ namespace Beefy.geom
|
|||
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.mZ = (matrix.m20 * vec.mX + matrix.m21 * vec.mY + matrix.m22 * vec.mZ + matrix.m23) * fInvW;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public static Vector3 operator -(Vector3 vec1)
|
||||
{
|
||||
return Vector3(-vec1.mX, -vec1.mY, -vec1.mZ);
|
||||
}
|
||||
|
||||
public static Vector3 operator *(Vector3 vec, float 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
|
||||
{
|
||||
AboveC, // Center
|
||||
AboveR, // Left edge of mark aligned on center of char8
|
||||
AboveE, // Center of mark aligned on right edge of char8
|
||||
AboveR, // Left edge of mark aligned on center of char
|
||||
AboveE, // Center of mark aligned on right edge of char
|
||||
BelowC,
|
||||
BelowR,
|
||||
OverC,
|
||||
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;
|
||||
|
@ -171,16 +171,33 @@ namespace Beefy.gfx
|
|||
{
|
||||
if (valType == 1)
|
||||
{
|
||||
String fontName = new String(&fontNameArr);
|
||||
String fontName = scope String(&fontNameArr);
|
||||
int parenPos = fontName.IndexOf(" (");
|
||||
if (parenPos != -1)
|
||||
fontName.RemoveToEnd(parenPos);
|
||||
fontName.ToUpper();
|
||||
String fontPath = new String(&data);
|
||||
if ((!fontPath.EndsWith(".TTF", .OrdinalIgnoreCase)) || (!sFontNameMap.TryAdd(fontName, fontPath)))
|
||||
String fontPath = scope String(&data);
|
||||
if ((!fontPath.EndsWith(".TTF", .OrdinalIgnoreCase)) && (!fontPath.EndsWith(".TTC", .OrdinalIgnoreCase)))
|
||||
continue;
|
||||
|
||||
if (fontName.Contains('&'))
|
||||
{
|
||||
delete fontName;
|
||||
delete fontPath;
|
||||
int collectionIdx = 0;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,10 @@ namespace Beefy.gfx
|
|||
const int32 CLIP_STACK_SIZE = 256;
|
||||
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 Rect? mClipRect = null;
|
||||
|
||||
|
@ -106,6 +110,10 @@ namespace Beefy.gfx
|
|||
mClipDisposeProxy = new DisposeProxy();
|
||||
mClipDisposeProxy.mDisposeProxyDelegate = new => PopClip;
|
||||
mRenderStateDisposeProxy = new DisposeProxy();
|
||||
mTexWrapDisableProxy = new DisposeProxy();
|
||||
mTexWrapDisableProxy.mDisposeProxyDelegate = new () => { PopTexWrap(false); };
|
||||
mTexWrapEnableProxy = new DisposeProxy();
|
||||
mTexWrapEnableProxy.mDisposeProxyDelegate = new () => { PopTexWrap(true); };
|
||||
|
||||
mWhiteDot = Image.LoadFromFile("!white");
|
||||
|
||||
|
@ -341,7 +349,7 @@ namespace Beefy.gfx
|
|||
Rect rectThing = mClipRect.Value;
|
||||
mClipRect = rectThing;
|
||||
|
||||
var clipRenderState = AllocRenderState(mDefaultShader, mClipRect);
|
||||
var clipRenderState = AllocRenderState(mDefaultShader, mClipRect, mTexWrap);
|
||||
|
||||
//clipRenderState.ClipRect = mClipRect;
|
||||
PushRenderState(clipRenderState);
|
||||
|
@ -349,7 +357,7 @@ namespace Beefy.gfx
|
|||
return mClipDisposeProxy;
|
||||
}
|
||||
|
||||
RenderState AllocRenderState(Shader shader, Rect? clipRect)
|
||||
RenderState AllocRenderState(Shader shader, Rect? clipRect, bool texWrap)
|
||||
{
|
||||
RenderState renderState = null;
|
||||
var curRenderState = mRenderStateStack[mRenderStateStackIdx];
|
||||
|
@ -365,6 +373,7 @@ namespace Beefy.gfx
|
|||
}
|
||||
else
|
||||
renderState = RenderState.Create(curRenderState);
|
||||
renderState.TexWrap = texWrap;
|
||||
renderState.Shader = shader;
|
||||
renderState.ClipRect = clipRect;
|
||||
return renderState;
|
||||
|
@ -375,16 +384,33 @@ namespace Beefy.gfx
|
|||
mClipStackIdx++;
|
||||
mClipStack[mClipStackIdx] = null;
|
||||
mClipRect = null;
|
||||
var clipRenderState = AllocRenderState(mDefaultShader, null);
|
||||
var clipRenderState = AllocRenderState(mDefaultShader, mClipRect, mTexWrap);
|
||||
//clipRenderState.ClipRect = null;
|
||||
PushRenderState(clipRenderState);
|
||||
|
||||
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()
|
||||
{
|
||||
var textRenderState = AllocRenderState(mTextShader, mClipRect);
|
||||
var textRenderState = AllocRenderState(mTextShader, mClipRect, mTexWrap);
|
||||
//textRenderState.ClipRect = mClipRect;
|
||||
//textRenderState.Shader = mTextShader;
|
||||
PushRenderState(textRenderState);
|
||||
|
@ -415,14 +441,17 @@ namespace Beefy.gfx
|
|||
//[CallingConvention(.Stdcall), CLink]
|
||||
//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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
static extern void Gfx_DrawQuads(void* textureSegment, Vertex3D* vertices, int32 vtxCount);
|
||||
|
@ -767,32 +796,57 @@ namespace Beefy.gfx
|
|||
}
|
||||
|
||||
public void DrawIndexedVertices(VertexDefinition vertexDef, void* vertices, int vtxCount, uint16[] indices)
|
||||
{
|
||||
if (vertexDef.mPosition2DOffset != -1)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (vertexDef.mPosition2DOffset != -1)
|
||||
{
|
||||
Gfx_DrawIndexedVertices2D(vertexDef.mVertexSize, vertices, (int32)vtxCount, indices, (int32)idxCount,
|
||||
mMatrix.a, mMatrix.b, mMatrix.c, mMatrix.d, mMatrix.tx, mMatrix.ty, ZDepth);
|
||||
}
|
||||
|
||||
public void SetShaderConstantData(int slotIdx, void* data, int size)
|
||||
else
|
||||
{
|
||||
Gfx_SetShaderConstantData((int32)slotIdx, data, (int32)size);
|
||||
Gfx_DrawIndexedVertices(vertexDef.mVertexSize, vertices, (int32)vtxCount, indices, (int32)idxCount);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetShaderConstantData(int32 slotIdx, void* data, ConstantDataDefinition constantDataDefinition)
|
||||
public void SetVertexShaderConstantData(int slotIdx, void* data, int size)
|
||||
{
|
||||
Gfx_SetShaderConstantData(0, (int32)slotIdx, data, (int32)size);
|
||||
}
|
||||
|
||||
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();
|
||||
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(slotIdx, &mtx, (int32)sizeof(Matrix4));
|
||||
Gfx_SetShaderConstantData(0, slotIdx, &mtx, (int32)sizeof(Matrix4));
|
||||
}
|
||||
|
||||
public void SetPixelShaderConstantData(int32 slotIdx, Matrix4 matrix)
|
||||
{
|
||||
var mtx = matrix;
|
||||
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)
|
||||
|
@ -811,12 +865,12 @@ namespace Beefy.gfx
|
|||
float d = m.d * height;
|
||||
|
||||
Gfx_AllocTris(image.mNativeTextureSegment, 6);
|
||||
Gfx_SetDrawVertex(0, m.tx, m.ty, 0, u1, 0, mColor);
|
||||
Gfx_SetDrawVertex(1, m.tx + a, m.ty + b, 0, u2, 0, mColor);
|
||||
Gfx_SetDrawVertex(2, m.tx + c, m.ty + d, 0, u1, 1, mColor);
|
||||
Gfx_SetDrawVertex(0, m.tx, m.ty, 0, u1, v1, 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, v2, mColor);
|
||||
Gfx_CopyDrawVertex(3, 2);
|
||||
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
|
||||
|
|
|
@ -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
|
||||
public class Image : IDrawable
|
||||
|
|
|
@ -49,6 +49,12 @@ namespace Beefy.gfx
|
|||
#if !STUDIO_CLIENT
|
||||
extension ModelDef
|
||||
{
|
||||
public enum ModelCreateFlags
|
||||
{
|
||||
None = 0,
|
||||
NoSetRenderState = 1
|
||||
}
|
||||
|
||||
public class Animation
|
||||
{
|
||||
public void* mNativeModelDefAnimation;
|
||||
|
@ -90,14 +96,32 @@ namespace Beefy.gfx
|
|||
public void* mNativeModelDef;
|
||||
public float mFrameRate;
|
||||
public int32 mJointCount;
|
||||
public Animation[] mAnims;
|
||||
public Dictionary<String, Animation> mAnimMap = new Dictionary<String, Animation>();
|
||||
public Animation[] mAnims ~ DeleteContainerAndItems!(_);
|
||||
public Dictionary<String, Animation> mAnimMap = new Dictionary<String, Animation>() ~ DeleteDictionaryAndKeys!(_);
|
||||
|
||||
[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* ModelDef_CreateModelInstance(void* nativeModel);
|
||||
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]
|
||||
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]
|
||||
extern static float ModelDef_GetFrameRate(void* nativeModel);
|
||||
|
@ -111,6 +135,15 @@ namespace Beefy.gfx
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
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)
|
||||
{
|
||||
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)
|
||||
return null;
|
||||
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)
|
||||
return null;
|
||||
var modelInstance = new ModelInstance(nativeModelInstance, this);
|
||||
|
@ -150,6 +189,42 @@ namespace Beefy.gfx
|
|||
{
|
||||
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
|
||||
|
|
|
@ -19,6 +19,12 @@ namespace Beefy.gfx
|
|||
Always
|
||||
}
|
||||
|
||||
public enum Topology
|
||||
{
|
||||
TriangleList,
|
||||
LineList
|
||||
}
|
||||
|
||||
#if !STUDIO_CLIENT
|
||||
public class RenderState
|
||||
{
|
||||
|
@ -31,6 +37,12 @@ namespace Beefy.gfx
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
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]
|
||||
static extern void RenderState_DisableClip(void* renderState);
|
||||
|
||||
|
@ -43,6 +55,9 @@ namespace Beefy.gfx
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
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 bool mIsFromDefaultRenderState;
|
||||
|
||||
|
@ -104,6 +119,30 @@ namespace Beefy.gfx
|
|||
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
|
||||
public class RenderState
|
||||
|
|
|
@ -424,9 +424,9 @@ namespace Beefy.theme.dark
|
|||
|
||||
if (selEnd > selStart)
|
||||
{
|
||||
String selPrevString = scope String(selStart);
|
||||
String selPrevString = new:ScopedAlloc! String(selStart);
|
||||
selPrevString.Append(sectionText, 0, selStart);
|
||||
String selIncludeString = scope String(selEnd);
|
||||
String selIncludeString = new:ScopedAlloc! String(selEnd);
|
||||
selIncludeString.Append(sectionText, 0, selEnd);
|
||||
|
||||
float selStartX = GetTabbedWidth(selPrevString, curX);
|
||||
|
@ -473,7 +473,7 @@ namespace Beefy.theme.dark
|
|||
|
||||
if (isInside)
|
||||
{
|
||||
String subText = scope String(mCursorTextPos - lineDrawStart);
|
||||
String subText = new:ScopedAlloc! String(mCursorTextPos - lineDrawStart);
|
||||
subText.Append(sectionText, 0, mCursorTextPos - lineDrawStart);
|
||||
aX = GetTabbedWidth(subText, curX);
|
||||
}
|
||||
|
@ -587,7 +587,7 @@ namespace Beefy.theme.dark
|
|||
|
||||
if (char8Count < lineText.Length)
|
||||
{
|
||||
String subString = scope String(char8Count);
|
||||
String subString = new:ScopedAlloc! String(char8Count);
|
||||
subString.Append(lineText, 0, char8Count);
|
||||
float subWidth = GetTabbedWidth(subString, 0);
|
||||
|
||||
|
|
|
@ -398,12 +398,12 @@ namespace Beefy.theme.dark
|
|||
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;
|
||||
if (useWidth == 0)
|
||||
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)
|
||||
|
|
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;
|
||||
switch (obj.GetType())
|
||||
{
|
||||
case typeof(Int32): val = (int32)obj;
|
||||
case typeof(Int64): val = (.)(int64)obj;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
@ -417,7 +417,7 @@ namespace Beefy.utils
|
|||
return;
|
||||
switch (obj.GetType())
|
||||
{
|
||||
case typeof(Int32): val = (int32)obj;
|
||||
case typeof(Int64): val = (int64)obj;
|
||||
case typeof(Float): val = (float)obj;
|
||||
default:
|
||||
}
|
||||
|
@ -470,6 +470,7 @@ namespace Beefy.utils
|
|||
Object val = Get(name);
|
||||
|
||||
outString.Clear();
|
||||
|
||||
if (val is uint64)
|
||||
val.ToString(outString);
|
||||
|
||||
|
@ -493,58 +494,112 @@ namespace Beefy.utils
|
|||
return;
|
||||
}
|
||||
|
||||
public int32 GetInt(String name, int32 theDefault = 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)
|
||||
public int32 GetInt(String name, int32 defaultVal = 0)
|
||||
{
|
||||
Object val = Get(name);
|
||||
if (val == null)
|
||||
return theDefault;
|
||||
return defaultVal;
|
||||
switch (val.GetType())
|
||||
{
|
||||
case typeof(Float): return (float)val;
|
||||
case typeof(Int32): return (int32)val;
|
||||
case typeof(Int): return (int)val;
|
||||
default: return theDefault;
|
||||
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 (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);
|
||||
if ((aVal == null) || (!(aVal is bool)))
|
||||
return theDefault;
|
||||
return (bool)aVal;
|
||||
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 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
|
||||
|
@ -634,9 +689,9 @@ namespace Beefy.utils
|
|||
public int32 GetCurInt(int32 theDefault = 0)
|
||||
{
|
||||
Object aVal = GetCurrent();
|
||||
if ((aVal == null) || (!(aVal is int32)))
|
||||
if ((aVal == null) || (!(aVal is int64)))
|
||||
return theDefault;
|
||||
return (int32)aVal;
|
||||
return (.)(int64)aVal;
|
||||
}
|
||||
|
||||
public uint32 GetCurUInt(uint32 theDefault = 0)
|
||||
|
@ -1786,7 +1841,7 @@ namespace Beefy.utils
|
|||
}
|
||||
else
|
||||
{
|
||||
var parseVal = int32.Parse(strView);
|
||||
var parseVal = int64.Parse(strView);
|
||||
if (parseVal case .Ok(var intVal))
|
||||
aValue = new:mBumpAllocator box intVal;
|
||||
else
|
||||
|
@ -2187,7 +2242,7 @@ namespace Beefy.utils
|
|||
}
|
||||
}
|
||||
|
||||
switch (Int32.Parse(value))
|
||||
switch (Int64.Parse(value))
|
||||
{
|
||||
case .Err: return null;
|
||||
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()
|
||||
{
|
||||
EnsureHasData();
|
||||
|
@ -2354,14 +2626,35 @@ namespace Beefy.utils
|
|||
mNextKeys.Reserve(guessItems);
|
||||
|
||||
bool isJson = false;
|
||||
bool isXml = false;
|
||||
bool mayBeJsonArray = false;
|
||||
for (char8 c in mSource.RawChars)
|
||||
{
|
||||
if (c.IsWhiteSpace)
|
||||
continue;
|
||||
if (c == '{')
|
||||
|
||||
if (mayBeJsonArray)
|
||||
{
|
||||
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 anIdx = 0;
|
||||
|
@ -2373,6 +2666,14 @@ namespace Beefy.utils
|
|||
return .Err(err);
|
||||
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
|
||||
{
|
||||
var values = new:mBumpAllocator NamedValues();
|
||||
|
|
|
@ -459,7 +459,7 @@ namespace Beefy.widgets
|
|||
public UndoManager mUndoManager = new UndoManager() ~ delete _;
|
||||
public int32 mNextCharId = 1; //
|
||||
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 _;
|
||||
|
||||
|
@ -1985,6 +1985,9 @@ namespace Beefy.widgets
|
|||
{
|
||||
scope AutoBeefPerf("EWC.Undo");
|
||||
|
||||
if (CheckReadOnly())
|
||||
return;
|
||||
|
||||
//Profiler.StartSampling();
|
||||
if (WantsUndo)
|
||||
mData.mUndoManager.Undo();
|
||||
|
@ -1995,6 +1998,9 @@ namespace Beefy.widgets
|
|||
{
|
||||
scope AutoBeefPerf("EWC.Redo");
|
||||
|
||||
if (CheckReadOnly())
|
||||
return;
|
||||
|
||||
if (WantsUndo)
|
||||
mData.mUndoManager.Redo();
|
||||
}
|
||||
|
|
|
@ -82,6 +82,8 @@ namespace Beefy.widgets
|
|||
F12 = 0x7B,
|
||||
Numlock = 0x90,
|
||||
Scroll = 0x91,
|
||||
RAlt = 0xA5,
|
||||
RMenu = 0xA5,
|
||||
Semicolon = 0xBA,
|
||||
Equals = 0xBB,
|
||||
Comma = 0xBC,
|
||||
|
|
|
@ -339,7 +339,7 @@ namespace Beefy.widgets
|
|||
}
|
||||
else
|
||||
{
|
||||
if (item.Selected)
|
||||
if ((item.Selected) && (item.mMouseOver))
|
||||
{
|
||||
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));
|
||||
if (aHorzPos == mHorzPos.mDest)
|
||||
return false;
|
||||
|
||||
mHorzPos.Set(aHorzPos);
|
||||
mHorzPos.Set(aHorzPos, immediate);
|
||||
if (mHorzScrollbar != null)
|
||||
{
|
||||
mHorzScrollbar.mContentPos = mHorzPos.v;
|
||||
|
|
|
@ -162,7 +162,7 @@ namespace Beefy.widgets
|
|||
if ((mSrcDraggingWindow != null) && (mSrcDraggingWindow.mCaptureWidget != null))
|
||||
mSrcDraggingWindow.ReleaseMouseCaptures();
|
||||
|
||||
mTabbedView.mParentDockingFrame.GetRootDockingFrame().HideDragTarget(this, !mDragHelper.mAborted);
|
||||
mTabbedView.mParentDockingFrame?.GetRootDockingFrame().HideDragTarget(this, !mDragHelper.mAborted);
|
||||
if (mNewDraggingWindow != null)
|
||||
{
|
||||
mNewDraggingWindow.mOnWindowLostFocus.Remove(scope => WindowDragLostFocusHandler, true);
|
||||
|
@ -176,7 +176,7 @@ namespace Beefy.widgets
|
|||
|
||||
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)
|
||||
|
@ -198,6 +198,8 @@ namespace Beefy.widgets
|
|||
|
||||
public virtual bool IsTotalWindowContent()
|
||||
{
|
||||
if (mTabbedView.mParentDockingFrame == null)
|
||||
return false;
|
||||
return (mTabbedView.mParentDockingFrame.mParentDockingFrame == null) &&
|
||||
(mTabbedView.mParentDockingFrame.GetDockedWindowCount() == 1) &&
|
||||
(mTabbedView.GetTabCount() == 1) &&
|
||||
|
@ -318,7 +320,7 @@ namespace Beefy.widgets
|
|||
//tabbedView.mSharedData.mOpenNewWindowDelegate = mTabbedView.mSharedData.mOpenNewWindowDelegate;
|
||||
tabbedView.SetRequestedSize(mTabbedView.mWidth, mTabbedView.mHeight);
|
||||
mTabbedView.RemoveTab(this, false);
|
||||
tabbedView.AddTab(this);
|
||||
tabbedView.AddTab(this, 0);
|
||||
|
||||
float rootX;
|
||||
float rootY;
|
||||
|
@ -470,7 +472,7 @@ namespace Beefy.widgets
|
|||
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();
|
||||
aTabButton.mTabbedView = this;
|
||||
|
@ -479,7 +481,7 @@ namespace Beefy.widgets
|
|||
aTabButton.mWantWidth = width;
|
||||
aTabButton.mHeight = mTabHeight;
|
||||
aTabButton.mContent = content;
|
||||
AddTab(aTabButton);
|
||||
AddTab(aTabButton, insertIdx);
|
||||
return aTabButton;
|
||||
}
|
||||
|
||||
|
@ -499,7 +501,7 @@ namespace Beefy.widgets
|
|||
return bestIdx;
|
||||
}
|
||||
|
||||
public virtual void AddTab(TabButton tabButton, int insertIdx = 0)
|
||||
public virtual void AddTab(TabButton tabButton, int insertIdx)
|
||||
{
|
||||
AddWidget(tabButton);
|
||||
mTabs.Insert(insertIdx, tabButton);
|
||||
|
|
|
@ -121,7 +121,7 @@ namespace Beefy.widgets
|
|||
KeyFlags keyFlags = default;
|
||||
if (IsKeyDown(KeyCode.Shift))
|
||||
keyFlags |= KeyFlags.Shift;
|
||||
if (IsKeyDown(KeyCode.Control))
|
||||
if ((IsKeyDown(KeyCode.Control)) && (!IsKeyDown(KeyCode.RAlt)))
|
||||
keyFlags |= KeyFlags.Ctrl;
|
||||
if (IsKeyDown(KeyCode.Menu))
|
||||
keyFlags |= KeyFlags.Alt;
|
||||
|
|
|
@ -192,7 +192,8 @@ namespace SDL2
|
|||
return;
|
||||
|
||||
int32 channel = SDLMixer.PlayChannel(-1, sound.mChunk, 0);
|
||||
//SDLMixer.SetPanning()
|
||||
if (channel < 0)
|
||||
return;
|
||||
SDLMixer.Volume(channel, (int32)(volume * 128));
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace System
|
|||
|
||||
public bool IsEmpty
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
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]
|
||||
public T* CArray()
|
||||
{
|
||||
|
@ -276,7 +317,7 @@ namespace System
|
|||
Debug.Assert(length >= 0);
|
||||
Debug.Assert((uint)srcOffset + (uint)length <= (uint)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
|
||||
|
@ -299,17 +340,18 @@ namespace System
|
|||
public void CopyTo(Span<T> destination)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
//TODO: Handle src/dest overlap (MemMove)
|
||||
Debug.Assert((uint)srcOffset + (uint)destination.[Friend]mLength <= (uint)mLength);
|
||||
var ptr = destination.[Friend]mPtr;
|
||||
for (int i = 0; i < destination.[Friend]mLength; i++)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace System
|
||||
{
|
||||
struct Char16 : char16, IHashable, IIsNaN
|
||||
struct Char16 : char16, ICharacter, IHashable, IIsNaN
|
||||
{
|
||||
const int UNICODE_PLANE00_END = 0x00ffff;
|
||||
// The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace System
|
||||
{
|
||||
struct Char32 : char32, IHashable, IIsNaN
|
||||
struct Char32 : char32, ICharacter, IHashable, IIsNaN
|
||||
{
|
||||
public int GetHashCode()
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace System
|
||||
{
|
||||
#unwarn
|
||||
struct Char8 : char8, IHashable, IIsNaN
|
||||
struct Char8 : char8, ICharacter, IHashable, IIsNaN
|
||||
{
|
||||
bool IIsNaN.IsNaN
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace System.Collections
|
|||
{
|
||||
public TKey mKey; // Key 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
|
||||
}
|
||||
|
||||
|
@ -257,22 +257,10 @@ namespace System.Collections
|
|||
}
|
||||
|
||||
public bool ContainsValue(TValue value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
for (int_cosize i = 0; i < mCount; i++)
|
||||
{
|
||||
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;
|
||||
}*/
|
||||
if (mEntries[i].mHashCode >= 0 && mEntries[i].mValue == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -290,6 +278,19 @@ namespace System.Collections
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Debug.Assert(kvPair.Length >= mCount);
|
||||
|
@ -306,12 +307,21 @@ namespace System.Collections
|
|||
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]
|
||||
private int FindEntry(TKey key)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key)) return i;
|
||||
|
@ -329,7 +339,7 @@ namespace System.Collections
|
|||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (mBuckets == null) Initialize(0);
|
||||
int32 hashCode = (int32)key.GetHashCode() & 0x7FFFFFFF;
|
||||
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
|
||||
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||
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))
|
||||
{
|
||||
|
@ -402,7 +412,7 @@ namespace System.Collections
|
|||
private bool Insert(TKey key, bool add, out TKey* keyPtr, out TValue* valuePtr, Entry** outOldData)
|
||||
{
|
||||
if (mBuckets == null) Initialize(0);
|
||||
int32 hashCode = (int32)key.GetHashCode() & 0x7FFFFFFF;
|
||||
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
|
||||
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
|
||||
{
|
||||
if (mBuckets == null) Initialize(0);
|
||||
int32 hashCode = (int32)key.GetHashCode() & 0x7FFFFFFF;
|
||||
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
|
||||
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
|
||||
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||
int targetBucket = hashCode % (int_cosize)mAllocSize;
|
||||
for (int i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
|
||||
{
|
||||
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key))
|
||||
{
|
||||
|
@ -541,7 +551,7 @@ namespace System.Collections
|
|||
{
|
||||
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)
|
||||
{
|
||||
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
|
||||
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||
int bucket = hashCode % (int_cosize)mAllocSize;
|
||||
int last = -1;
|
||||
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
||||
|
@ -609,7 +619,7 @@ namespace System.Collections
|
|||
{
|
||||
if (mBuckets != null)
|
||||
{
|
||||
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
|
||||
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||
int bucket = hashCode % (int_cosize)mAllocSize;
|
||||
int last = -1;
|
||||
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
||||
|
@ -653,8 +663,8 @@ namespace System.Collections
|
|||
if (mBuckets != null)
|
||||
{
|
||||
|
||||
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
|
||||
int_cosize bucket = hashCode % (int_cosize)mAllocSize;
|
||||
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||
int bucket = hashCode % (int_cosize)mAllocSize;
|
||||
int_cosize last = -1;
|
||||
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
||||
{
|
||||
|
@ -694,8 +704,8 @@ namespace System.Collections
|
|||
if (mBuckets != null)
|
||||
{
|
||||
|
||||
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
|
||||
int_cosize bucket = hashCode % (int_cosize)mAllocSize;
|
||||
int_cosize hashCode = GetKeyHash(key.GetHashCode());
|
||||
int bucket = hashCode % (int_cosize)mAllocSize;
|
||||
int_cosize last = -1;
|
||||
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
|
||||
{
|
||||
|
@ -742,6 +752,18 @@ namespace System.Collections
|
|||
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)
|
||||
{
|
||||
int_cosize i = (int_cosize)FindEntry(key);
|
||||
|
@ -876,6 +898,16 @@ namespace System.Collections
|
|||
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
|
||||
{
|
||||
#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
|
||||
{
|
||||
#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
|
||||
{
|
||||
#if VERSION_DICTIONARY
|
||||
|
|
|
@ -196,7 +196,13 @@ namespace System.Collections
|
|||
return false;
|
||||
}
|
||||
|
||||
[Obsolete("Method renamed to ContainsAlt", false)]
|
||||
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)
|
||||
{
|
||||
|
@ -346,6 +352,11 @@ namespace System.Collections
|
|||
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, int32 arrayIndex, int32 count)
|
||||
|
@ -632,6 +643,71 @@ namespace System.Collections
|
|||
mVersion++;
|
||||
#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(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(m_comparer)) {
|
||||
m_comparer = (IEqualityComparer<T>) HashHelpers.GetRandomizedEqualityComparer(m_comparer);
|
||||
|
@ -1071,6 +1147,15 @@ namespace System.Collections
|
|||
return item.GetHashCode() & Lower31BitMask;
|
||||
}
|
||||
|
||||
private int InternalGetHashCodeAlt<TAltKey>(TAltKey item) where TAltKey : IHashable
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return item.GetHashCode() & Lower31BitMask;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// used for set checking operations (using enumerables) that rely on counting
|
||||
|
|
|
@ -148,6 +148,7 @@ namespace System.Collections
|
|||
|
||||
public int Count
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
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
|
||||
{
|
||||
get
|
||||
|
@ -534,7 +605,7 @@ namespace System.Collections
|
|||
if (mSize == AllocSize) EnsureCapacity(mSize + 1, true);
|
||||
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;
|
||||
mSize++;
|
||||
|
@ -553,7 +624,7 @@ namespace System.Collections
|
|||
if (mSize + addCount > AllocSize) EnsureCapacity(mSize + addCount, true);
|
||||
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));
|
||||
mSize += (int_cosize)addCount;
|
||||
|
@ -567,7 +638,7 @@ namespace System.Collections
|
|||
Debug.Assert((uint)index < (uint)mSize);
|
||||
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--;
|
||||
#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>
|
||||
{
|
||||
IRawAllocator mAlloc;
|
||||
|
|
|
@ -18,6 +18,12 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
public static class Options
|
||||
{
|
||||
[LinkName("#AllocStackCount")]
|
||||
public static extern int32 AllocStackCount;
|
||||
}
|
||||
|
||||
[LinkName("#CallerLineNum")]
|
||||
public static extern int CallerLineNum;
|
||||
|
||||
|
@ -37,7 +43,7 @@ namespace System
|
|||
public static extern String CallerProject;
|
||||
|
||||
[LinkName("#CallerExpression")]
|
||||
public static extern String[Int32.MaxValue] CallerExpression;
|
||||
public static extern String[0x0FFFFFFF] CallerExpression;
|
||||
|
||||
[LinkName("#ProjectName")]
|
||||
public static extern String ProjectName;
|
||||
|
|
|
@ -7,6 +7,12 @@ namespace System
|
|||
{
|
||||
public static class Console
|
||||
{
|
||||
public enum CancelKind
|
||||
{
|
||||
CtrlC,
|
||||
CtrlBreak
|
||||
}
|
||||
|
||||
static Encoding InputEncoding = Encoding.ASCII;
|
||||
static Encoding OutputEncoding = Encoding.ASCII;
|
||||
|
||||
|
@ -16,6 +22,9 @@ namespace System
|
|||
static readonly ConsoleColor sOriginalForegroundColor = sForegroundColor;
|
||||
static readonly ConsoleColor sOriginalBackgroundColor = sBackgroundColor;
|
||||
|
||||
static Event<delegate void (CancelKind cancelKind, ref bool terminate)> sOnCancel ~ _.Dispose();
|
||||
static bool sCancelEventRegistered;
|
||||
|
||||
public static ConsoleColor ForegroundColor
|
||||
{
|
||||
get { return sForegroundColor; }
|
||||
|
@ -42,16 +51,57 @@ namespace System
|
|||
public uint16[2] mMaximumWindowSize;
|
||||
}
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
static extern int SetConsoleTextAttribute(void* hConsoleOutput, uint16 wAttributes);
|
||||
[CRepr]
|
||||
struct COORD : this(int16 X, int16 Y)
|
||||
{
|
||||
}
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
static extern int GetConsoleScreenBufferInfo(void* hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
static extern void* GetStdHandle(uint32 nStdHandle);
|
||||
public static ref Event<delegate void (CancelKind cancelKind, ref bool terminate)> OnCancel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!sCancelEventRegistered)
|
||||
{
|
||||
sCancelEventRegistered = true;
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
SetConsoleCtrlHandler(=> ConsoleCtrlHandler, true);
|
||||
#endif
|
||||
}
|
||||
return ref sOnCancel;
|
||||
}
|
||||
}
|
||||
|
||||
#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()
|
||||
{
|
||||
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
@ -219,6 +269,49 @@ namespace System
|
|||
#else
|
||||
Write("\x1B[{}m", ForegroundColor.AnsiCode);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace System.Diagnostics
|
|||
private char8[] char8Buffer;
|
||||
// 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
|
||||
// a user's char8[] directly, instead of our internal char8[].
|
||||
private int32 mMaxCharsPerBuffer;
|
||||
|
@ -194,7 +194,7 @@ namespace System.Diagnostics
|
|||
int lineStart = 0;
|
||||
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'
|
||||
if (bLastCarriageReturn && (len > 0) && sb[0] == '\n')
|
||||
{
|
||||
|
@ -206,7 +206,7 @@ namespace System.Diagnostics
|
|||
while (currentIndex < len)
|
||||
{
|
||||
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
|
||||
if (ch == '\r' || ch == '\n')
|
||||
{
|
||||
|
@ -214,7 +214,7 @@ namespace System.Diagnostics
|
|||
s.Append(sb, lineStart, currentIndex - lineStart);
|
||||
|
||||
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'))
|
||||
{
|
||||
lineStart++;
|
||||
|
@ -232,7 +232,7 @@ namespace System.Diagnostics
|
|||
{
|
||||
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 == 0)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace System.Diagnostics
|
||||
{
|
||||
class Check
|
||||
static class Check
|
||||
{
|
||||
|
||||
[Unchecked, SkipCall]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace System.Diagnostics.Contracts
|
||||
{
|
||||
class Contract
|
||||
static class Contract
|
||||
{
|
||||
public enum ContractFailureKind
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace System.Diagnostics
|
||||
{
|
||||
class Debug
|
||||
static class Debug
|
||||
{
|
||||
#if !DEBUG
|
||||
[SkipCall]
|
||||
|
@ -44,6 +44,11 @@ namespace System.Diagnostics
|
|||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
|
@ -150,9 +150,7 @@ namespace System
|
|||
break;
|
||||
}
|
||||
if (idx == -1)
|
||||
{
|
||||
Runtime.FatalError("Not found");
|
||||
}
|
||||
return .Err;
|
||||
|
||||
if (deleteDelegate)
|
||||
delete list[idx];
|
||||
|
@ -177,18 +175,14 @@ namespace System
|
|||
else
|
||||
{
|
||||
T dlgMember = (T)data;
|
||||
if (Delegate.Equals(compareDelegate, dlgMember))
|
||||
{
|
||||
if (!Delegate.Equals(compareDelegate, dlgMember))
|
||||
return .Err;
|
||||
if (deleteDelegate)
|
||||
delete dlgMember;
|
||||
Target = null;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Runtime.FatalError("Not found");
|
||||
}
|
||||
}
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public rettype(T) Invoke(params T p) mut
|
||||
|
|
|
@ -175,6 +175,17 @@ namespace System
|
|||
{
|
||||
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 (decimalMultiplier != 0)
|
||||
|
|
|
@ -173,6 +173,10 @@ namespace System
|
|||
// 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>
|
||||
{
|
||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace System.Globalization
|
|||
|
||||
// cache for the invariant 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.
|
||||
private CultureData m_cultureData;
|
||||
|
@ -139,6 +139,8 @@ namespace System.Globalization
|
|||
List<Object> ownedObjects = new .() ~ DeleteContainerAndItems!(_);
|
||||
|
||||
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
|
||||
) ~ delete _;
|
||||
|
||||
private static volatile Calendar s_defaultInstance;
|
||||
private static volatile Calendar s_defaultInstance ~ delete _;
|
||||
|
||||
|
||||
#region Serialization
|
||||
|
|
|
@ -23,6 +23,10 @@ namespace System
|
|||
{
|
||||
}
|
||||
|
||||
interface ICharacter
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Consider operator constraint such as `where bool : operator T == T`", false)]
|
||||
interface IOpEquals
|
||||
{
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace System.IO
|
|||
|
||||
public override Result<int> TryRead(Span<uint8> data)
|
||||
{
|
||||
int spaceLeft = (.)(mBufferEnd - mPos);
|
||||
int64 spaceLeft = (.)(mBufferEnd - mPos);
|
||||
if (mPos < mBufferPos)
|
||||
spaceLeft = 0;
|
||||
if (data.Length <= spaceLeft)
|
||||
|
@ -83,18 +83,16 @@ namespace System.IO
|
|||
var data;
|
||||
if (spaceLeft > 0)
|
||||
{
|
||||
Internal.MemCpy(data.Ptr, mBuffer.Ptr + (mPos - mBufferPos), spaceLeft);
|
||||
Internal.MemCpy(data.Ptr, mBuffer.Ptr + (mPos - mBufferPos), (.)spaceLeft);
|
||||
mPos += spaceLeft;
|
||||
data.RemoveFromStart(spaceLeft);
|
||||
data.RemoveFromStart((.)spaceLeft);
|
||||
}
|
||||
|
||||
if (mWriteDirtyPos >= 0)
|
||||
Try!(Flush());
|
||||
|
||||
if ((mBuffer == null) || (data.Length > mBuffer.Count))
|
||||
{
|
||||
var result = TryReadUnderlying(mPos, data);
|
||||
if (result case .Ok(let len))
|
||||
let len = Try!(TryReadUnderlying(mPos, data));
|
||||
mPos += len;
|
||||
return (.)(mPos - readStart);
|
||||
}
|
||||
|
@ -148,10 +146,9 @@ namespace System.IO
|
|||
|
||||
if ((mBuffer == null) || (data.Length > mBuffer.Count))
|
||||
{
|
||||
var result = TryWriteUnderlying(mPos, data);
|
||||
if (result case .Ok(let len))
|
||||
let len = Try!(TryWriteUnderlying(mPos, data));
|
||||
mPos += len;
|
||||
writeCount += result;
|
||||
writeCount += len;
|
||||
return writeCount;
|
||||
}
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ namespace System.IO
|
|||
}
|
||||
}
|
||||
|
||||
struct FileEnumerator : IEnumerator<FileFindEntry>
|
||||
struct FileEnumerator : IEnumerator<FileFindEntry>, IDisposable
|
||||
{
|
||||
String mSearchStr;
|
||||
Platform.BfpFindFileData* mFindFileData;
|
||||
|
|
|
@ -15,6 +15,11 @@ namespace System.IO
|
|||
mOwnsData = true;
|
||||
}
|
||||
|
||||
public this(List<uint8> data)
|
||||
{
|
||||
mData = data;
|
||||
}
|
||||
|
||||
public uint8* Ptr
|
||||
{
|
||||
get
|
||||
|
@ -112,4 +117,100 @@ namespace System.IO
|
|||
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);
|
||||
}
|
||||
|
||||
class File
|
||||
static class File
|
||||
{
|
||||
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)
|
||||
{
|
||||
FileStream fs = scope FileStream();
|
||||
UnbufferedFileStream fs = scope UnbufferedFileStream();
|
||||
var result = fs.Open(path, doAppend ? .Append : .Create, .Write);
|
||||
if (result case .Err)
|
||||
return .Err;
|
||||
|
@ -76,7 +76,7 @@ namespace System.IO
|
|||
|
||||
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);
|
||||
if (result case .Err)
|
||||
return .Err;
|
||||
|
@ -87,7 +87,7 @@ namespace System.IO
|
|||
|
||||
public static Result<void> WriteAllText(StringView path, StringView text, Encoding encoding)
|
||||
{
|
||||
FileStream fs = scope FileStream();
|
||||
UnbufferedFileStream fs = scope UnbufferedFileStream();
|
||||
|
||||
int len = encoding.GetEncodedSize(text);
|
||||
uint8* data = new uint8[len]*;
|
||||
|
|
|
@ -17,16 +17,16 @@ namespace System.IO
|
|||
/// Opens an existing file. Fails if the file does not exist.
|
||||
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,
|
||||
|
||||
// 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
|
||||
// WRITE access. Fails if the file does not exist.
|
||||
/// 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
|
||||
/// WRITE access. Fails if the file does not exist.
|
||||
Truncate = 5,
|
||||
|
||||
// Opens the file if it exists and seeks to the end. Otherwise,
|
||||
// creates a new file.
|
||||
/// Opens the file if it exists and seeks to the end. Otherwise,
|
||||
/// creates a new file.
|
||||
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()
|
||||
{
|
||||
Delete();
|
||||
|
@ -165,12 +175,13 @@ namespace System.IO
|
|||
createKind = .CreateIfNotExists;
|
||||
case .Create:
|
||||
createKind = .CreateAlways;
|
||||
createFlags |= .Truncate;
|
||||
case .Open:
|
||||
createKind = .OpenExisting;
|
||||
case .OpenOrCreate:
|
||||
createKind = .CreateAlways;
|
||||
createKind = .OpenAlways;
|
||||
case .Truncate:
|
||||
createKind = .CreateAlways;
|
||||
createKind = .OpenExisting;
|
||||
createFlags |= .Truncate;
|
||||
case .Append:
|
||||
createKind = .CreateAlways;
|
||||
|
@ -225,6 +236,32 @@ namespace System.IO
|
|||
return .Err;
|
||||
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
|
||||
|
@ -233,6 +270,32 @@ namespace System.IO
|
|||
protected int64 mBfpFilePos;
|
||||
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()
|
||||
{
|
||||
|
||||
|
@ -254,22 +317,6 @@ namespace System.IO
|
|||
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)
|
||||
{
|
||||
return Open(path, FileMode.Create, access, share, bufferSize, options, secAttrs);
|
||||
|
@ -317,7 +364,7 @@ namespace System.IO
|
|||
case .Open:
|
||||
createKind = .OpenExisting;
|
||||
case .OpenOrCreate:
|
||||
createKind = .CreateAlways;
|
||||
createKind = .OpenAlways;
|
||||
case .Truncate:
|
||||
createKind = .CreateAlways;
|
||||
createFlags |= .Truncate;
|
||||
|
@ -386,15 +433,20 @@ namespace System.IO
|
|||
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)
|
||||
{
|
||||
if (mBfpFilePos != pos)
|
||||
{
|
||||
int64 newPos = Platform.BfpFile_Seek(mBfpFile, pos, .Absolute);
|
||||
if (newPos != pos)
|
||||
return .Err;
|
||||
mBfpFilePos = pos;
|
||||
}
|
||||
Try!(SeekUnderlying(pos));
|
||||
|
||||
Platform.BfpFileResult result = .Ok;
|
||||
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, -1, &result);
|
||||
if ((result != .Ok) && (result != .PartialData))
|
||||
|
@ -406,12 +458,8 @@ namespace System.IO
|
|||
protected override Result<int> TryWriteUnderlying(int64 pos, Span<uint8> data)
|
||||
{
|
||||
if (mBfpFilePos != pos)
|
||||
{
|
||||
int64 newPos = Platform.BfpFile_Seek(mBfpFile, pos, .Absolute);
|
||||
if (newPos != pos)
|
||||
return .Err;
|
||||
mBfpFilePos = pos;
|
||||
}
|
||||
Try!(SeekUnderlying(pos));
|
||||
|
||||
Platform.BfpFileResult result = .Ok;
|
||||
int numBytesRead = Platform.BfpFile_Write(mBfpFile, data.Ptr, data.Length, -1, &result);
|
||||
if ((result != .Ok) && (result != .PartialData))
|
||||
|
@ -423,12 +471,7 @@ namespace System.IO
|
|||
public Result<int> TryRead(Span<uint8> data, int timeoutMS)
|
||||
{
|
||||
if (mBfpFilePos != mPos)
|
||||
{
|
||||
int64 newPos = Platform.BfpFile_Seek(mBfpFile, mPos, .Absolute);
|
||||
if (newPos != mPos)
|
||||
return .Err;
|
||||
mBfpFilePos = mPos;
|
||||
}
|
||||
Try!(SeekUnderlying(mPos));
|
||||
|
||||
Platform.BfpFileResult result = .Ok;
|
||||
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, timeoutMS, &result);
|
||||
|
@ -436,6 +479,40 @@ namespace System.IO
|
|||
return .Err;
|
||||
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
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace System.IO
|
|||
{
|
||||
class MemoryStream : Stream
|
||||
{
|
||||
List<uint8> mMemory = new List<uint8>() ~ delete _;
|
||||
List<uint8> mMemory ~ delete _;
|
||||
int mPosition = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
let count = data.Length;
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace System.IO
|
|||
public const char8 DirectorySeparatorChar = '/';
|
||||
#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
|
||||
// and MacOS.
|
||||
//
|
||||
|
@ -25,7 +25,7 @@ namespace System.IO
|
|||
public const char8 AltDirectorySeparatorChar = '\\';
|
||||
#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
|
||||
// useful for parsing paths like "c:\windows" or "MacVolume:System Folder".
|
||||
//
|
||||
|
@ -37,7 +37,7 @@ namespace System.IO
|
|||
|
||||
// Make this public sometime.
|
||||
// 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;
|
||||
private const int32 MaxDirectoryLength = 255;
|
||||
|
||||
|
@ -297,7 +297,7 @@ namespace System.IO
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -97,25 +97,32 @@ namespace System.IO
|
|||
}
|
||||
}
|
||||
|
||||
//Read sized string from stream
|
||||
public Result<void> ReadStrSized32(int64 size, String output)
|
||||
/// Read sized string from stream
|
||||
public Result<void> ReadStrSized32(int size, String output)
|
||||
{
|
||||
if (size <= 0)
|
||||
if (size < 0)
|
||||
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>();
|
||||
if (char == .Err)
|
||||
return .Err;
|
||||
|
||||
output.Append(char);
|
||||
}
|
||||
|
||||
case .Ok(let readLen):
|
||||
if (readLen < size)
|
||||
output.Length = prevLen + readLen;
|
||||
return .Ok;
|
||||
case .Err:
|
||||
return .Err;
|
||||
}
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
Result<char8> char0;
|
||||
|
@ -197,6 +204,11 @@ namespace System.IO
|
|||
return .Ok;
|
||||
}
|
||||
|
||||
public virtual Result<void> SetLength(int64 length)
|
||||
{
|
||||
return .Err;
|
||||
}
|
||||
|
||||
public void Align(int alignSize)
|
||||
{
|
||||
int64 pos = Length;
|
||||
|
|
|
@ -256,7 +256,7 @@ namespace System.IO
|
|||
{
|
||||
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
|
||||
if (ch == '\r' || ch == '\n')
|
||||
{
|
||||
|
@ -481,7 +481,7 @@ namespace System.IO
|
|||
}
|
||||
while (mCharLen == 0);
|
||||
|
||||
//Console.WriteLine("ReadBuffer called. char8s: "+char8Len);
|
||||
//Console.WriteLine("ReadBuffer called. chars: "+char8Len);
|
||||
return mCharLen;
|
||||
}
|
||||
|
||||
|
@ -522,7 +522,7 @@ namespace System.IO
|
|||
repeat
|
||||
{
|
||||
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
|
||||
if (ch == '\r' || ch == '\n')
|
||||
{
|
||||
|
|
|
@ -243,6 +243,7 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static String[] CreateParamsArray()
|
||||
{
|
||||
char8* cmdLine = GetCommandLineArgs();
|
||||
|
@ -347,6 +348,7 @@ namespace System
|
|||
return strVals;
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static void DeleteStringArray(String[] arr)
|
||||
{
|
||||
for (var str in arr)
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace System
|
|||
private static float[7] sRoundPower10Single = .(
|
||||
1E0f, 1E1f, 1E2f, 1E3f, 1E4f, 1E5f, 1E6f);
|
||||
|
||||
private static float sMachineEpsilonFloat = GetMachineEpsilonFloat();
|
||||
|
||||
public const double PI_d = 3.14159265358979323846;
|
||||
public const double E_d = 2.7182818284590452354;
|
||||
public const float PI_f = 3.14159265358979323846f;
|
||||
|
@ -48,6 +50,33 @@ namespace System
|
|||
public static extern float Floor(float f);
|
||||
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)
|
||||
{
|
||||
if (Abs(value) < cSingleRoundLimit)
|
||||
|
@ -476,5 +505,125 @@ namespace System
|
|||
{
|
||||
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
|
||||
{
|
||||
const uint16 WINSOCK_VERSION = 0x0202;
|
||||
const int32 WSAENETRESET = 10052;
|
||||
const int32 WSAECONNABORTED = 10053;
|
||||
const int32 WSAECONNRESET = 10054;
|
||||
|
@ -170,11 +171,21 @@ namespace System.Net
|
|||
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||
static extern int32 WSAStartup(uint16 versionRequired, WSAData* wsaData);
|
||||
|
||||
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||
static extern int32 WSACleanup();
|
||||
|
||||
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||
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
|
||||
[CLink]
|
||||
static int32 errno;
|
||||
static int32* _errno() => &errno;
|
||||
#endif
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
|
@ -230,11 +241,22 @@ namespace System.Net
|
|||
#endif
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
public static int32 Init(uint16 versionRequired = WINSOCK_VERSION)
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -243,7 +265,7 @@ namespace System.Net
|
|||
#if BF_PLATFORM_WINDOWS
|
||||
return WSAGetLastError();
|
||||
#else
|
||||
return errno;
|
||||
return *_errno();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -2675,7 +2675,7 @@ namespace System
|
|||
return;
|
||||
|
||||
int i = sb.Length + (end - start);
|
||||
sb.Length = i;
|
||||
sb.PrepareBuffer(i);
|
||||
|
||||
var end;
|
||||
var start;
|
||||
|
|
|
@ -271,6 +271,7 @@ namespace System
|
|||
CreateAlways,
|
||||
CreateIfNotExists,
|
||||
OpenExisting,
|
||||
OpenAlways,
|
||||
};
|
||||
|
||||
public enum BfpFileCreateFlags : int32
|
||||
|
@ -337,6 +338,8 @@ namespace System
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern BfpFile* BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern int BfpFile_GetSystemHandle(BfpFile* file);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpFile_Release(BfpFile* file);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
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]
|
||||
public static extern int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpFile_Truncate(BfpFile* file);
|
||||
public static extern void BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
|
@ -410,7 +413,8 @@ namespace System
|
|||
AppData_LocalLow,
|
||||
AppData_Roaming,
|
||||
Programs,
|
||||
Programs_Common
|
||||
Programs_Common,
|
||||
Documents
|
||||
}
|
||||
|
||||
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:
|
||||
let attrData = Decode!<int64>(data);
|
||||
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:
|
||||
let stringId = Decode!<int32>(data);
|
||||
String str = String.[Friend]sIdStringLiterals[stringId];
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace System.Reflection
|
|||
get
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
Type.[Friend]Comptime_Method_GetName(mNativeMethodInstance);
|
||||
return "";
|
||||
return Type.[Friend]Comptime_Method_GetName(mNativeMethodInstance);
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
public int ParamCount
|
||||
|
|
|
@ -20,53 +20,13 @@ namespace System.Reflection
|
|||
mFieldData = fieldData;
|
||||
}
|
||||
|
||||
public int32 MemberOffset
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int32)mFieldData.mData;
|
||||
}
|
||||
}
|
||||
|
||||
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 TypeInstance DeclaringType => mTypeInstance;
|
||||
public int32 MemberOffset => (int32)mFieldData.mData;
|
||||
public Type FieldType => Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
||||
public bool IsConst => mFieldData.mFlags.HasFlag(.Const);
|
||||
public bool IsStatic => mFieldData.mFlags.HasFlag(.Static);
|
||||
public bool IsInstanceField => !mFieldData.mFlags.HasFlag(.Static) && !mFieldData.mFlags.HasFlag(.Const);
|
||||
public StringView Name => mFieldData.mName;
|
||||
|
||||
public Result<void, Error> SetValue(Object obj, Object value)
|
||||
{
|
||||
|
@ -525,7 +485,15 @@ namespace System.Reflection
|
|||
{
|
||||
mIdx++;
|
||||
if (mIdx == mTypeInstance.[Friend]mFieldDataCount)
|
||||
{
|
||||
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];
|
||||
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (fieldData.mFlags.HasFlag(FieldFlags.Static)));
|
||||
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!fieldData.mFlags.HasFlag(FieldFlags.Static)));
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace System.Reflection
|
|||
mMethodData = methodData;
|
||||
}
|
||||
|
||||
public TypeInstance DeclaringType => mTypeInstance;
|
||||
public bool IsInitialized => mMethodData != null;
|
||||
public StringView Name => mMethodData.[Friend]mName;
|
||||
public int ParamCount => mMethodData.[Friend]mParamCount;
|
||||
|
@ -37,11 +38,22 @@ namespace System.Reflection
|
|||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
case None;
|
||||
|
@ -777,7 +789,15 @@ namespace System.Reflection
|
|||
{
|
||||
mIdx++;
|
||||
if (mIdx == mTypeInstance.[Friend]mMethodDataCount)
|
||||
{
|
||||
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];
|
||||
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (methodData.mFlags.HasFlag(.Static)));
|
||||
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!methodData.mFlags.HasFlag(.Static)));
|
||||
|
|
|
@ -41,6 +41,26 @@ namespace System
|
|||
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)
|
||||
{
|
||||
return .Err(.NoResults);
|
||||
|
@ -123,7 +143,10 @@ namespace System.Reflection
|
|||
let objType = typeof(Object) as TypeInstance;
|
||||
|
||||
#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
|
||||
void* mem = new [Align(16)] uint8[mInstSize]* (?);
|
||||
obj = Internal.UnsafeCastToObject(mem);
|
||||
|
|
|
@ -20,22 +20,26 @@ namespace System
|
|||
|
||||
public T Value
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
return Unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public static implicit operator Result<T>(T value)
|
||||
{
|
||||
return .Ok(value);
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public static implicit operator T(Result<T> result)
|
||||
{
|
||||
return result.Unwrap();
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public void IgnoreError()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ using System.Threading;
|
|||
|
||||
namespace System
|
||||
{
|
||||
[StaticInitPriority(100)]
|
||||
class Runtime
|
||||
[StaticInitPriority(101)]
|
||||
static class Runtime
|
||||
{
|
||||
const int32 cVersion = 8;
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace System
|
|||
function void* (int size) mAlloc;
|
||||
function void (void* ptr) mFree;
|
||||
function void (Object obj) mObject_Delete;
|
||||
function void (Object obj, String str) mObject_ToString;
|
||||
void* mUnused0;
|
||||
function Type (Object obj) mObject_GetType;
|
||||
function void (Object obj) mObject_GCMarkMembers;
|
||||
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
|
||||
|
@ -141,13 +141,6 @@ namespace System
|
|||
delete obj;
|
||||
}
|
||||
|
||||
static void Object_ToString(Object obj, String str)
|
||||
{
|
||||
#if BF_DBG_RUNTIME
|
||||
obj.ToString(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
static Type Object_GetType(Object obj)
|
||||
{
|
||||
#if BF_DBG_RUNTIME
|
||||
|
@ -241,7 +234,6 @@ namespace System
|
|||
mAlloc = => Alloc;
|
||||
mFree = => Free;
|
||||
mObject_Delete = => Object_Delete;
|
||||
mObject_ToString = => Object_ToString;
|
||||
mObject_GetType = => Object_GetType;
|
||||
mObject_GCMarkMembers = => Object_GCMarkMembers;
|
||||
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
|
||||
|
|
|
@ -1,5 +1,35 @@
|
|||
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
|
||||
{
|
||||
public uint8[16] mHash;
|
||||
|
@ -50,6 +80,14 @@ namespace System.Security.Cryptography
|
|||
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
|
||||
|
|
|
@ -16,18 +16,35 @@ namespace System
|
|||
|
||||
public this(T[] array)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
this = default;
|
||||
return;
|
||||
}
|
||||
mPtr = &array.[Friend]GetRef(0);
|
||||
mLength = array.[Friend]mLength;
|
||||
}
|
||||
|
||||
public this(T[] array, int index)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
Debug.Assert(index == 0);
|
||||
this = default;
|
||||
return;
|
||||
}
|
||||
mPtr = &array[index];
|
||||
mLength = array.[Friend]mLength - index;
|
||||
}
|
||||
|
||||
public this(T[] array, int index, int length)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
Debug.Assert(index == 0 && length == 0);
|
||||
this = default;
|
||||
return;
|
||||
}
|
||||
if (length == 0)
|
||||
mPtr = null;
|
||||
else
|
||||
|
@ -110,13 +127,95 @@ namespace System
|
|||
|
||||
public ref T this[int index]
|
||||
{
|
||||
[Inline]
|
||||
[Checked]
|
||||
get
|
||||
{
|
||||
Runtime.Assert((uint)index < (uint)mLength);
|
||||
return ref mPtr[index];
|
||||
}
|
||||
|
||||
[Unchecked, Inline]
|
||||
get
|
||||
{
|
||||
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)
|
||||
{
|
||||
Debug.Assert((uint)index <= (uint)mLength);
|
||||
|
@ -200,6 +299,8 @@ namespace System
|
|||
return Enumerator(this);
|
||||
}
|
||||
|
||||
public ReverseEnumerator Reversed => ReverseEnumerator(this);
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
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
|
||||
{
|
||||
if (!MoveNext())
|
||||
|
|
|
@ -329,7 +329,7 @@ namespace System
|
|||
|
||||
set
|
||||
{
|
||||
Debug.Assert((uint)mLength <= (uint)value);
|
||||
Debug.Assert((uint)value <= (uint)mLength);
|
||||
mLength = (int_strsize)value;
|
||||
}
|
||||
}
|
||||
|
@ -1010,17 +1010,95 @@ namespace System
|
|||
|
||||
public ref char8 this[int index]
|
||||
{
|
||||
[Checked]
|
||||
get
|
||||
{
|
||||
Debug.Assert((uint)index < (uint)mLength);
|
||||
return ref Ptr[index];
|
||||
}
|
||||
|
||||
[Unchecked, Inline]
|
||||
get
|
||||
{
|
||||
return ref Ptr[index];
|
||||
}
|
||||
|
||||
[Checked]
|
||||
set
|
||||
{
|
||||
Debug.Assert((uint)index < (uint)mLength);
|
||||
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)
|
||||
|
@ -1351,12 +1429,7 @@ namespace System
|
|||
return -1;
|
||||
}
|
||||
|
||||
public bool Contains(String str)
|
||||
{
|
||||
return IndexOf(str) != -1;
|
||||
}
|
||||
|
||||
public bool Contains(String str, bool ignoreCase)
|
||||
public bool Contains(StringView str, bool ignoreCase = false)
|
||||
{
|
||||
return IndexOf(str, ignoreCase) != -1;
|
||||
}
|
||||
|
@ -1542,7 +1615,7 @@ namespace System
|
|||
mLength = newLength;
|
||||
}
|
||||
|
||||
public void Insert(int_strsize idx, char8 c)
|
||||
public void Insert(int idx, char8 c)
|
||||
{
|
||||
Contract.Requires(idx >= 0);
|
||||
|
||||
|
@ -1557,7 +1630,7 @@ namespace System
|
|||
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);
|
||||
|
||||
|
@ -1576,7 +1649,7 @@ namespace System
|
|||
mLength = newLength;
|
||||
}
|
||||
|
||||
public void Insert(int_strsize idx, char32 c)
|
||||
public void Insert(int idx, char32 c)
|
||||
{
|
||||
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);
|
||||
|
||||
|
@ -1700,7 +1773,7 @@ namespace System
|
|||
|
||||
//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)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
|
||||
|
||||
|
@ -1708,7 +1781,7 @@ namespace System
|
|||
if (charA != charB)
|
||||
return false;
|
||||
|
||||
// Next char8
|
||||
// Next char
|
||||
curA++;curB++;
|
||||
curLength--;
|
||||
}
|
||||
|
@ -1733,7 +1806,7 @@ namespace System
|
|||
|
||||
//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)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
|
||||
|
||||
|
@ -1741,7 +1814,7 @@ namespace System
|
|||
if (charA != charB)
|
||||
return charA - charB;
|
||||
|
||||
// Next char8
|
||||
// Next char
|
||||
a++;b++;
|
||||
length--;
|
||||
}
|
||||
|
@ -1761,7 +1834,7 @@ namespace System
|
|||
int_strsize charB = (int_strsize)*b;
|
||||
|
||||
//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)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
|
||||
|
||||
|
@ -1769,7 +1842,7 @@ namespace System
|
|||
if (charA != charB)
|
||||
return charA - charB;
|
||||
|
||||
// Next char8
|
||||
// Next char
|
||||
a++;b++;
|
||||
length--;
|
||||
}
|
||||
|
@ -2130,6 +2203,82 @@ namespace System
|
|||
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)
|
||||
{
|
||||
bool isFirst = true;
|
||||
|
@ -2271,6 +2420,7 @@ namespace System
|
|||
|
||||
public RawEnumerator RawChars
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
return RawEnumerator(Ptr, 0, mLength);
|
||||
|
@ -2279,6 +2429,7 @@ namespace System
|
|||
|
||||
public UTF8Enumerator DecodedChars
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
return UTF8Enumerator(Ptr, 0, mLength);
|
||||
|
@ -2440,6 +2591,7 @@ namespace System
|
|||
int_strsize mIdx;
|
||||
int_strsize mLength;
|
||||
|
||||
[Inline]
|
||||
public this(char8* ptr, int idx, int length)
|
||||
{
|
||||
mPtr = ptr;
|
||||
|
@ -2449,11 +2601,13 @@ namespace System
|
|||
|
||||
public char8 Current
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
return mPtr[mIdx];
|
||||
}
|
||||
|
||||
[Inline]
|
||||
set
|
||||
{
|
||||
mPtr[mIdx] = value;
|
||||
|
@ -2462,6 +2616,7 @@ namespace System
|
|||
|
||||
public ref char8 CurrentRef
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
return ref mPtr[mIdx];
|
||||
|
@ -2470,6 +2625,7 @@ namespace System
|
|||
|
||||
public int Index
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
return mIdx;
|
||||
|
@ -2478,42 +2634,29 @@ namespace System
|
|||
|
||||
public int Length
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool MoveNext() mut
|
||||
[Inline]
|
||||
public Result<char8> GetNext() mut
|
||||
{
|
||||
++mIdx;
|
||||
if (mIdx >= mLength)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public Result<char8> GetNext() mut
|
||||
{
|
||||
if (!MoveNext())
|
||||
return .Err;
|
||||
return Current;
|
||||
return mPtr[mIdx];
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public Result<char8*> GetNextRef() mut
|
||||
{
|
||||
if (!MoveNext())
|
||||
++mIdx;
|
||||
if (mIdx >= mLength)
|
||||
return .Err;
|
||||
return &CurrentRef;
|
||||
return &mPtr[mIdx];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2670,6 +2813,14 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
public int32 MatchIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
return mCurCount - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasMore
|
||||
{
|
||||
get
|
||||
|
@ -2821,6 +2972,97 @@ namespace System
|
|||
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
|
||||
{
|
||||
get
|
||||
|
@ -2914,6 +3156,13 @@ namespace System
|
|||
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)
|
||||
{
|
||||
if (mLength != str.[Friend]mLength)
|
||||
|
@ -3037,9 +3286,9 @@ namespace System
|
|||
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)
|
||||
|
@ -3130,6 +3379,92 @@ namespace System
|
|||
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)
|
||||
{
|
||||
if (mLength == 0)
|
||||
|
@ -3137,6 +3472,15 @@ namespace System
|
|||
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)
|
||||
{
|
||||
if (mLength == 0)
|
||||
|
@ -3144,6 +3488,19 @@ namespace System
|
|||
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)
|
||||
{
|
||||
String.QuoteString(Ptr, Length, outString);
|
||||
|
@ -3226,6 +3583,34 @@ namespace System
|
|||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
delete val;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Diagnostics;
|
||||
namespace System.Text
|
||||
{
|
||||
[StaticInitPriority(100)]
|
||||
abstract class Encoding
|
||||
{
|
||||
public enum DecodeError
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Diagnostics;
|
||||
namespace System.Text
|
||||
{
|
||||
public class UTF16
|
||||
public static class UTF16
|
||||
{
|
||||
public enum EncodeError
|
||||
{
|
||||
|
@ -140,10 +140,10 @@ namespace System.Text
|
|||
|
||||
public static int GetMaxEncodedLen(int utf8Len)
|
||||
{
|
||||
// Consider all incoming char8s are < \u80, each incoming char88 equals one outgoing char816 (utfLen * 1)
|
||||
// For char8s from \u80 to \u7FF, then two incoming char88 equals one outgoing char816 (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 char8s from \u1000 to \u10FFFF, then four incoming char88 equals two outgoing char816s (utfLen * 0.5)
|
||||
// Consider all incoming chars are < \u80, each incoming char8 equals one outgoing char16 (utfLen * 1)
|
||||
// For chars from \u80 to \u7FF, then two incoming char8 equals one outgoing char16 (utfLen * 0.5)
|
||||
// For chars from \u800 to \u7FFF, then three incoming char8 equals one or two char16s (utfLen * 0.33) to (utfLen * 0.67)
|
||||
// For chars from \u1000 to \u10FFFF, then four incoming char8 equals two outgoing char16s (utfLen * 0.5)
|
||||
return utf8Len;
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,7 @@ namespace System.Text
|
|||
if (c <= '\u{FFFF}')
|
||||
{
|
||||
#if BF_UTF_PEDANTIC
|
||||
// Illegal UTF16 char8?
|
||||
// Illegal UTF16 char?
|
||||
Debug.Assert((c <= '\u{D7FF}') || (c >= '\u{E000}'));
|
||||
#endif
|
||||
EncodeChar((char16)c);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Diagnostics;
|
||||
namespace System.Text
|
||||
{
|
||||
class UTF8
|
||||
static class UTF8
|
||||
{
|
||||
public const int8[256] sTrailingBytesForUTF8 =
|
||||
.(
|
||||
|
|
|
@ -8,10 +8,11 @@ namespace System.Threading
|
|||
public delegate void ThreadStart();
|
||||
public delegate void ParameterizedThreadStart(Object obj);
|
||||
|
||||
[StaticInitPriority(100)]
|
||||
public sealed class Thread
|
||||
{
|
||||
private int mInternalThread;
|
||||
private int32 mPriority;
|
||||
private ThreadPriority mPriority = .Normal;
|
||||
public int32 mMaxStackSize;
|
||||
private String mName ~ delete _;
|
||||
private Delegate mDelegate;
|
||||
|
@ -21,7 +22,7 @@ namespace System.Threading
|
|||
bool mAutoDelete;
|
||||
public static Thread sMainThread = new Thread() ~ delete _;
|
||||
|
||||
[StaticInitPriority(101)]
|
||||
[StaticInitPriority(102)]
|
||||
struct RuntimeThreadInit
|
||||
{
|
||||
static Object Thread_Alloc()
|
||||
|
@ -67,6 +68,8 @@ namespace System.Threading
|
|||
|
||||
if (thread.mName != null)
|
||||
thread.InformThreadNameChange(thread.mName);
|
||||
if (thread.mPriority != .Normal)
|
||||
thread.SetPriorityNative((.)thread.mPriority);
|
||||
|
||||
int32 stackStart = 0;
|
||||
thread.SetStackStart((void*)&stackStart);
|
||||
|
@ -219,8 +222,18 @@ namespace System.Threading
|
|||
|
||||
public ThreadPriority Priority
|
||||
{
|
||||
get { return (ThreadPriority)GetPriorityNative(); }
|
||||
set { SetPriorityNative((int32)value); }
|
||||
get
|
||||
{
|
||||
if (mInternalThread != 0)
|
||||
return (ThreadPriority)GetPriorityNative();
|
||||
return mPriority;
|
||||
}
|
||||
set
|
||||
{
|
||||
mPriority = value;
|
||||
if (mInternalThread != 0)
|
||||
SetPriorityNative((int32)value);
|
||||
}
|
||||
}
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern int32 GetPriorityNative();
|
||||
|
|
|
@ -253,7 +253,10 @@ namespace System {
|
|||
if (rule != null)
|
||||
rule = rule.Clone();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace System
|
|||
protected int32 mMemberDataOffset;
|
||||
protected TypeCode mTypeCode;
|
||||
protected uint8 mAlign;
|
||||
protected uint8 mAllocStackCountOverride;
|
||||
|
||||
public static TypeId TypeIdEnd
|
||||
{
|
||||
|
@ -683,13 +684,7 @@ namespace System
|
|||
|
||||
namespace System.Reflection
|
||||
{
|
||||
public struct TypeId : int32
|
||||
{
|
||||
public Type ToType()
|
||||
{
|
||||
return Type.[Friend]sTypes[(int32)this];
|
||||
}
|
||||
}
|
||||
public struct TypeId : int32 {}
|
||||
|
||||
[Ordered, AlwaysInclude(AssumeInstantiated=true)]
|
||||
public class TypeInstance : Type
|
||||
|
@ -724,6 +719,7 @@ namespace System.Reflection
|
|||
public int32 mMethodIdx;
|
||||
public int32 mVirtualIdx;
|
||||
public int32 mCustomAttributesIdx;
|
||||
public int32 mReturnCustomAttributesIdx;
|
||||
}
|
||||
|
||||
public enum ParamFlags : int16
|
||||
|
@ -740,6 +736,7 @@ namespace System.Reflection
|
|||
public TypeId mType;
|
||||
public ParamFlags mParamFlags;
|
||||
public int32 mDefaultIdx;
|
||||
public int32 mCustomAttributesIdx;
|
||||
}
|
||||
|
||||
public struct InterfaceData
|
||||
|
@ -1137,7 +1134,7 @@ namespace System.Reflection
|
|||
|
||||
public Type GetGenericArg(int argIdx)
|
||||
{
|
||||
return mResolvedTypeRefs[argIdx].ToType();
|
||||
return Type.GetType(mResolvedTypeRefs[argIdx]);
|
||||
}
|
||||
|
||||
public override void GetFullName(String strBuffer)
|
||||
|
@ -1191,7 +1188,10 @@ namespace System.Reflection
|
|||
let genericType = GetGenericArg(0);
|
||||
let arraySize = [Friend]mInstSize - genericType.Size + genericType.Stride * count;
|
||||
#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
|
||||
void* mem = new [Align(16)] uint8[arraySize]* (?);
|
||||
obj = Internal.UnsafeCastToObject(mem);
|
||||
|
|
|
@ -48,8 +48,8 @@ namespace System
|
|||
public struct VTable
|
||||
{
|
||||
public function HResult(COM_IUnknown* self, ref Guid riid, void** result) QueryInterface;
|
||||
public function HResult(COM_IUnknown* self) AddRef;
|
||||
public function HResult(COM_IUnknown* self) Release;
|
||||
public function uint32(COM_IUnknown* self) AddRef;
|
||||
public function uint32(COM_IUnknown* self) Release;
|
||||
}
|
||||
|
||||
public enum HResult : int32
|
||||
|
|
|
@ -876,7 +876,7 @@ namespace CURL
|
|||
static extern int curl_easy_perform(void* curl);
|
||||
|
||||
[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)]
|
||||
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()));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return WrapResult((ReturnCode)curl_easy_perform(mCURL));
|
||||
|
|
|
@ -8,7 +8,8 @@ namespace CURL
|
|||
{
|
||||
class Transfer
|
||||
{
|
||||
CURL.Easy mCurl = new CURL.Easy() ~ delete _;
|
||||
CURL.Easy mCurl;
|
||||
bool mOwns;
|
||||
bool mCancelling = false;
|
||||
List<uint8> mData = new List<uint8>() ~ delete _;
|
||||
Stopwatch mStatsTimer = new Stopwatch() ~ delete _;
|
||||
|
@ -59,7 +60,13 @@ namespace CURL
|
|||
|
||||
public this()
|
||||
{
|
||||
mCurl = new CURL.Easy();
|
||||
mOwns = true;
|
||||
}
|
||||
|
||||
public this(CURL.Easy curl)
|
||||
{
|
||||
mCurl = curl;
|
||||
}
|
||||
|
||||
public ~this()
|
||||
|
@ -67,6 +74,9 @@ namespace CURL
|
|||
mCancelling = true;
|
||||
if (mRunning)
|
||||
mDoneEvent.WaitFor();
|
||||
|
||||
if (mOwns)
|
||||
delete mCurl;
|
||||
}
|
||||
|
||||
int GetCurBytesPerSecond()
|
||||
|
@ -119,7 +129,7 @@ namespace CURL
|
|||
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;
|
||||
mCurl.SetOptFunc(.XferInfoFunction, (void*)callback);
|
||||
|
@ -133,6 +143,13 @@ namespace CURL
|
|||
mCurl.SetOpt(.URL, url);
|
||||
mCurl.SetOpt(.NoProgress, false);
|
||||
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()
|
||||
|
@ -178,6 +195,11 @@ namespace CURL
|
|||
return mResult;
|
||||
}
|
||||
|
||||
public void GetContentType(String outContentType)
|
||||
{
|
||||
mCurl.GetInfo(.ContentType, outContentType);
|
||||
}
|
||||
|
||||
public void Cancel(bool wait = false)
|
||||
{
|
||||
mCancelling = true;
|
||||
|
|
|
@ -421,8 +421,13 @@ void BFGC::RawShutdown()
|
|||
gDbgErrorString = errorStr;
|
||||
gDbgErrorString += "\n";
|
||||
|
||||
int passLeakCount = 0;
|
||||
|
||||
for (auto& rawLeak : mSweepInfo.mRawLeaks)
|
||||
{
|
||||
if (passLeakCount == 20000) // Only display so many...
|
||||
break;
|
||||
|
||||
Beefy::String typeName;
|
||||
if (rawLeak.mRawAllocData->mType != NULL)
|
||||
typeName = rawLeak.mRawAllocData->mType->GetFullName() + "*";
|
||||
|
@ -451,6 +456,8 @@ void BFGC::RawShutdown()
|
|||
|
||||
if (gDbgErrorString.length() < 256)
|
||||
gDbgErrorString += StrFormat(" %s\n", leakStr.c_str());
|
||||
|
||||
passLeakCount++;
|
||||
}
|
||||
|
||||
BF_ASSERT(mSweepInfo.mLeakCount > 0);
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace bf
|
|||
void*(*Alloc)(intptr size);
|
||||
void(*Free)(void* ptr);
|
||||
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);
|
||||
void(*Object_GCMarkMembers)(bf::System::Object* obj);
|
||||
bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId);
|
||||
|
|
|
@ -85,7 +85,6 @@ namespace bf
|
|||
BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj);
|
||||
BFRT_EXPORT static void ObjectDynCheck(Object* object, int typeId, bool allowNull);
|
||||
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 FatalError(String* error, intptr stackOffset = 0);
|
||||
BFRT_EXPORT static void MemCpy(void* dest, void* src, intptr length);
|
||||
|
@ -215,17 +214,19 @@ static void TestReadCmd(Beefy::String& str);
|
|||
|
||||
static void Internal_FatalError(const char* error)
|
||||
{
|
||||
if (gClientPipe != NULL)
|
||||
if ((gClientPipe != NULL) && (!gTestBreakOnFailure))
|
||||
{
|
||||
Beefy::String str = ":TestFatal\t";
|
||||
str += error;
|
||||
str.Replace('\n', '\r');
|
||||
str += "\n";
|
||||
TestString(str);
|
||||
|
||||
Beefy::String result;
|
||||
TestReadCmd(result);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
else
|
||||
BfpSystem_FatalError(error, "BEEF FATAL ERROR");
|
||||
}
|
||||
|
||||
|
@ -395,26 +396,21 @@ void* Internal::UnsafeCastToPtr(Object* 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)
|
||||
{
|
||||
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()))
|
||||
{
|
||||
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)
|
||||
{
|
||||
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()))
|
||||
{
|
||||
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
|
||||
|
@ -659,6 +671,7 @@ void Internal::Test_Error(char* error)
|
|||
{
|
||||
Beefy::String str = ":TestFail\t";
|
||||
str += error;
|
||||
str.Replace('\n', '\r');
|
||||
str += "\n";
|
||||
TestString(str);
|
||||
}
|
||||
|
@ -670,12 +683,7 @@ void Internal::Test_Write(char* strPtr)
|
|||
{
|
||||
Beefy::String str = ":TestWrite\t";
|
||||
str += strPtr;
|
||||
for (char& c : str)
|
||||
{
|
||||
if (c == '\n')
|
||||
c = '\r';
|
||||
}
|
||||
|
||||
str.Replace('\n', '\r');
|
||||
str += "\n";
|
||||
TestString(str);
|
||||
}
|
||||
|
|
|
@ -53,12 +53,12 @@ void Thread::SetJoinOnDelete(bool joinOnDelete)
|
|||
|
||||
int Thread::GetPriorityNative()
|
||||
{
|
||||
return (int)BfpThread_GetPriority(GetInternalThread()->mThreadHandle, NULL);
|
||||
return (int)BfpThread_GetPriority(GetInternalThread()->mThreadHandle, NULL) + 2;
|
||||
}
|
||||
|
||||
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()
|
||||
|
|
|
@ -234,9 +234,8 @@ namespace BeefPerf
|
|||
mMainFrame = new MainFrame();
|
||||
mDockingFrame = mMainFrame.mDockingFrame;
|
||||
|
||||
BFWindow.Flags windowFlags = BFWindow.Flags.Border | BFWindow.Flags.SysMenu | //| BFWindow.Flags.CaptureMediaKeys |
|
||||
BFWindow.Flags.Caption | BFWindow.Flags.Minimize | BFWindow.Flags.QuitOnClose | BFWindowBase.Flags.Resizable |
|
||||
BFWindow.Flags.Menu | BFWindow.Flags.SysMenu;
|
||||
BFWindow.Flags windowFlags = .Border | .SysMenu | .Caption | .Minimize | .Maximize |
|
||||
.QuitOnClose | .Resizable | .Menu;
|
||||
if (mWantsFullscreen)
|
||||
windowFlags |= BFWindowBase.Flags.Fullscreen;
|
||||
|
||||
|
@ -336,7 +335,7 @@ namespace BeefPerf
|
|||
|
||||
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 () =>
|
||||
{
|
||||
var tabbedView = tabButton.mTabbedView;
|
||||
|
@ -921,7 +920,7 @@ namespace BeefPerf
|
|||
TabbedView tabbedView = FindTabbedView(mDockingFrame, -1, 1);
|
||||
if (tabbedView != null)
|
||||
{
|
||||
tabButton = tabbedView.AddTab(name, width, tabContent, ownsContent);
|
||||
tabButton = tabbedView.AddTab(name, width, tabContent, ownsContent, 0);
|
||||
result = ShowTabResult.OpenedNew;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -311,7 +311,7 @@ namespace BeefPerf
|
|||
{
|
||||
var str = scope::String();
|
||||
if (argView.UnQuoteString(str) case .Err)
|
||||
Fail("Failed to unquote string");
|
||||
Fail($"Failed to unquote string: {argView}\nCmd:{cmdLineView}");
|
||||
args.Add(str);
|
||||
isLiteralString = false;
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ namespace BeefPerf
|
|||
case .Ok(let val):
|
||||
args.Add(scope:: box val);
|
||||
case .Err:
|
||||
Fail("Failed to parse float");
|
||||
Fail($"Failed to parse float: {argView}\nCmd:{cmdLineView}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ namespace BeefPerf
|
|||
case .Ok(let val):
|
||||
args.Add(scope:: box val);
|
||||
case .Err:
|
||||
Fail("Failed to parse double");
|
||||
Fail($"Failed to parse double: {argView}\nCmd:{cmdLineView}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ namespace BeefPerf
|
|||
case .Ok(let val):
|
||||
args.Add(scope:: box val);
|
||||
case .Err:
|
||||
Fail("Failed to parse int");
|
||||
Fail($"Failed to parse int: {argView}\nCmd:{cmdLineView}");
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -678,6 +695,16 @@ BF_EXPORT void BF_CALLTYPE RenderState_Delete(RenderState* 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_ASSERT((width >= 0) && (height >= 0));
|
||||
|
@ -715,6 +742,11 @@ BF_EXPORT void BF_CALLTYPE RenderState_SetDepthWrite(RenderState* renderState, i
|
|||
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)
|
||||
{
|
||||
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="gfx\DrawLayer.cpp" />
|
||||
<ClCompile Include="gfx\FTFont.cpp" />
|
||||
<ClCompile Include="gfx\glTF.cpp" />
|
||||
<ClCompile Include="gfx\ModelDef.cpp" />
|
||||
<ClCompile Include="gfx\ModelInstance.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\CatmullRom.cpp" />
|
||||
<ClCompile Include="util\ChunkedDataBuffer.cpp" />
|
||||
<ClCompile Include="util\Compress.cpp" />
|
||||
<ClCompile Include="util\CubicFuncSpline.cpp" />
|
||||
<ClCompile Include="util\CubicSpline.cpp" />
|
||||
<ClCompile Include="util\Hash.cpp" />
|
||||
<ClCompile Include="util\Heap.cpp" />
|
||||
<ClCompile Include="util\Json.cpp" />
|
||||
<ClCompile Include="util\MappedFile.cpp" />
|
||||
<ClCompile Include="util\MathUtils.cpp" />
|
||||
<ClCompile Include="util\Matrix4.cpp" />
|
||||
<ClCompile Include="util\PerfTimer.cpp" />
|
||||
<ClCompile Include="util\Point.cpp" />
|
||||
<ClCompile Include="util\PolySpline.cpp" />
|
||||
<ClCompile Include="util\Quaternion.cpp" />
|
||||
<ClCompile Include="util\Sphere.cpp" />
|
||||
<ClCompile Include="util\StackHelper.cpp" />
|
||||
<ClCompile Include="util\String.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\Font.h" />
|
||||
<ClInclude Include="gfx\FTFont.h" />
|
||||
<ClInclude Include="gfx\glTF.h" />
|
||||
<ClInclude Include="gfx\ModelDef.h" />
|
||||
<ClInclude Include="gfx\ModelInstance.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\ChunkedDataBuffer.h" />
|
||||
<ClInclude Include="util\ChunkedVector.h" />
|
||||
<ClInclude Include="util\Compress.h" />
|
||||
<ClInclude Include="util\CritSect.h" />
|
||||
<ClInclude Include="util\CubicFuncSpline.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\HashSet.h" />
|
||||
<ClInclude Include="util\Heap.h" />
|
||||
<ClInclude Include="util\Json.h" />
|
||||
<ClInclude Include="util\MappedFile.h" />
|
||||
<ClInclude Include="util\MathUtils.h" />
|
||||
<ClInclude Include="util\Matrix4.h" />
|
||||
<ClInclude Include="util\MultiHashSet.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\SizedArray.h" />
|
||||
<ClInclude Include="util\SLIList.h" />
|
||||
<ClInclude Include="util\Sphere.h" />
|
||||
<ClInclude Include="util\StackHelper.h" />
|
||||
<ClInclude Include="util\String.h" />
|
||||
<ClInclude Include="util\ThreadPool.h" />
|
||||
|
|
|
@ -707,6 +707,21 @@
|
|||
<ClCompile Include="util\Heap.cpp">
|
||||
<Filter>src\util</Filter>
|
||||
</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>
|
||||
<ClInclude Include="Common.h">
|
||||
|
@ -1075,6 +1090,21 @@
|
|||
<ClInclude Include="util\Heap.h">
|
||||
<Filter>src\util</Filter>
|
||||
</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>
|
||||
<CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">
|
||||
|
|
|
@ -278,6 +278,7 @@ file(GLOB SRC_FILES
|
|||
util/BSpline.cpp
|
||||
util/CatmullRom.cpp
|
||||
util/ChunkedDataBuffer.cpp
|
||||
util/Compress.cpp
|
||||
util/CubicFuncSpline.cpp
|
||||
util/CubicSpline.cpp
|
||||
util/FileEnumerator.cpp
|
||||
|
@ -285,11 +286,13 @@ file(GLOB SRC_FILES
|
|||
util/Heap.cpp
|
||||
util/Json.cpp
|
||||
util/MappedFile.cpp
|
||||
util/MathUtils.cpp
|
||||
util/Matrix4.cpp
|
||||
util/PerfTimer.cpp
|
||||
util/Point.cpp
|
||||
util/PolySpline.cpp
|
||||
util/Quaternion.cpp
|
||||
util/Sphere.cpp
|
||||
util/String.cpp
|
||||
util/StackHelper.cpp
|
||||
util/ThreadPool.cpp
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "platform/PlatformHelper.h"
|
||||
|
||||
#ifndef BF_SMALL
|
||||
#define STB_SPRINTF_DECORATE(name) BF_stbsp_##name
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#include "third_party/stb/stb_sprintf.h"
|
||||
#endif
|
||||
|
@ -811,7 +812,7 @@ String Beefy::vformat(const char* fmt, va_list argPtr)
|
|||
{
|
||||
String str;
|
||||
char buf[STB_SPRINTF_MIN];
|
||||
stbsp_vsprintfcb(StbspCallback, (void*)&str, buf, fmt, argPtr);
|
||||
BF_stbsp_vsprintfcb(StbspCallback, (void*)&str, buf, fmt, argPtr);
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
@ -943,6 +944,21 @@ char* Beefy::LoadTextData(const StringImpl& path, int* size)
|
|||
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
|
||||
unsigned long long __cdecl _byteswap_uint64(unsigned long long _Int64)
|
||||
{
|
||||
|
@ -1263,3 +1279,4 @@ void Beefy::BFFatalError(const char* message, const char* file, int line)
|
|||
{
|
||||
BFFatalError(String(message), String(file), line);
|
||||
}
|
||||
|
||||
|
|
|
@ -220,6 +220,7 @@ int32 GetHighestBitSet(int32 n);
|
|||
|
||||
uint8* LoadBinaryData(const StringImpl& path, int* size);
|
||||
char* LoadTextData(const StringImpl& path, int* size);
|
||||
bool LoadTextData(const StringImpl& path, StringImpl& str);
|
||||
int64 GetFileTimeWrite(const StringImpl& path);
|
||||
String GetFileDir(const StringImpl& path);
|
||||
String GetFileName(const StringImpl& path);
|
||||
|
|
|
@ -49,6 +49,14 @@ public:
|
|||
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(uint8 val);
|
||||
virtual void Write(int8 val);
|
||||
|
|
|
@ -219,7 +219,8 @@ void SysFileStream::SetSizeFast(int size)
|
|||
|
||||
int curPos = GetPos();
|
||||
SetPos(size);
|
||||
BfpFile_Truncate(mFile);
|
||||
BfpFileResult result = BfpFileResult_Ok;
|
||||
BfpFile_Truncate(mFile, &result);
|
||||
SetPos(curPos);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ class Span
|
|||
{
|
||||
public:
|
||||
T* mVals;
|
||||
int mSize;
|
||||
intptr mSize;
|
||||
|
||||
public:
|
||||
struct Iterator
|
||||
|
@ -47,16 +47,17 @@ public:
|
|||
|
||||
Span()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Span(T* mPtr, int size)
|
||||
{
|
||||
mSize = (int)refVec.size();
|
||||
mVals = NULL;
|
||||
mSize = 0;
|
||||
}
|
||||
|
||||
T& operator[](int idx) const
|
||||
Span(T* mPtr, intptr size)
|
||||
{
|
||||
mVals = mPtr;
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
T& operator[](intptr idx) const
|
||||
{
|
||||
return mVals[idx];
|
||||
}
|
||||
|
@ -76,7 +77,7 @@ public:
|
|||
return mVals[mSize - 1];
|
||||
}
|
||||
|
||||
int size() const
|
||||
intptr size() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
@ -91,7 +92,7 @@ public:
|
|||
return mSize == 0;
|
||||
}
|
||||
|
||||
T Get(int idx)
|
||||
T Get(intptr idx)
|
||||
{
|
||||
if ((idx < 0) || (idx >= mSize))
|
||||
return (T)0;
|
||||
|
@ -99,7 +100,7 @@ public:
|
|||
}
|
||||
|
||||
template <typename T2>
|
||||
T2 GetAs(int idx)
|
||||
T2 GetAs(intptr idx)
|
||||
{
|
||||
if ((idx < 0) || (idx >= mSize))
|
||||
return (T2)0;
|
||||
|
@ -120,7 +121,7 @@ public:
|
|||
return mVals[0];
|
||||
}
|
||||
|
||||
void SetSize(int size)
|
||||
void SetSize(intptr size)
|
||||
{
|
||||
BF_ASSERT(size <= mSize);
|
||||
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->PhysSetRenderTarget(textureSegment->mTexture);
|
||||
drawLayer->Draw();
|
||||
drawLayer->Clear();
|
||||
renderDevice->mCurRenderTarget = prevTarget;
|
||||
}
|
||||
|
|
|
@ -99,8 +99,8 @@ public:
|
|||
virtual DrawBatch* AllocateBatch(int minVtxCount, int minIdxCount);
|
||||
void QueueRenderCmd(RenderCmd* renderCmd);
|
||||
virtual RenderCmd* CreateSetTextureCmd(int textureIdx, Texture* texture) = 0;
|
||||
virtual void SetShaderConstantData(int slotIdx, void* constData, int size) = 0;
|
||||
virtual void SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount);
|
||||
virtual void SetShaderConstantData(int usageIdx, int slotIdx, void* constData, int size) = 0;
|
||||
virtual void SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount);
|
||||
|
||||
public:
|
||||
DrawLayer();
|
||||
|
|
|
@ -144,7 +144,16 @@ bool FTFont::Load(const StringImpl& fileName, float pointSize)
|
|||
|
||||
face->mFileName = fileName;
|
||||
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;
|
||||
}
|
||||
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