From 334580acdcc9bf6339963ee90f83d8f870d5a589 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Thu, 3 Oct 2024 21:39:36 +0800 Subject: [PATCH] feat: update BMapSharp code --- BMapBindings/BMapSharp/BMapSharp/BMap.cs | 21 +- .../BMapSharp/BMapSharp/BMapWrapper.cs | 276 ++++++++++++++---- 2 files changed, 227 insertions(+), 70 deletions(-) diff --git a/BMapBindings/BMapSharp/BMapSharp/BMap.cs b/BMapBindings/BMapSharp/BMapSharp/BMap.cs index e837f60..549b0a9 100644 --- a/BMapBindings/BMapSharp/BMapSharp/BMap.cs +++ b/BMapBindings/BMapSharp/BMapSharp/BMap.cs @@ -5,16 +5,19 @@ using BMapSharp.VirtoolsTypes; namespace BMapSharp { - public static class BMap { - - /// BMapSharp module specific exception. - public class BMapException : Exception { - public BMapException() {} - public BMapException(string message) - : base(message) {} - public BMapException(string message, Exception inner) - : base(message, inner) {} + /// BMapSharp module specific exception. + public class BMapException : Exception { + public BMapException() {} + public BMapException(string message) + : base(message) {} + public BMapException(string message, Exception inner) + : base(message, inner) {} + public static void ThrowIfFailed(bool condition) { + if (!condition) throw new BMapException("BMap operation failed."); } + } + + public static class BMap { /// The callback function of BMap. /// The message content need to be printed. diff --git a/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs b/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs index 6f18f51..e73eaff 100644 --- a/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs +++ b/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs @@ -1,112 +1,266 @@ using System; +using System.Reflection.Metadata.Ecma335; using System.Runtime.InteropServices; using BMapSharp.VirtoolsTypes; namespace BMapSharp.BMapWrapper { - public sealed class BMapGuard : IDisposable { - internal BMapGuard() { - BMap.BMInit(); + /// + /// The guard of native BMap environment. + /// This class initialize native BMap environment when constructing and free it when destructing. + /// + internal sealed class BMapGuard : SafeHandle { + private static readonly IntPtr MAGIC_HANDLE = (IntPtr)61; + internal BMapGuard() : base(Utils.INVALID_PTR, true) { + BMapException.ThrowIfFailed(BMap.BMInit()); + this.handle = MAGIC_HANDLE; } - public void Dispose() { - throw new NotImplementedException(); - } - - public bool IsBMapAvailable() { - + public override bool IsInvalid => this.handle == Utils.INVALID_PTR; + protected override bool ReleaseHandle() { + return BMap.BMDispose(); } } - public static class Utilities { - public static readonly BMapGuard Guard = new BMapGuard(); - + public static class Utils { + /// The representation of invalid raw pointer. internal static readonly IntPtr INVALID_PTR = IntPtr.Zero; + /// The representation of invalid CK_ID. internal static readonly uint INVALID_CKID = 0u; + /// + /// The function used as callback for BMap. + /// It just writes the data in console. + /// internal static void BMapSharpCallback(string msg) { Console.WriteLine(msg); } + + private static readonly BMapGuard Singleton = new BMapGuard(); + public static bool IsBMapAvailable() { + return !Singleton.IsInvalid; + } } - public abstract class AbstractPointer : IComparable, IEquatable { - private IntPtr mRawPointer; - - protected AbstractPointer(IntPtr raw_pointer) { - mRawPointer = raw_pointer; + public abstract class AbstractPointer : SafeHandle { + internal AbstractPointer(IntPtr raw_pointer) : base(Utils.INVALID_PTR, true) { + this.handle = raw_pointer; } - protected virtual bool IsValid() => mRawPointer != Utilities.INVALID_PTR; - protected IntPtr GetPointer() => mRawPointer; - protected void SetPointer(IntPtr raw_pointer) => mRawPointer = raw_pointer; + public override bool IsInvalid => this.handle == Utils.INVALID_PTR; + protected override bool ReleaseHandle() => throw new NotImplementedException(); - #region IComparable + protected bool isValid() => this.handle != Utils.INVALID_PTR; + protected IntPtr getPointer() => this.handle; - public int CompareTo(AbstractPointer other) { - return mRawPointer.CompareTo(other.mRawPointer); - } + // protected AbstractPointer(IntPtr raw_pointer) : base(raw_pointer, true) {} - #endregion + // protected IntPtr GetPointer() => this.handle; + // public override bool IsInvalid { get { return this.handle == Utils.INVALID_PTR; } } - #region IEquatable + // #region IComparable - public static bool operator ==(AbstractPointer left, AbstractPointer right) => left.mRawPointer == right.mRawPointer; - public static bool operator !=(AbstractPointer left, AbstractPointer right) => left.mRawPointer != right.mRawPointer; + // public int CompareTo(AbstractPointer other) { + // return m_RawPointer.CompareTo(other.m_RawPointer); + // } - public bool Equals(AbstractPointer other) => this == other; - public override bool Equals(object obj) { - return (!(obj is null)) && (obj is AbstractPointer) && this.Equals((AbstractPointer)obj); - } + // #endregion - #endregion + // #region IEquatable + + // public override bool Equals(object obj) => this.Equals(obj as AbstractPointer); + // public bool Equals(AbstractPointer other) { + // if (other is null) return false; + // if (Object.ReferenceEquals(this, other)) return true; + // // if (this.GetType() != other.GetType()) return false; + // return this.m_RawPointer == other.m_RawPointer; + // } + + // public static bool operator ==(AbstractPointer lhs, AbstractPointer rhs) { + // if (lhs is null) { + // if (rhs is null) return true; + // return false; + // } + // return lhs.Equals(rhs); + // } + // public static bool operator !=(AbstractPointer lhs, AbstractPointer rhs) => !(lhs == rhs); + + // #endregion #region Misc - public override int GetHashCode() => mRawPointer.GetHashCode(); - public override string ToString() => mRawPointer.ToString(); + public override int GetHashCode() => this.handle.GetHashCode(); + public override string ToString() => this.handle.ToString(); #endregion } - public abstract class AbstractCKObject : AbstractPointer, IComparable, IEquatable { - private uint mCKID; - - protected AbstractCKObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer) { - mCKID = ckid; + public abstract class AbstractCKObject { + internal AbstractCKObject(IntPtr raw_pointer, uint ckid) { + m_RawPointer = raw_pointer; + m_CKID = ckid; } - protected override bool IsValid() => base.IsValid() && mCKID != Utilities.INVALID_CKID; - protected uint GetCKID() => mCKID; + private readonly IntPtr m_RawPointer; + private readonly uint m_CKID; + protected bool isValid() => m_RawPointer != Utils.INVALID_PTR && m_RawPointer != Utils.INVALID_CKID; + protected IntPtr getPointer() => m_RawPointer; + protected uint getCKID() => m_CKID; - #region IComparable + // private uint m_CKID; - public int CompareTo(AbstractCKObject other) { - var ret = base.CompareTo((AbstractPointer)other); - if (ret != 0) return ret; - return mCKID.CompareTo(other.mCKID); - } + // protected AbstractCKObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer) { + // m_CKID = ckid; + // } - #endregion + // protected override bool IsValid() => base.IsValid() && m_CKID != Utils.INVALID_CKID; + // protected uint GetCKID() => m_CKID; - #region IEquatable + // #region IComparable - public static bool operator ==(AbstractCKObject left, AbstractCKObject right) => - ((AbstractPointer)left == (AbstractPointer)right) && left.mCKID == right.mCKID; - public static bool operator !=(AbstractCKObject left, AbstractCKObject right) => - ((AbstractPointer)left != (AbstractPointer)right) || left.mCKID != right.mCKID; + // public int CompareTo(AbstractCKObject other) { + // var ret = base.CompareTo((AbstractPointer)other); + // if (ret != 0) return ret; + // return m_CKID.CompareTo(other.m_CKID); + // } - public bool Equals(AbstractCKObject other) => this == other; - public override bool Equals(object obj) { - return (!(obj is null)) && (obj is AbstractCKObject) && this.Equals((AbstractCKObject)obj); - } + // #endregion - #endregion + // #region IEquatable + + // public override bool Equals(object obj) => this.Equals(obj as AbstractCKObject); + // public bool Equals(AbstractCKObject other) { + // if (other is null) return false; + // if (Object.ReferenceEquals(this, other)) return true; + + // } + + // public static bool operator ==(AbstractCKObject left, AbstractCKObject right) => + // ((AbstractPointer)left == (AbstractPointer)right) && left.m_CKID == right.m_CKID; + // public static bool operator !=(AbstractCKObject left, AbstractCKObject right) => + // ((AbstractPointer)left != (AbstractPointer)right) || left.m_CKID != right.m_CKID; + + // #endregion #region Misc - public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), mCKID); - public override string ToString() => $"{base.ToString()} {mCKID.ToString()}"; + public override int GetHashCode() => HashCode.Combine(m_RawPointer, m_CKID); + public override string ToString() => $"{m_RawPointer}, {m_CKID}"; #endregion } + public class BMObject : AbstractCKObject { + internal BMObject(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {} + + public string GetName() { + BMapException.ThrowIfFailed(BMap.BMObject_GetName( + this.getPointer(), this.getCKID(), out string out_name + )); + return out_name; + } + public void SetName(string name) { + BMapException.ThrowIfFailed(BMap.BMObject_SetName( + this.getPointer(), this.getCKID(), name + )); + } + } + + public class BMTexture : BMObject { + internal BMTexture(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {} + } + + public class BMMaterial : BMObject { + internal BMMaterial(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {} + } + + public class BMMesh : BMObject { + internal BMMesh(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {} + } + + public class BM3dObject : BMObject { + internal BM3dObject(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {} + } + + public class BMGroup : BMObject { + internal BMGroup(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {} + } + + public sealed class BMFileReader : AbstractPointer { + private static IntPtr AllocateHandle(string file_name, string temp_folder, string texture_folder, string[] encodings) { + BMapException.ThrowIfFailed(BMap.BMFile_Load( + file_name, temp_folder, texture_folder, + Utils.BMapSharpCallback, + (uint)encodings.Length, encodings, + out IntPtr out_file + )); + return out_file; + } + protected override bool ReleaseHandle() { + return BMap.BMFile_Free(this.handle); + } + public BMFileReader(string file_name, string temp_folder, string texture_folder, string[] encodings) + : base(AllocateHandle(file_name, temp_folder, texture_folder, encodings)) {} + + public uint GetTextureCount() { + BMapException.ThrowIfFailed(BMap.BMFile_GetTextureCount(this.getPointer(), out uint out_count)); + return out_count; + } + public IEnumerable GetTextures() { + uint count = GetTextureCount(); + for (uint i = 0; i < count; ++i) { + BMapException.ThrowIfFailed(BMap.BMFile_GetTexture(this.getPointer(), i, out uint out_id)); + yield return new BMTexture(this.getPointer(), out_id); + } + } + + public uint GetMaterialCount() { + BMapException.ThrowIfFailed(BMap.BMFile_GetMaterialCount(this.getPointer(), out uint out_count)); + return out_count; + } + public IEnumerable GetMaterials() { + uint count = GetMaterialCount(); + for (uint i = 0; i < count; ++i) { + BMapException.ThrowIfFailed(BMap.BMFile_GetMaterial(this.getPointer(), i, out uint out_id)); + yield return new BMMaterial(this.getPointer(), out_id); + } + } + + public uint GetMeshCount() { + BMapException.ThrowIfFailed(BMap.BMFile_GetMeshCount(this.getPointer(), out uint out_count)); + return out_count; + } + public IEnumerable GetMeshs() { + uint count = GetMeshCount(); + for (uint i = 0; i < count; ++i) { + BMapException.ThrowIfFailed(BMap.BMFile_GetMesh(this.getPointer(), i, out uint out_id)); + yield return new BMMesh(this.getPointer(), out_id); + } + } + + public uint Get3dObjectCount() { + BMapException.ThrowIfFailed(BMap.BMFile_Get3dObjectCount(this.getPointer(), out uint out_count)); + return out_count; + } + public IEnumerable Get3dObjects() { + uint count = Get3dObjectCount(); + for (uint i = 0; i < count; ++i) { + BMapException.ThrowIfFailed(BMap.BMFile_Get3dObject(this.getPointer(), i, out uint out_id)); + yield return new BM3dObject(this.getPointer(), out_id); + } + } + + public uint GetGroupCount() { + BMapException.ThrowIfFailed(BMap.BMFile_GetGroupCount(this.getPointer(), out uint out_count)); + return out_count; + } + public IEnumerable GetGroups() { + uint count = GetGroupCount(); + for (uint i = 0; i < count; ++i) { + BMapException.ThrowIfFailed(BMap.BMFile_GetGroup(this.getPointer(), i, out uint out_id)); + yield return new BMGroup(this.getPointer(), out_id); + } + } + + } + }