From 3e4084c42a30a3008ba108198a35981f8ea45ae2 Mon Sep 17 00:00:00 2001 From: Misaki Date: Sun, 15 Mar 2026 02:19:40 +0900 Subject: [PATCH] Added ufbx warper --- .../AssetHandler/TextureProcessor.cs | 2 +- src/GhostEngine.slnx | 3 + src/Test/Ghost.MicroTest/NvttBindingTest.cs | 2 +- src/Test/Ghost.MicroTest/UfbxBindingTest.cs | 68 +- .../{Warper => Wrapper}/NvttBatchList.cs | 2 +- .../NvttCompressionOptions.cs | 2 +- .../{Warper => Wrapper}/NvttContext.cs | 2 +- .../{Warper => Wrapper}/NvttCubeSurface.cs | 2 +- .../{Warper => Wrapper}/NvttGlobal.cs | 2 +- .../{Warper => Wrapper}/NvttInterop.cs | 2 +- .../{Warper => Wrapper}/NvttOutputOptions.cs | 2 +- .../{Warper => Wrapper}/NvttSurface.cs | 2 +- .../{Warper => Wrapper}/NvttSurfaceSet.cs | 2 +- .../{Warper => Wrapper}/NvttTimingContext.cs | 2 +- src/ThridParty/Ghost.Ufbx/Generated/Api.cs | 25 +- .../Ghost.Ufbx/Generated/ufbx_baked_quat.cs | 3 +- .../Ghost.Ufbx/Generated/ufbx_edge.cs | 1 + .../Generated/ufbx_material_fbx_maps.cs | 1 + .../Generated/ufbx_material_features.cs | 1 + .../Generated/ufbx_material_pbr_maps.cs | 1 + .../Ghost.Ufbx/Generated/ufbx_metadata.cs | 3 +- .../Ghost.Ufbx/Generated/ufbx_node.cs | 6 +- .../Ghost.Ufbx/Generated/ufbx_prop.cs | 1 + .../Ghost.Ufbx/Generated/ufbx_scene.cs | 1 + .../Ghost.Ufbx/Generated/ufbx_transform.cs | 3 +- src/ThridParty/Ghost.Ufbx/Ghost.Ufbx.csproj | 5 - src/ThridParty/Ghost.Ufbx/LoadOpts.cs | 47 + .../Ghost.Ufbx/UfbxErrorExtensions.cs | 25 + .../Ghost.Ufbx/Wrapper/Allocator.nativegen.cs | 17 + .../Wrapper/AllocatorOpts.nativegen.cs | 25 + .../Ghost.Ufbx/Wrapper/Anim.nativegen.cs | 91 ++ .../Ghost.Ufbx/Wrapper/AnimCurve.nativegen.cs | 50 + .../Wrapper/AnimCurveList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/AnimLayer.nativegen.cs | 60 + .../Wrapper/AnimLayerList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/AnimOpts.nativegen.cs | 27 + .../Ghost.Ufbx/Wrapper/AnimProp.nativegen.cs | 24 + .../Ghost.Ufbx/Wrapper/AnimStack.nativegen.cs | 35 + .../Wrapper/AnimStackList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/AnimValue.nativegen.cs | 48 + .../Wrapper/AnimValueList.nativegen.cs | 52 + .../Wrapper/Application.nativegen.cs | 24 + .../Ghost.Ufbx/Wrapper/AudioClip.nativegen.cs | 43 + .../Wrapper/AudioClipList.nativegen.cs | 52 + .../Wrapper/AudioLayer.nativegen.cs | 28 + .../Wrapper/AudioLayerList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/BakeOpts.nativegen.cs | 53 + .../Ghost.Ufbx/Wrapper/BakedAnim.nativegen.cs | 61 + .../Wrapper/BakedAnimMetadata.nativegen.cs | 23 + .../Wrapper/BakedElement.nativegen.cs | 19 + .../Ghost.Ufbx/Wrapper/BakedNode.nativegen.cs | 31 + .../Ghost.Ufbx/Wrapper/BakedProp.nativegen.cs | 22 + .../Ghost.Ufbx/Wrapper/BakedQuat.nativegen.cs | 21 + .../Ghost.Ufbx/Wrapper/BakedVec3.nativegen.cs | 21 + .../Wrapper/BlendChannel.nativegen.cs | 33 + .../Wrapper/BlendChannelList.nativegen.cs | 52 + .../Wrapper/BlendDeformer.nativegen.cs | 38 + .../Wrapper/BlendDeformerList.nativegen.cs | 52 + .../Wrapper/BlendKeyframe.nativegen.cs | 22 + .../Wrapper/BlendShape.nativegen.cs | 51 + .../Wrapper/BlendShapeList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/Bone.nativegen.cs | 34 + .../Ghost.Ufbx/Wrapper/BoneList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/BonePose.nativegen.cs | 22 + .../Wrapper/CacheChannel.nativegen.cs | 39 + .../Wrapper/CacheDeformer.nativegen.cs | 38 + .../Wrapper/CacheDeformerList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/CacheFile.nativegen.cs | 46 + .../Wrapper/CacheFileList.nativegen.cs | 52 + .../Wrapper/CacheFrame.nativegen.cs | 51 + .../Ghost.Ufbx/Wrapper/Camera.nativegen.cs | 68 + .../Wrapper/CameraList.nativegen.cs | 52 + .../Wrapper/CameraSwitcher.nativegen.cs | 28 + .../Wrapper/CameraSwitcherList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/Character.nativegen.cs | 26 + .../Wrapper/CharacterList.nativegen.cs | 52 + .../Wrapper/CloseMemoryCb.nativegen.cs | 17 + .../Ghost.Ufbx/Wrapper/ColorSet.nativegen.cs | 22 + .../Wrapper/Connection.nativegen.cs | 27 + .../Wrapper/Constraint.nativegen.cs | 59 + .../Wrapper/ConstraintList.nativegen.cs | 52 + .../Wrapper/ConstraintTarget.nativegen.cs | 22 + .../Wrapper/CoordinateAxes.nativegen.cs | 21 + .../Wrapper/CurvePoint.nativegen.cs | 21 + .../Wrapper/DisplayLayer.nativegen.cs | 34 + .../Wrapper/DisplayLayerList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/DomNode.nativegen.cs | 72 ++ .../Wrapper/DomNodeList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/DomValue.nativegen.cs | 26 + .../Ghost.Ufbx/Wrapper/Edge.nativegen.cs | 19 + .../Ghost.Ufbx/Wrapper/Element.nativegen.cs | 263 ++++ .../Wrapper/ElementList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/Empty.nativegen.cs | 28 + .../Ghost.Ufbx/Wrapper/EmptyList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/Error.nativegen.cs | 24 + .../Wrapper/ErrorFrame.nativegen.cs | 23 + .../Wrapper/EvaluateOpts.nativegen.cs | 29 + .../Wrapper/Extrapolation.nativegen.cs | 19 + .../Ghost.Ufbx/Wrapper/Face.nativegen.cs | 19 + .../Ghost.Ufbx/Wrapper/FaceGroup.nativegen.cs | 20 + .../Wrapper/GeometryCache.nativegen.cs | 44 + .../GeometryCacheDataOpts.nativegen.cs | 25 + .../Wrapper/GeometryCacheOpts.nativegen.cs | 29 + .../Wrapper/InflateInput.nativegen.cs | 41 + .../Wrapper/InflateRetain.nativegen.cs | 17 + .../Ghost.Ufbx/Wrapper/Keyframe.nativegen.cs | 25 + .../Ghost.Ufbx/Wrapper/Light.nativegen.cs | 48 + .../Ghost.Ufbx/Wrapper/LightList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/LineCurve.nativegen.cs | 48 + .../Wrapper/LineCurveList.nativegen.cs | 52 + .../Wrapper/LineSegment.nativegen.cs | 19 + .../Ghost.Ufbx/Wrapper/LoadOpts.nativegen.cs | 167 +++ .../Ghost.Ufbx/Wrapper/LodGroup.nativegen.cs | 40 + .../Wrapper/LodGroupList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/LodLevel.nativegen.cs | 19 + .../Ghost.Ufbx/Wrapper/Marker.nativegen.cs | 30 + .../Wrapper/MarkerList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/Material.nativegen.cs | 55 + .../Wrapper/MaterialFbxMaps.nativegen.cs | 55 + .../Wrapper/MaterialFeatureInfo.nativegen.cs | 19 + .../Wrapper/MaterialFeatures.nativegen.cs | 61 + .../Wrapper/MaterialList.nativegen.cs | 52 + .../Wrapper/MaterialMap.nativegen.cs | 36 + .../Wrapper/MaterialPbrMaps.nativegen.cs | 127 ++ .../Wrapper/MaterialTexture.nativegen.cs | 24 + .../Ghost.Ufbx/Wrapper/Matrix.nativegen.cs | 39 + .../Ghost.Ufbx/Wrapper/Mesh.nativegen.cs | 168 +++ .../Ghost.Ufbx/Wrapper/MeshList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/MeshPart.nativegen.cs | 29 + .../Ghost.Ufbx/Wrapper/Metadata.nativegen.cs | 109 ++ .../Wrapper/MetadataObject.nativegen.cs | 26 + .../Wrapper/MetadataObjectList.nativegen.cs | 52 + .../Wrapper/NameElement.nativegen.cs | 23 + .../Wrapper/NativeWrapperHelpers.nativegen.cs | 45 + .../Ghost.Ufbx/Wrapper/Node.nativegen.cs | 125 ++ .../Ghost.Ufbx/Wrapper/NodeList.nativegen.cs | 52 + .../Wrapper/NurbsBasis.nativegen.cs | 38 + .../Wrapper/NurbsCurve.nativegen.cs | 42 + .../Wrapper/NurbsCurveList.nativegen.cs | 52 + .../Wrapper/NurbsSurface.nativegen.cs | 57 + .../Wrapper/NurbsSurfaceList.nativegen.cs | 52 + .../Wrapper/NurbsTrimBoundary.nativegen.cs | 28 + .../NurbsTrimBoundaryList.nativegen.cs | 52 + .../Wrapper/NurbsTrimSurface.nativegen.cs | 28 + .../Wrapper/NurbsTrimSurfaceList.nativegen.cs | 52 + .../Wrapper/OpenFileCb.nativegen.cs | 17 + .../Wrapper/OpenFileInfo.nativegen.cs | 21 + .../Wrapper/OpenFileOpts.nativegen.cs | 19 + .../Wrapper/OpenMemoryOpts.nativegen.cs | 21 + .../Ghost.Ufbx/Wrapper/Panic.nativegen.cs | 84 ++ .../Ghost.Ufbx/Wrapper/Pose.nativegen.cs | 35 + .../Ghost.Ufbx/Wrapper/PoseList.nativegen.cs | 52 + .../Wrapper/ProceduralGeometry.nativegen.cs | 28 + .../ProceduralGeometryList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/Progress.nativegen.cs | 19 + .../Wrapper/ProgressCb.nativegen.cs | 17 + .../Ghost.Ufbx/Wrapper/Prop.nativegen.cs | 37 + .../Wrapper/PropOverride.nativegen.cs | 27 + .../Wrapper/PropOverrideDesc.nativegen.cs | 27 + .../Ghost.Ufbx/Wrapper/Props.nativegen.cs | 101 ++ .../Ghost.Ufbx/Wrapper/Quat.nativegen.cs | 23 + .../Ghost.Ufbx/Wrapper/Scene.nativegen.cs | 256 ++++ .../Wrapper/SceneSettings.nativegen.cs | 38 + .../Wrapper/SelectionNode.nativegen.cs | 40 + .../Wrapper/SelectionNodeList.nativegen.cs | 52 + .../Wrapper/SelectionSet.nativegen.cs | 28 + .../Wrapper/SelectionSetList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/Shader.nativegen.cs | 50 + .../Wrapper/ShaderBinding.nativegen.cs | 28 + .../Wrapper/ShaderBindingList.nativegen.cs | 52 + .../Wrapper/ShaderList.nativegen.cs | 52 + .../Wrapper/ShaderPropBinding.nativegen.cs | 21 + .../Wrapper/ShaderTexture.nativegen.cs | 47 + .../Wrapper/ShaderTextureInput.nativegen.cs | 49 + .../Wrapper/SkinCluster.nativegen.cs | 45 + .../Wrapper/SkinClusterList.nativegen.cs | 52 + .../Wrapper/SkinDeformer.nativegen.cs | 42 + .../Wrapper/SkinDeformerList.nativegen.cs | 52 + .../Wrapper/SkinVertex.nativegen.cs | 21 + .../Wrapper/SkinWeight.nativegen.cs | 19 + .../Wrapper/StereoCamera.nativegen.cs | 34 + .../Wrapper/StereoCameraList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/Stream.nativegen.cs | 47 + .../Wrapper/SubdivideOpts.nativegen.cs | 39 + .../Wrapper/SubdivisionResult.nativegen.cs | 31 + .../Wrapper/SubdivisionWeight.nativegen.cs | 19 + .../SubdivisionWeightRange.nativegen.cs | 19 + .../Wrapper/SurfacePoint.nativegen.cs | 23 + .../Ghost.Ufbx/Wrapper/Tangent.nativegen.cs | 19 + .../Wrapper/TessellateCurveOpts.nativegen.cs | 21 + .../TessellateSurfaceOpts.nativegen.cs | 25 + .../Ghost.Ufbx/Wrapper/Texture.nativegen.cs | 74 ++ .../Wrapper/TextureFile.nativegen.cs | 34 + .../Wrapper/TextureLayer.nativegen.cs | 22 + .../Wrapper/TextureList.nativegen.cs | 52 + .../Wrapper/ThreadOpts.nativegen.cs | 21 + .../Wrapper/ThreadPool.nativegen.cs | 17 + .../Wrapper/ThreadPoolInfo.nativegen.cs | 17 + .../Ghost.Ufbx/Wrapper/Thumbnail.nativegen.cs | 25 + .../Ghost.Ufbx/Wrapper/TopoEdge.nativegen.cs | 39 + .../Ghost.Ufbx/Wrapper/Transform.nativegen.cs | 26 + .../Wrapper/TransformOverride.nativegen.cs | 19 + .../Ghost.Ufbx/Wrapper/Ufbx.nativegen.cs | 140 +++ .../Ghost.Ufbx/Wrapper/UfbxBlob.nativegen.cs | 19 + .../Wrapper/UfbxString.nativegen.cs | 19 + .../Ghost.Ufbx/Wrapper/Unknown.nativegen.cs | 35 + .../Wrapper/UnknownList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/UvSet.nativegen.cs | 26 + .../Wrapper/VertexAttrib.nativegen.cs | 27 + .../Wrapper/VertexReal.nativegen.cs | 27 + .../Wrapper/VertexStream.nativegen.cs | 26 + .../Wrapper/VertexVec2.nativegen.cs | 27 + .../Wrapper/VertexVec3.nativegen.cs | 32 + .../Wrapper/VertexVec4.nativegen.cs | 27 + .../Ghost.Ufbx/Wrapper/Video.nativegen.cs | 43 + .../Ghost.Ufbx/Wrapper/VideoList.nativegen.cs | 52 + .../Ghost.Ufbx/Wrapper/VoidList.nativegen.cs | 15 + .../Ghost.Ufbx/Wrapper/Warning.nativegen.cs | 24 + src/ThridParty/Ghost.Ufbx/cstring.cs | 104 ++ src/ThridParty/Ghost.Ufbx/ufbx_string.cs | 21 + .../Config/WrapperConfig.cs | 108 ++ .../Ghost.NativeWrapperGen/Emit/CodeWriter.cs | 44 + .../Emit/GeneratedFile.cs | 7 + .../Emit/WrapperGeneratorEmitter.cs | 1090 +++++++++++++++++ .../Ghost.NativeWrapperGen.csproj | 14 + .../Model/NativeLibrary.cs | 55 + .../Parsing/BindingParser.cs | 211 ++++ src/Tools/Ghost.NativeWrapperGen/Program.cs | 118 ++ src/Tools/Ghost.NativeWrapperGen/README.md | 552 +++++++++ .../Transform/NamingConventions.cs | 49 + .../Transform/PublicTypeResolver.cs | 56 + .../Ghost.NativeWrapperGen/configs/ufbx.json | 221 ++++ 232 files changed, 10989 insertions(+), 55 deletions(-) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttBatchList.cs (98%) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttCompressionOptions.cs (99%) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttContext.cs (99%) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttCubeSurface.cs (99%) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttGlobal.cs (99%) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttInterop.cs (98%) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttOutputOptions.cs (99%) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttSurface.cs (99%) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttSurfaceSet.cs (99%) rename src/ThridParty/Ghost.Nvtt/{Warper => Wrapper}/NvttTimingContext.cs (99%) create mode 100644 src/ThridParty/Ghost.Ufbx/LoadOpts.cs create mode 100644 src/ThridParty/Ghost.Ufbx/UfbxErrorExtensions.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Allocator.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AllocatorOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Anim.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimCurve.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimCurveList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimLayer.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimLayerList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimProp.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimStack.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimStackList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimValue.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AnimValueList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Application.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AudioClip.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AudioClipList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AudioLayer.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/AudioLayerList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BakeOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BakedAnim.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BakedAnimMetadata.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BakedElement.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BakedNode.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BakedProp.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BakedQuat.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BakedVec3.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BlendChannel.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BlendChannelList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BlendDeformer.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BlendDeformerList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BlendKeyframe.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BlendShape.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BlendShapeList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Bone.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BoneList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/BonePose.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CacheChannel.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CacheDeformer.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CacheDeformerList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CacheFile.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CacheFileList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CacheFrame.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Camera.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CameraList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CameraSwitcher.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CameraSwitcherList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Character.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CharacterList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CloseMemoryCb.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ColorSet.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Connection.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Constraint.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ConstraintList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ConstraintTarget.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CoordinateAxes.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/CurvePoint.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/DisplayLayer.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/DisplayLayerList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/DomNode.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/DomNodeList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/DomValue.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Edge.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Element.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ElementList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Empty.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/EmptyList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Error.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ErrorFrame.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/EvaluateOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Extrapolation.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Face.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/FaceGroup.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCache.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCacheDataOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCacheOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/InflateInput.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/InflateRetain.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Keyframe.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Light.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/LightList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/LineCurve.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/LineCurveList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/LineSegment.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/LoadOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/LodGroup.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/LodGroupList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/LodLevel.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Marker.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MarkerList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Material.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFbxMaps.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFeatureInfo.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFeatures.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MaterialList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MaterialMap.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MaterialPbrMaps.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MaterialTexture.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Matrix.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Mesh.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MeshList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MeshPart.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Metadata.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MetadataObject.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/MetadataObjectList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NameElement.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NativeWrapperHelpers.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Node.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NodeList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NurbsBasis.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NurbsCurve.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NurbsCurveList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NurbsSurface.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NurbsSurfaceList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimBoundary.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimBoundaryList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimSurface.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimSurfaceList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileCb.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileInfo.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/OpenMemoryOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Panic.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Pose.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/PoseList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ProceduralGeometry.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ProceduralGeometryList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Progress.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ProgressCb.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Prop.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/PropOverride.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/PropOverrideDesc.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Props.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Quat.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Scene.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SceneSettings.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SelectionNode.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SelectionNodeList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SelectionSet.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SelectionSetList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Shader.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ShaderBinding.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ShaderBindingList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ShaderList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ShaderPropBinding.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ShaderTexture.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ShaderTextureInput.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SkinCluster.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SkinClusterList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SkinDeformer.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SkinDeformerList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SkinVertex.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SkinWeight.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/StereoCamera.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/StereoCameraList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Stream.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SubdivideOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionResult.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionWeight.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionWeightRange.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/SurfacePoint.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Tangent.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/TessellateCurveOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/TessellateSurfaceOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Texture.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/TextureFile.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/TextureLayer.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/TextureList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ThreadOpts.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ThreadPool.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/ThreadPoolInfo.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Thumbnail.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/TopoEdge.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Transform.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/TransformOverride.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Ufbx.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/UfbxBlob.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/UfbxString.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Unknown.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/UnknownList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/UvSet.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/VertexAttrib.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/VertexReal.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/VertexStream.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec2.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec3.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec4.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Video.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/VideoList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/VoidList.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/Wrapper/Warning.nativegen.cs create mode 100644 src/ThridParty/Ghost.Ufbx/cstring.cs create mode 100644 src/ThridParty/Ghost.Ufbx/ufbx_string.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/Config/WrapperConfig.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/Emit/CodeWriter.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/Emit/GeneratedFile.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/Emit/WrapperGeneratorEmitter.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/Ghost.NativeWrapperGen.csproj create mode 100644 src/Tools/Ghost.NativeWrapperGen/Model/NativeLibrary.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/Parsing/BindingParser.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/Program.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/README.md create mode 100644 src/Tools/Ghost.NativeWrapperGen/Transform/NamingConventions.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/Transform/PublicTypeResolver.cs create mode 100644 src/Tools/Ghost.NativeWrapperGen/configs/ufbx.json diff --git a/src/Editor/Ghost.Editor.Core/AssetHandler/TextureProcessor.cs b/src/Editor/Ghost.Editor.Core/AssetHandler/TextureProcessor.cs index 02ea371..cdb9f8f 100644 --- a/src/Editor/Ghost.Editor.Core/AssetHandler/TextureProcessor.cs +++ b/src/Editor/Ghost.Editor.Core/AssetHandler/TextureProcessor.cs @@ -1,5 +1,5 @@ using Ghost.Nvtt; -using Ghost.Nvtt.Warper; +using Ghost.Nvtt.Wrapper; using Misaki.HighPerformance.Image; using System.IO.Hashing; using System.Runtime.CompilerServices; diff --git a/src/GhostEngine.slnx b/src/GhostEngine.slnx index 35865c6..0e73003 100644 --- a/src/GhostEngine.slnx +++ b/src/GhostEngine.slnx @@ -47,4 +47,7 @@ + + + diff --git a/src/Test/Ghost.MicroTest/NvttBindingTest.cs b/src/Test/Ghost.MicroTest/NvttBindingTest.cs index 23ef57a..f7c28d5 100644 --- a/src/Test/Ghost.MicroTest/NvttBindingTest.cs +++ b/src/Test/Ghost.MicroTest/NvttBindingTest.cs @@ -1,5 +1,5 @@ using Ghost.Nvtt; -using Ghost.Nvtt.Warper; +using Ghost.Nvtt.Wrapper; using Ghost.Test.Core; namespace Ghost.MicroTest; diff --git a/src/Test/Ghost.MicroTest/UfbxBindingTest.cs b/src/Test/Ghost.MicroTest/UfbxBindingTest.cs index d6bea38..3d63e58 100644 --- a/src/Test/Ghost.MicroTest/UfbxBindingTest.cs +++ b/src/Test/Ghost.MicroTest/UfbxBindingTest.cs @@ -1,12 +1,9 @@ using Ghost.Test.Core; using Ghost.Ufbx; -using System.Diagnostics; -using System.Text; -using static Ghost.Ufbx.Api; namespace Ghost.MicroTest; -internal unsafe class UfbxBindingTest : ITest +internal class UfbxBindingTest : ITest { private static ReadOnlySpan TestFilePath => "F:/c/Third Parties/ufbx/data/blender_340_z_up_7400_binary.fbx"u8; @@ -16,37 +13,60 @@ internal unsafe class UfbxBindingTest : ITest public void Run() { - ufbx_load_opts opts = default; - ufbx_error error; - ufbx_scene* pScene; + // Smoke-test LoadOpts heap-pointer shape (construct, set, read back, dispose) + using var opts = new LoadOpts(); + opts.IgnoreAnimation = true; + opts.IgnoreEmbedded = true; - var path = TestFilePath; - fixed (byte* p = path) - { - pScene = ufbx_load_file((sbyte*)p, &opts, &error); - } + // Load scene using the safe high-level wrapper (no unsafe, no fixed blocks) + using var scene = Scene.LoadFile(TestFilePath, opts); - if (pScene == null) + // Enumerate nodes using the wrapper's NodeList (ref struct, no allocation) + for (var i = 0; i < scene.Nodes.Count; i++) { - Debug.Fail($"Failed to load scene: {Encoding.UTF8.GetString((byte*)error.description.data, (int)error.description.length)}"); - } - - for (nuint i = 0; i < pScene->nodes.count; i++) - { - var node = pScene->nodes.data[i]; - if (node->is_root) + var node = scene.Nodes[i]; + if (node.IsRoot) { continue; } - Console.WriteLine($"Object: {Encoding.UTF8.GetString((byte*)node->name.data, (int)node->name.length)}"); - if (node->mesh != null) + // node.Name is a string property — no manual ToString() needed + Console.WriteLine($"Object: {node.Name}"); + + if (node.HasMesh) { - Console.WriteLine($"-> mesh with {node->mesh->faces.count} faces"); + Console.WriteLine($"-> mesh with {node.Mesh.NumFaces} faces"); } } - ufbx_free_scene(pScene); + // Find a node by name using the new instance method (no unsafe, no fixed) + var rootNode = scene.FindNode("RootNode"u8); + if (!rootNode.IsNull) + { + Console.WriteLine($"Found root node: {rootNode.Name}"); + } + + // Find a material by name + var material = scene.FindMaterial("Material"u8); + if (!material.IsNull) + { + Console.WriteLine($"Found material: {material.Name}"); + // Find a prop on the material's props using the instance method + var prop = material.Props.FindProp("DiffuseColor"u8); + if (!prop.IsNull) + { + Console.WriteLine($" DiffuseColor prop type: {prop.Type}"); + } + } + + // Find an anim stack + var animStack = scene.FindAnimStack("Take 001"u8); + if (!animStack.IsNull) + { + Console.WriteLine($"Found anim stack: {animStack.Name}"); + } + + Console.WriteLine("Done."); } public void Cleanup() diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttBatchList.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttBatchList.cs similarity index 98% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttBatchList.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttBatchList.cs index 380dc5b..fc11351 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttBatchList.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttBatchList.cs @@ -1,4 +1,4 @@ -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Wrapper around an nvtt batch list — a list of (surface, face, mipmap, diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttCompressionOptions.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttCompressionOptions.cs similarity index 99% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttCompressionOptions.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttCompressionOptions.cs index 0681917..263a189 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttCompressionOptions.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttCompressionOptions.cs @@ -1,4 +1,4 @@ -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Controls how a surface is compressed - format, quality, pixel layout and diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttContext.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttContext.cs similarity index 99% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttContext.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttContext.cs index dcadb15..3e16672 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttContext.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttContext.cs @@ -1,4 +1,4 @@ -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Wrapper around the nvtt compression context — the central object that drives diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttCubeSurface.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttCubeSurface.cs similarity index 99% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttCubeSurface.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttCubeSurface.cs index c2bfa33..4f4f795 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttCubeSurface.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttCubeSurface.cs @@ -1,4 +1,4 @@ -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Wrapper around an nvtt cube-map surface (six faces, optional mip chain). diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttGlobal.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttGlobal.cs similarity index 99% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttGlobal.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttGlobal.cs index 7180895..0af9649 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttGlobal.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttGlobal.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Static helpers wrapping global nvtt functions (version, CUDA detection, diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttInterop.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttInterop.cs similarity index 98% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttInterop.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttInterop.cs index 425d2d3..614af0b 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttInterop.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttInterop.cs @@ -1,7 +1,7 @@ using System.Runtime.CompilerServices; using System.Text; -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Internal helpers for converting between managed and unmanaged types. diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttOutputOptions.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttOutputOptions.cs similarity index 99% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttOutputOptions.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttOutputOptions.cs index 43d2b81..69547d6 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttOutputOptions.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttOutputOptions.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Configures where compressed data is written and how it is formatted. diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttSurface.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttSurface.cs similarity index 99% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttSurface.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttSurface.cs index f183958..bc248c6 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttSurface.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttSurface.cs @@ -1,4 +1,4 @@ -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Wrapper around a single 2-D / 3-D / cube-face image surface used as input diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttSurfaceSet.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttSurfaceSet.cs similarity index 99% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttSurfaceSet.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttSurfaceSet.cs index 439440f..3dc3510 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttSurfaceSet.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttSurfaceSet.cs @@ -1,4 +1,4 @@ -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Wrapper around an nvtt surface set — a collection of faces and mip levels diff --git a/src/ThridParty/Ghost.Nvtt/Warper/NvttTimingContext.cs b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttTimingContext.cs similarity index 99% rename from src/ThridParty/Ghost.Nvtt/Warper/NvttTimingContext.cs rename to src/ThridParty/Ghost.Nvtt/Wrapper/NvttTimingContext.cs index 5f9a17d..cd2d213 100644 --- a/src/ThridParty/Ghost.Nvtt/Warper/NvttTimingContext.cs +++ b/src/ThridParty/Ghost.Nvtt/Wrapper/NvttTimingContext.cs @@ -1,4 +1,4 @@ -namespace Ghost.Nvtt.Warper; +namespace Ghost.Nvtt.Wrapper; /// /// Wraps an nvtt timing context that records per-operation wall-clock times. diff --git a/src/ThridParty/Ghost.Ufbx/Generated/Api.cs b/src/ThridParty/Ghost.Ufbx/Generated/Api.cs index 1b416af..f2a2277 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/Api.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/Api.cs @@ -1,3 +1,4 @@ +using System; using System.Runtime.InteropServices; using static Ghost.Ufbx.ufbx_aperture_format; using static Ghost.Ufbx.ufbx_aperture_mode; @@ -418,7 +419,8 @@ namespace Ghost.Ufbx public static extern Misaki.HighPerformance.Mathematics.float3 ufbx_evaluate_baked_vec3(ufbx_baked_vec3_list keyframes, double time); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ufbx_quat ufbx_evaluate_baked_quat(ufbx_baked_quat_list keyframes, double time); + [return: NativeTypeName("ufbx_quat")] + public static extern Misaki.HighPerformance.Mathematics.quaternion ufbx_evaluate_baked_quat(ufbx_baked_quat_list keyframes, double time); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] public static extern ufbx_bone_pose* ufbx_get_bone_pose([NativeTypeName("const ufbx_pose *")] ufbx_pose* pose, [NativeTypeName("const ufbx_node *")] ufbx_node* node); @@ -457,30 +459,35 @@ namespace Ghost.Ufbx [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [return: NativeTypeName("ufbx_real")] - public static extern float ufbx_quat_dot(ufbx_quat a, ufbx_quat b); + public static extern float ufbx_quat_dot([NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion a, [NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion b); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ufbx_quat ufbx_quat_mul(ufbx_quat a, ufbx_quat b); + [return: NativeTypeName("ufbx_quat")] + public static extern Misaki.HighPerformance.Mathematics.quaternion ufbx_quat_mul([NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion a, [NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion b); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ufbx_quat ufbx_quat_normalize(ufbx_quat q); + [return: NativeTypeName("ufbx_quat")] + public static extern Misaki.HighPerformance.Mathematics.quaternion ufbx_quat_normalize([NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion q); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ufbx_quat ufbx_quat_fix_antipodal(ufbx_quat q, ufbx_quat reference); + [return: NativeTypeName("ufbx_quat")] + public static extern Misaki.HighPerformance.Mathematics.quaternion ufbx_quat_fix_antipodal([NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion q, [NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion reference); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ufbx_quat ufbx_quat_slerp(ufbx_quat a, ufbx_quat b, [NativeTypeName("ufbx_real")] float t); + [return: NativeTypeName("ufbx_quat")] + public static extern Misaki.HighPerformance.Mathematics.quaternion ufbx_quat_slerp([NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion a, [NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion b, [NativeTypeName("ufbx_real")] float t); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [return: NativeTypeName("ufbx_vec3")] - public static extern Misaki.HighPerformance.Mathematics.float3 ufbx_quat_rotate_vec3(ufbx_quat q, [NativeTypeName("ufbx_vec3")] Misaki.HighPerformance.Mathematics.float3 v); + public static extern Misaki.HighPerformance.Mathematics.float3 ufbx_quat_rotate_vec3([NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion q, [NativeTypeName("ufbx_vec3")] Misaki.HighPerformance.Mathematics.float3 v); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [return: NativeTypeName("ufbx_vec3")] - public static extern Misaki.HighPerformance.Mathematics.float3 ufbx_quat_to_euler(ufbx_quat q, ufbx_rotation_order order); + public static extern Misaki.HighPerformance.Mathematics.float3 ufbx_quat_to_euler([NativeTypeName("ufbx_quat")] Misaki.HighPerformance.Mathematics.quaternion q, ufbx_rotation_order order); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ufbx_quat ufbx_euler_to_quat([NativeTypeName("ufbx_vec3")] Misaki.HighPerformance.Mathematics.float3 v, ufbx_rotation_order order); + [return: NativeTypeName("ufbx_quat")] + public static extern Misaki.HighPerformance.Mathematics.quaternion ufbx_euler_to_quat([NativeTypeName("ufbx_vec3")] Misaki.HighPerformance.Mathematics.float3 v, ufbx_rotation_order order); [DllImport("ufbx", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [return: NativeTypeName("ufbx_matrix")] diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_baked_quat.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_baked_quat.cs index 6d66728..6968e95 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_baked_quat.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_baked_quat.cs @@ -4,7 +4,8 @@ namespace Ghost.Ufbx { public double time; - public ufbx_quat value; + [NativeTypeName("ufbx_quat")] + public Misaki.HighPerformance.Mathematics.quaternion value; public ufbx_baked_key_flags flags; } diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_edge.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_edge.cs index 24233c2..959f0b0 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_edge.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_edge.cs @@ -1,3 +1,4 @@ +using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_fbx_maps.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_fbx_maps.cs index 301abac..8111b37 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_fbx_maps.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_fbx_maps.cs @@ -1,3 +1,4 @@ +using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_features.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_features.cs index a57900f..9fac1cc 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_features.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_features.cs @@ -1,3 +1,4 @@ +using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_pbr_maps.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_pbr_maps.cs index 379a499..b7b7617 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_pbr_maps.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_material_pbr_maps.cs @@ -1,3 +1,4 @@ +using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_metadata.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_metadata.cs index bf97c48..b42bdcd 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_metadata.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_metadata.cs @@ -111,7 +111,8 @@ namespace Ghost.Ufbx public ufbx_mirror_axis handedness_conversion_axis; - public ufbx_quat root_rotation; + [NativeTypeName("ufbx_quat")] + public Misaki.HighPerformance.Mathematics.quaternion root_rotation; [NativeTypeName("ufbx_real")] public float root_scale; diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_node.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_node.cs index 037879e..68c4c67 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_node.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_node.cs @@ -66,12 +66,14 @@ namespace Ghost.Ufbx [NativeTypeName("ufbx_vec3")] public Misaki.HighPerformance.Mathematics.float3 adjust_pre_translation; - public ufbx_quat adjust_pre_rotation; + [NativeTypeName("ufbx_quat")] + public Misaki.HighPerformance.Mathematics.quaternion adjust_pre_rotation; [NativeTypeName("ufbx_real")] public float adjust_pre_scale; - public ufbx_quat adjust_post_rotation; + [NativeTypeName("ufbx_quat")] + public Misaki.HighPerformance.Mathematics.quaternion adjust_post_rotation; [NativeTypeName("ufbx_real")] public float adjust_post_scale; diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_prop.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_prop.cs index b896d07..ea457ae 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_prop.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_prop.cs @@ -1,3 +1,4 @@ +using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_scene.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_scene.cs index 2c8608a..fa09898 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_scene.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_scene.cs @@ -1,3 +1,4 @@ +using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_transform.cs b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_transform.cs index 2e87fcb..4b89419 100644 --- a/src/ThridParty/Ghost.Ufbx/Generated/ufbx_transform.cs +++ b/src/ThridParty/Ghost.Ufbx/Generated/ufbx_transform.cs @@ -5,7 +5,8 @@ namespace Ghost.Ufbx [NativeTypeName("ufbx_vec3")] public Misaki.HighPerformance.Mathematics.float3 translation; - public ufbx_quat rotation; + [NativeTypeName("ufbx_quat")] + public Misaki.HighPerformance.Mathematics.quaternion rotation; [NativeTypeName("ufbx_vec3")] public Misaki.HighPerformance.Mathematics.float3 scale; diff --git a/src/ThridParty/Ghost.Ufbx/Ghost.Ufbx.csproj b/src/ThridParty/Ghost.Ufbx/Ghost.Ufbx.csproj index d6934a9..a077ceb 100644 --- a/src/ThridParty/Ghost.Ufbx/Ghost.Ufbx.csproj +++ b/src/ThridParty/Ghost.Ufbx/Ghost.Ufbx.csproj @@ -19,11 +19,6 @@ - - - - - PreserveNewest diff --git a/src/ThridParty/Ghost.Ufbx/LoadOpts.cs b/src/ThridParty/Ghost.Ufbx/LoadOpts.cs new file mode 100644 index 0000000..3086c39 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/LoadOpts.cs @@ -0,0 +1,47 @@ +using System.Runtime.InteropServices; + +namespace Ghost.Ufbx; + +public unsafe partial class LoadOpts +{ + public partial cstring ObjMtlPath + { + get => _objMtlPath; + set + { + _objMtlPath.Dispose(); + _objMtlPath = new cstring(value); + _ptr->obj_mtl_path = new ufbx_string + { + data = (sbyte*)_objMtlPath.ptr, + length = (nuint)_objMtlPath.length, + }; + } + } + + public partial cstring Filename + { + get => _filename; + set + { + _filename.Dispose(); + _filename = new cstring(value); + _ptr->filename = new ufbx_string + { + data = (sbyte*)_filename.ptr, + length = (nuint)_filename.length, + }; + } + } + + public partial void Dispose() + { + _objMtlPath.Dispose(); + _filename.Dispose(); + if (_csAlloc && _ptr != null) + { + NativeMemory.Free(_ptr); + _ptr = null; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/UfbxErrorExtensions.cs b/src/ThridParty/Ghost.Ufbx/UfbxErrorExtensions.cs new file mode 100644 index 0000000..4728c8c --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/UfbxErrorExtensions.cs @@ -0,0 +1,25 @@ +using System.Text; + +namespace Ghost.Ufbx; + +public static unsafe class UfbxErrorExtensions +{ + /// + /// Formats a ufbx_error into a human-readable string using ufbx_format_error. + /// Allocates a 2KB stack buffer; the result is truncated if the message exceeds that. + /// + public static string FormatError(ref this ufbx_error error) + { + const int BufferSize = 2048; + Span buffer = stackalloc byte[BufferSize]; + fixed (ufbx_error* pError = &error) + fixed (byte* pBuffer = buffer) + { + var len = Api.ufbx_format_error((sbyte*)pBuffer, (nuint)BufferSize, pError); + if (len == 0) + return string.Empty; + // ufbx_format_error returns the number of characters written (excluding null terminator) + return Encoding.UTF8.GetString(buffer[..(int)len]); + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Allocator.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Allocator.nativegen.cs new file mode 100644 index 0000000..7c0f448 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Allocator.nativegen.cs @@ -0,0 +1,17 @@ +namespace Ghost.Ufbx; + +public unsafe struct Allocator +{ + private ufbx_allocator* _ptr; + + internal Allocator(ufbx_allocator* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public void* User => _ptr->user; + + internal ufbx_allocator* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AllocatorOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AllocatorOpts.nativegen.cs new file mode 100644 index 0000000..1ad8950 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AllocatorOpts.nativegen.cs @@ -0,0 +1,25 @@ +namespace Ghost.Ufbx; + +public unsafe struct AllocatorOpts +{ + private ufbx_allocator_opts* _ptr; + + internal AllocatorOpts(ufbx_allocator_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Allocator Allocator => new((ufbx_allocator*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->allocator)); + + public nuint MemoryLimit => _ptr->memory_limit; + + public nuint AllocationLimit => _ptr->allocation_limit; + + public nuint HugeThreshold => _ptr->huge_threshold; + + public nuint MaxChunkSize => _ptr->max_chunk_size; + + internal ufbx_allocator_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Anim.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Anim.nativegen.cs new file mode 100644 index 0000000..4db119f --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Anim.nativegen.cs @@ -0,0 +1,91 @@ +namespace Ghost.Ufbx; + +public unsafe ref struct Anim +{ + private ufbx_anim* _ptr; + + internal Anim(ufbx_anim* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_prop EvaluatePropLen(Element element, sbyte* name, nuint nameLen, double time) + { + return Api.ufbx_evaluate_prop_len(_ptr, element.GetUnsafePtr(), name, nameLen, time); + } + + public ufbx_prop EvaluateProp(Element element, sbyte* name, double time) + { + return Api.ufbx_evaluate_prop(_ptr, element.GetUnsafePtr(), name, time); + } + + public ufbx_prop EvaluatePropFlagsLen(Element element, sbyte* name, nuint nameLen, double time, uint flags) + { + return Api.ufbx_evaluate_prop_flags_len(_ptr, element.GetUnsafePtr(), name, nameLen, time, flags); + } + + public ufbx_prop EvaluatePropFlags(Element element, sbyte* name, double time, uint flags) + { + return Api.ufbx_evaluate_prop_flags(_ptr, element.GetUnsafePtr(), name, time, flags); + } + + public ufbx_props EvaluateProps(Element element, double time, Prop buffer, nuint bufferSize) + { + return Api.ufbx_evaluate_props(_ptr, element.GetUnsafePtr(), time, buffer.GetUnsafePtr(), bufferSize); + } + + public ufbx_props EvaluatePropsFlags(Element element, double time, Prop buffer, nuint bufferSize, uint flags) + { + return Api.ufbx_evaluate_props_flags(_ptr, element.GetUnsafePtr(), time, buffer.GetUnsafePtr(), bufferSize, flags); + } + + public ufbx_transform EvaluateTransform(Node node, double time) + { + return Api.ufbx_evaluate_transform(_ptr, node.GetUnsafePtr(), time); + } + + public ufbx_transform EvaluateTransformFlags(Node node, double time, uint flags) + { + return Api.ufbx_evaluate_transform_flags(_ptr, node.GetUnsafePtr(), time, flags); + } + + public float EvaluateBlendWeight(BlendChannel channel, double time) + { + return Api.ufbx_evaluate_blend_weight(_ptr, channel.GetUnsafePtr(), time); + } + + public float EvaluateBlendWeightFlags(BlendChannel channel, double time, uint flags) + { + return Api.ufbx_evaluate_blend_weight_flags(_ptr, channel.GetUnsafePtr(), time, flags); + } + + public void FreeAnim() + { + Api.ufbx_free_anim(_ptr); + } + + public void RetainAnim() + { + Api.ufbx_retain_anim(_ptr); + } + + public double TimeBegin => _ptr->time_begin; + + public double TimeEnd => _ptr->time_end; + + public AnimLayerList Layers => new(_ptr->layers.data, _ptr->layers.count); + + public ReadOnlySpan OverrideLayerWeights => _ptr->override_layer_weights.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->override_layer_weights.data, checked((int)_ptr->override_layer_weights.count)); + + public ReadOnlySpan PropOverrides => _ptr->prop_overrides.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->prop_overrides.data, checked((int)_ptr->prop_overrides.count)); + + public ReadOnlySpan TransformOverrides => _ptr->transform_overrides.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->transform_overrides.data, checked((int)_ptr->transform_overrides.count)); + + public bool IgnoreConnections => _ptr->ignore_connections; + + public bool Custom => _ptr->custom; + + internal ufbx_anim* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimCurve.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimCurve.nativegen.cs new file mode 100644 index 0000000..505d51e --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimCurve.nativegen.cs @@ -0,0 +1,50 @@ +namespace Ghost.Ufbx; + +public unsafe struct AnimCurve +{ + private ufbx_anim_curve* _ptr; + + internal AnimCurve(ufbx_anim_curve* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public float EvaluateCurve(double time, float defaultValue) + { + return Api.ufbx_evaluate_curve(_ptr, time, defaultValue); + } + + public float EvaluateCurveFlags(double time, float defaultValue, uint flags) + { + return Api.ufbx_evaluate_curve_flags(_ptr, time, defaultValue, flags); + } + + public ReadOnlySpan Keyframes => _ptr->keyframes.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->keyframes.data, checked((int)_ptr->keyframes.count)); + + public Extrapolation PreExtrapolation => new((ufbx_extrapolation*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->pre_extrapolation)); + + public Extrapolation PostExtrapolation => new((ufbx_extrapolation*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->post_extrapolation)); + + public float MinValue => _ptr->min_value; + + public float MaxValue => _ptr->max_value; + + public double MinTime => _ptr->min_time; + + public double MaxTime => _ptr->max_time; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_anim_curve* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimCurveList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimCurveList.nativegen.cs new file mode 100644 index 0000000..9136c65 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimCurveList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct AnimCurveList +{ + private readonly ufbx_anim_curve** _data; + public int Count { get; } + + internal AnimCurveList(ufbx_anim_curve** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public AnimCurve this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_anim_curve** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_anim_curve** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public AnimCurve Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimLayer.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimLayer.nativegen.cs new file mode 100644 index 0000000..b6cbcac --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimLayer.nativegen.cs @@ -0,0 +1,60 @@ +namespace Ghost.Ufbx; + +public unsafe struct AnimLayer +{ + private ufbx_anim_layer* _ptr; + + internal AnimLayer(ufbx_anim_layer* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AnimProp FindAnimPropLen(Element element, sbyte* prop, nuint propLen) + { + return new(Api.ufbx_find_anim_prop_len(_ptr, element.GetUnsafePtr(), prop, propLen)); + } + + public AnimProp FindAnimProp(Element element, sbyte* prop) + { + return new(Api.ufbx_find_anim_prop(_ptr, element.GetUnsafePtr(), prop)); + } + + public ufbx_anim_prop_list FindAnimProps(Element element) + { + return Api.ufbx_find_anim_props(_ptr, element.GetUnsafePtr()); + } + + public float Weight => _ptr->weight; + + public bool WeightIsAnimated => _ptr->weight_is_animated; + + public bool Blended => _ptr->blended; + + public bool Additive => _ptr->additive; + + public bool ComposeRotation => _ptr->compose_rotation; + + public bool ComposeScale => _ptr->compose_scale; + + public AnimValueList AnimValues => new(_ptr->anim_values.data, _ptr->anim_values.count); + + public ReadOnlySpan AnimProps => _ptr->anim_props.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->anim_props.data, checked((int)_ptr->anim_props.count)); + + public bool HasAnim => _ptr->anim != null; + public Anim Anim => _ptr->anim != null ? new(_ptr->anim) : throw new InvalidOperationException("Anim is null."); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_anim_layer* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimLayerList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimLayerList.nativegen.cs new file mode 100644 index 0000000..4ceecd4 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimLayerList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct AnimLayerList +{ + private readonly ufbx_anim_layer** _data; + public int Count { get; } + + internal AnimLayerList(ufbx_anim_layer** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public AnimLayer this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_anim_layer** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_anim_layer** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public AnimLayer Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimOpts.nativegen.cs new file mode 100644 index 0000000..30066ae --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimOpts.nativegen.cs @@ -0,0 +1,27 @@ +namespace Ghost.Ufbx; + +public unsafe struct AnimOpts +{ + private ufbx_anim_opts* _ptr; + + internal AnimOpts(ufbx_anim_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan LayerIds => _ptr->layer_ids.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->layer_ids.data, checked((int)_ptr->layer_ids.count)); + + public ReadOnlySpan OverrideLayerWeights => _ptr->override_layer_weights.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->override_layer_weights.data, checked((int)_ptr->override_layer_weights.count)); + + public ReadOnlySpan PropOverrides => _ptr->prop_overrides.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->prop_overrides.data, checked((int)_ptr->prop_overrides.count)); + + public ReadOnlySpan TransformOverrides => _ptr->transform_overrides.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->transform_overrides.data, checked((int)_ptr->transform_overrides.count)); + + public bool IgnoreConnections => _ptr->ignore_connections; + + public AllocatorOpts ResultAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->result_allocator)); + + internal ufbx_anim_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimProp.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimProp.nativegen.cs new file mode 100644 index 0000000..1c8c50a --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimProp.nativegen.cs @@ -0,0 +1,24 @@ +namespace Ghost.Ufbx; + +public unsafe struct AnimProp +{ + private ufbx_anim_prop* _ptr; + + internal AnimProp(ufbx_anim_prop* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool HasElement => _ptr->element != null; + public Element Element => _ptr->element != null ? new(_ptr->element) : throw new InvalidOperationException("Element is null."); + + public ReadOnlySpan PropNameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->prop_name); + public string PropName => NativeWrapperHelpers.GetString(_ptr->prop_name); + + public bool HasAnimValue => _ptr->anim_value != null; + public AnimValue AnimValue => _ptr->anim_value != null ? new(_ptr->anim_value) : throw new InvalidOperationException("AnimValue is null."); + + internal ufbx_anim_prop* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimStack.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimStack.nativegen.cs new file mode 100644 index 0000000..2e1abba --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimStack.nativegen.cs @@ -0,0 +1,35 @@ +namespace Ghost.Ufbx; + +public unsafe struct AnimStack +{ + private ufbx_anim_stack* _ptr; + + internal AnimStack(ufbx_anim_stack* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public double TimeBegin => _ptr->time_begin; + + public double TimeEnd => _ptr->time_end; + + public AnimLayerList Layers => new(_ptr->layers.data, _ptr->layers.count); + + public bool HasAnim => _ptr->anim != null; + public Anim Anim => _ptr->anim != null ? new(_ptr->anim) : throw new InvalidOperationException("Anim is null."); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_anim_stack* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimStackList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimStackList.nativegen.cs new file mode 100644 index 0000000..218082b --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimStackList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct AnimStackList +{ + private readonly ufbx_anim_stack** _data; + public int Count { get; } + + internal AnimStackList(ufbx_anim_stack** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public AnimStack this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_anim_stack** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_anim_stack** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public AnimStack Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimValue.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimValue.nativegen.cs new file mode 100644 index 0000000..71ded9e --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimValue.nativegen.cs @@ -0,0 +1,48 @@ +namespace Ghost.Ufbx; + +public unsafe struct AnimValue +{ + private ufbx_anim_value* _ptr; + + internal AnimValue(ufbx_anim_value* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public float EvaluateAnimValueReal(double time) + { + return Api.ufbx_evaluate_anim_value_real(_ptr, time); + } + + public Misaki.HighPerformance.Mathematics.float3 EvaluateAnimValueVec3(double time) + { + return Api.ufbx_evaluate_anim_value_vec3(_ptr, time); + } + + public float EvaluateAnimValueRealFlags(double time, uint flags) + { + return Api.ufbx_evaluate_anim_value_real_flags(_ptr, time, flags); + } + + public Misaki.HighPerformance.Mathematics.float3 EvaluateAnimValueVec3Flags(double time, uint flags) + { + return Api.ufbx_evaluate_anim_value_vec3_flags(_ptr, time, flags); + } + + public Misaki.HighPerformance.Mathematics.float3 DefaultValue => _ptr->default_value; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_anim_value* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AnimValueList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimValueList.nativegen.cs new file mode 100644 index 0000000..2fcc7e4 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AnimValueList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct AnimValueList +{ + private readonly ufbx_anim_value** _data; + public int Count { get; } + + internal AnimValueList(ufbx_anim_value** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public AnimValue this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_anim_value** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_anim_value** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public AnimValue Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Application.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Application.nativegen.cs new file mode 100644 index 0000000..9010f62 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Application.nativegen.cs @@ -0,0 +1,24 @@ +namespace Ghost.Ufbx; + +public unsafe struct Application +{ + private ufbx_application* _ptr; + + internal Application(ufbx_application* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan VendorBytes => NativeWrapperHelpers.AsByteSpan(_ptr->vendor); + public string Vendor => NativeWrapperHelpers.GetString(_ptr->vendor); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public ReadOnlySpan VersionBytes => NativeWrapperHelpers.AsByteSpan(_ptr->version); + public string Version => NativeWrapperHelpers.GetString(_ptr->version); + + internal ufbx_application* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AudioClip.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AudioClip.nativegen.cs new file mode 100644 index 0000000..52b483b --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AudioClip.nativegen.cs @@ -0,0 +1,43 @@ +namespace Ghost.Ufbx; + +public unsafe struct AudioClip +{ + private ufbx_audio_clip* _ptr; + + internal AudioClip(ufbx_audio_clip* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan FilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->filename); + public string Filename => NativeWrapperHelpers.GetString(_ptr->filename); + + public ReadOnlySpan AbsoluteFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->absolute_filename); + public string AbsoluteFilename => NativeWrapperHelpers.GetString(_ptr->absolute_filename); + + public ReadOnlySpan RelativeFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->relative_filename); + public string RelativeFilename => NativeWrapperHelpers.GetString(_ptr->relative_filename); + + public ReadOnlySpan RawFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_filename); + + public ReadOnlySpan RawAbsoluteFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_absolute_filename); + + public ReadOnlySpan RawRelativeFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_relative_filename); + + public ReadOnlySpan Content => NativeWrapperHelpers.AsSpan(_ptr->content); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_audio_clip* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AudioClipList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AudioClipList.nativegen.cs new file mode 100644 index 0000000..5504bf6 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AudioClipList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct AudioClipList +{ + private readonly ufbx_audio_clip** _data; + public int Count { get; } + + internal AudioClipList(ufbx_audio_clip** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public AudioClip this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_audio_clip** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_audio_clip** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public AudioClip Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AudioLayer.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AudioLayer.nativegen.cs new file mode 100644 index 0000000..bb140f8 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AudioLayer.nativegen.cs @@ -0,0 +1,28 @@ +namespace Ghost.Ufbx; + +public unsafe struct AudioLayer +{ + private ufbx_audio_layer* _ptr; + + internal AudioLayer(ufbx_audio_layer* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AudioClipList Clips => new(_ptr->clips.data, _ptr->clips.count); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_audio_layer* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/AudioLayerList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/AudioLayerList.nativegen.cs new file mode 100644 index 0000000..b93a3fc --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/AudioLayerList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct AudioLayerList +{ + private readonly ufbx_audio_layer** _data; + public int Count { get; } + + internal AudioLayerList(ufbx_audio_layer** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public AudioLayer this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_audio_layer** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_audio_layer** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public AudioLayer Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BakeOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BakeOpts.nativegen.cs new file mode 100644 index 0000000..6c2ef47 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BakeOpts.nativegen.cs @@ -0,0 +1,53 @@ +namespace Ghost.Ufbx; + +public unsafe struct BakeOpts +{ + private ufbx_bake_opts* _ptr; + + internal BakeOpts(ufbx_bake_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AllocatorOpts TempAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->temp_allocator)); + + public AllocatorOpts ResultAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->result_allocator)); + + public bool TrimStartTime => _ptr->trim_start_time; + + public double ResampleRate => _ptr->resample_rate; + + public double MinimumSampleRate => _ptr->minimum_sample_rate; + + public double MaximumSampleRate => _ptr->maximum_sample_rate; + + public bool BakeTransformProps => _ptr->bake_transform_props; + + public bool SkipNodeTransforms => _ptr->skip_node_transforms; + + public bool NoResampleRotation => _ptr->no_resample_rotation; + + public bool IgnoreLayerWeightAnimation => _ptr->ignore_layer_weight_animation; + + public nuint MaxKeyframeSegments => _ptr->max_keyframe_segments; + + public ufbx_bake_step_handling StepHandling => _ptr->step_handling; + + public double StepCustomDuration => _ptr->step_custom_duration; + + public double StepCustomEpsilon => _ptr->step_custom_epsilon; + + public uint EvaluateFlags => _ptr->evaluate_flags; + + public bool KeyReductionEnabled => _ptr->key_reduction_enabled; + + public bool KeyReductionRotation => _ptr->key_reduction_rotation; + + public double KeyReductionThreshold => _ptr->key_reduction_threshold; + + public nuint KeyReductionPasses => _ptr->key_reduction_passes; + + internal ufbx_bake_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BakedAnim.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedAnim.nativegen.cs new file mode 100644 index 0000000..e98a624 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedAnim.nativegen.cs @@ -0,0 +1,61 @@ +namespace Ghost.Ufbx; + +public unsafe struct BakedAnim +{ + private ufbx_baked_anim* _ptr; + + internal BakedAnim(ufbx_baked_anim* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public void RetainBakedAnim() + { + Api.ufbx_retain_baked_anim(_ptr); + } + + public void FreeBakedAnim() + { + Api.ufbx_free_baked_anim(_ptr); + } + + public BakedNode FindBakedNodeByTypedId(uint typedId) + { + return new(Api.ufbx_find_baked_node_by_typed_id(_ptr, typedId)); + } + + public BakedNode FindBakedNode(Node node) + { + return new(Api.ufbx_find_baked_node(_ptr, node.GetUnsafePtr())); + } + + public BakedElement FindBakedElementByElementId(uint elementId) + { + return new(Api.ufbx_find_baked_element_by_element_id(_ptr, elementId)); + } + + public BakedElement FindBakedElement(Element element) + { + return new(Api.ufbx_find_baked_element(_ptr, element.GetUnsafePtr())); + } + + public ReadOnlySpan Nodes => _ptr->nodes.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->nodes.data, checked((int)_ptr->nodes.count)); + + public ReadOnlySpan Elements => _ptr->elements.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->elements.data, checked((int)_ptr->elements.count)); + + public double PlaybackTimeBegin => _ptr->playback_time_begin; + + public double PlaybackTimeEnd => _ptr->playback_time_end; + + public double PlaybackDuration => _ptr->playback_duration; + + public double KeyTimeMin => _ptr->key_time_min; + + public double KeyTimeMax => _ptr->key_time_max; + + public BakedAnimMetadata Metadata => new((ufbx_baked_anim_metadata*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->metadata)); + + internal ufbx_baked_anim* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BakedAnimMetadata.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedAnimMetadata.nativegen.cs new file mode 100644 index 0000000..55da747 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedAnimMetadata.nativegen.cs @@ -0,0 +1,23 @@ +namespace Ghost.Ufbx; + +public unsafe struct BakedAnimMetadata +{ + private ufbx_baked_anim_metadata* _ptr; + + internal BakedAnimMetadata(ufbx_baked_anim_metadata* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public nuint ResultMemoryUsed => _ptr->result_memory_used; + + public nuint TempMemoryUsed => _ptr->temp_memory_used; + + public nuint ResultAllocs => _ptr->result_allocs; + + public nuint TempAllocs => _ptr->temp_allocs; + + internal ufbx_baked_anim_metadata* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BakedElement.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedElement.nativegen.cs new file mode 100644 index 0000000..cba5509 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedElement.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct BakedElement +{ + private ufbx_baked_element* _ptr; + + internal BakedElement(ufbx_baked_element* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint ElementId => _ptr->element_id; + + public ReadOnlySpan Props => _ptr->props.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->props.data, checked((int)_ptr->props.count)); + + internal ufbx_baked_element* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BakedNode.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedNode.nativegen.cs new file mode 100644 index 0000000..2c2678a --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedNode.nativegen.cs @@ -0,0 +1,31 @@ +namespace Ghost.Ufbx; + +public unsafe struct BakedNode +{ + private ufbx_baked_node* _ptr; + + internal BakedNode(ufbx_baked_node* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint TypedId => _ptr->typed_id; + + public uint ElementId => _ptr->element_id; + + public bool ConstantTranslation => _ptr->constant_translation; + + public bool ConstantRotation => _ptr->constant_rotation; + + public bool ConstantScale => _ptr->constant_scale; + + public ReadOnlySpan TranslationKeys => _ptr->translation_keys.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->translation_keys.data, checked((int)_ptr->translation_keys.count)); + + public ReadOnlySpan RotationKeys => _ptr->rotation_keys.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->rotation_keys.data, checked((int)_ptr->rotation_keys.count)); + + public ReadOnlySpan ScaleKeys => _ptr->scale_keys.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->scale_keys.data, checked((int)_ptr->scale_keys.count)); + + internal ufbx_baked_node* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BakedProp.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedProp.nativegen.cs new file mode 100644 index 0000000..2592b7f --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedProp.nativegen.cs @@ -0,0 +1,22 @@ +namespace Ghost.Ufbx; + +public unsafe struct BakedProp +{ + private ufbx_baked_prop* _ptr; + + internal BakedProp(ufbx_baked_prop* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public bool ConstantValue => _ptr->constant_value; + + public ReadOnlySpan Keys => _ptr->keys.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->keys.data, checked((int)_ptr->keys.count)); + + internal ufbx_baked_prop* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BakedQuat.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedQuat.nativegen.cs new file mode 100644 index 0000000..4031661 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedQuat.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct BakedQuat +{ + private ufbx_baked_quat* _ptr; + + internal BakedQuat(ufbx_baked_quat* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public double Time => _ptr->time; + + public Misaki.HighPerformance.Mathematics.quaternion Value => _ptr->value; + + public ufbx_baked_key_flags Flags => _ptr->flags; + + internal ufbx_baked_quat* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BakedVec3.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedVec3.nativegen.cs new file mode 100644 index 0000000..8bdffc4 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BakedVec3.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct BakedVec3 +{ + private ufbx_baked_vec3* _ptr; + + internal BakedVec3(ufbx_baked_vec3* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public double Time => _ptr->time; + + public Misaki.HighPerformance.Mathematics.float3 Value => _ptr->value; + + public ufbx_baked_key_flags Flags => _ptr->flags; + + internal ufbx_baked_vec3* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BlendChannel.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendChannel.nativegen.cs new file mode 100644 index 0000000..2a1f2f2 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendChannel.nativegen.cs @@ -0,0 +1,33 @@ +namespace Ghost.Ufbx; + +public unsafe struct BlendChannel +{ + private ufbx_blend_channel* _ptr; + + internal BlendChannel(ufbx_blend_channel* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public float Weight => _ptr->weight; + + public ReadOnlySpan Keyframes => _ptr->keyframes.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->keyframes.data, checked((int)_ptr->keyframes.count)); + + public bool HasTargetShape => _ptr->target_shape != null; + public BlendShape TargetShape => _ptr->target_shape != null ? new(_ptr->target_shape) : throw new InvalidOperationException("TargetShape is null."); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_blend_channel* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BlendChannelList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendChannelList.nativegen.cs new file mode 100644 index 0000000..e8e4fc1 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendChannelList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct BlendChannelList +{ + private readonly ufbx_blend_channel** _data; + public int Count { get; } + + internal BlendChannelList(ufbx_blend_channel** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public BlendChannel this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_blend_channel** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_blend_channel** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public BlendChannel Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BlendDeformer.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendDeformer.nativegen.cs new file mode 100644 index 0000000..2078161 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendDeformer.nativegen.cs @@ -0,0 +1,38 @@ +namespace Ghost.Ufbx; + +public unsafe struct BlendDeformer +{ + private ufbx_blend_deformer* _ptr; + + internal BlendDeformer(ufbx_blend_deformer* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Misaki.HighPerformance.Mathematics.float3 GetBlendVertexOffset(nuint vertex) + { + return Api.ufbx_get_blend_vertex_offset(_ptr, vertex); + } + + public void AddBlendVertexOffsets(Misaki.HighPerformance.Mathematics.float3* vertices, nuint numVertices, float weight) + { + Api.ufbx_add_blend_vertex_offsets(_ptr, vertices, numVertices, weight); + } + + public BlendChannelList Channels => new(_ptr->channels.data, _ptr->channels.count); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_blend_deformer* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BlendDeformerList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendDeformerList.nativegen.cs new file mode 100644 index 0000000..213f5af --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendDeformerList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct BlendDeformerList +{ + private readonly ufbx_blend_deformer** _data; + public int Count { get; } + + internal BlendDeformerList(ufbx_blend_deformer** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public BlendDeformer this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_blend_deformer** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_blend_deformer** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public BlendDeformer Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BlendKeyframe.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendKeyframe.nativegen.cs new file mode 100644 index 0000000..e1b16ae --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendKeyframe.nativegen.cs @@ -0,0 +1,22 @@ +namespace Ghost.Ufbx; + +public unsafe struct BlendKeyframe +{ + private ufbx_blend_keyframe* _ptr; + + internal BlendKeyframe(ufbx_blend_keyframe* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool HasShape => _ptr->shape != null; + public BlendShape Shape => _ptr->shape != null ? new(_ptr->shape) : throw new InvalidOperationException("Shape is null."); + + public float TargetWeight => _ptr->target_weight; + + public float EffectiveWeight => _ptr->effective_weight; + + internal ufbx_blend_keyframe* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BlendShape.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendShape.nativegen.cs new file mode 100644 index 0000000..136e49f --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendShape.nativegen.cs @@ -0,0 +1,51 @@ +namespace Ghost.Ufbx; + +public unsafe struct BlendShape +{ + private ufbx_blend_shape* _ptr; + + internal BlendShape(ufbx_blend_shape* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint GetBlendShapeOffsetIndex(nuint vertex) + { + return Api.ufbx_get_blend_shape_offset_index(_ptr, vertex); + } + + public Misaki.HighPerformance.Mathematics.float3 GetBlendShapeVertexOffset(nuint vertex) + { + return Api.ufbx_get_blend_shape_vertex_offset(_ptr, vertex); + } + + public void AddBlendShapeVertexOffsets(Misaki.HighPerformance.Mathematics.float3* vertices, nuint numVertices, float weight) + { + Api.ufbx_add_blend_shape_vertex_offsets(_ptr, vertices, numVertices, weight); + } + + public nuint NumOffsets => _ptr->num_offsets; + + public ReadOnlySpan OffsetVertices => _ptr->offset_vertices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->offset_vertices.data, checked((int)_ptr->offset_vertices.count)); + + public ReadOnlySpan PositionOffsets => _ptr->position_offsets.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->position_offsets.data, checked((int)_ptr->position_offsets.count)); + + public ReadOnlySpan NormalOffsets => _ptr->normal_offsets.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->normal_offsets.data, checked((int)_ptr->normal_offsets.count)); + + public ReadOnlySpan OffsetWeights => _ptr->offset_weights.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->offset_weights.data, checked((int)_ptr->offset_weights.count)); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_blend_shape* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BlendShapeList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendShapeList.nativegen.cs new file mode 100644 index 0000000..b11f483 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BlendShapeList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct BlendShapeList +{ + private readonly ufbx_blend_shape** _data; + public int Count { get; } + + internal BlendShapeList(ufbx_blend_shape** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public BlendShape this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_blend_shape** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_blend_shape** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public BlendShape Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Bone.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Bone.nativegen.cs new file mode 100644 index 0000000..1c61ff5 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Bone.nativegen.cs @@ -0,0 +1,34 @@ +namespace Ghost.Ufbx; + +public unsafe struct Bone +{ + private ufbx_bone* _ptr; + + internal Bone(ufbx_bone* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public float Radius => _ptr->radius; + + public float RelativeLength => _ptr->relative_length; + + public bool IsRoot => _ptr->is_root; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_bone* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BoneList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BoneList.nativegen.cs new file mode 100644 index 0000000..b996942 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BoneList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct BoneList +{ + private readonly ufbx_bone** _data; + public int Count { get; } + + internal BoneList(ufbx_bone** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Bone this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_bone** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_bone** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Bone Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/BonePose.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/BonePose.nativegen.cs new file mode 100644 index 0000000..579927b --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/BonePose.nativegen.cs @@ -0,0 +1,22 @@ +namespace Ghost.Ufbx; + +public unsafe struct BonePose +{ + private ufbx_bone_pose* _ptr; + + internal BonePose(ufbx_bone_pose* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool HasBoneNode => _ptr->bone_node != null; + public Node BoneNode => _ptr->bone_node != null ? new(_ptr->bone_node) : throw new InvalidOperationException("BoneNode is null."); + + public Misaki.HighPerformance.Mathematics.float3x4 BoneToWorld => _ptr->bone_to_world; + + public Misaki.HighPerformance.Mathematics.float3x4 BoneToParent => _ptr->bone_to_parent; + + internal ufbx_bone_pose* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CacheChannel.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheChannel.nativegen.cs new file mode 100644 index 0000000..d623fa0 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheChannel.nativegen.cs @@ -0,0 +1,39 @@ +namespace Ghost.Ufbx; + +public unsafe struct CacheChannel +{ + private ufbx_cache_channel* _ptr; + + internal CacheChannel(ufbx_cache_channel* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public nuint SampleGeometryCacheReal(double time, float* data, nuint numData, GeometryCacheDataOpts opts) + { + return Api.ufbx_sample_geometry_cache_real(_ptr, time, data, numData, opts.GetUnsafePtr()); + } + + public nuint SampleGeometryCacheVec3(double time, Misaki.HighPerformance.Mathematics.float3* data, nuint numData, GeometryCacheDataOpts opts) + { + return Api.ufbx_sample_geometry_cache_vec3(_ptr, time, data, numData, opts.GetUnsafePtr()); + } + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public ufbx_cache_interpretation Interpretation => _ptr->interpretation; + + public ReadOnlySpan InterpretationNameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->interpretation_name); + public string InterpretationName => NativeWrapperHelpers.GetString(_ptr->interpretation_name); + + public ReadOnlySpan Frames => _ptr->frames.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->frames.data, checked((int)_ptr->frames.count)); + + public ufbx_mirror_axis MirrorAxis => _ptr->mirror_axis; + + public float ScaleFactor => _ptr->scale_factor; + + internal ufbx_cache_channel* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CacheDeformer.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheDeformer.nativegen.cs new file mode 100644 index 0000000..24fd309 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheDeformer.nativegen.cs @@ -0,0 +1,38 @@ +namespace Ghost.Ufbx; + +public unsafe struct CacheDeformer +{ + private ufbx_cache_deformer* _ptr; + + internal CacheDeformer(ufbx_cache_deformer* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan ChannelBytes => NativeWrapperHelpers.AsByteSpan(_ptr->channel); + public string Channel => NativeWrapperHelpers.GetString(_ptr->channel); + + public bool HasFile => _ptr->file != null; + public CacheFile File => _ptr->file != null ? new(_ptr->file) : throw new InvalidOperationException("File is null."); + + public bool HasExternalCache => _ptr->external_cache != null; + public GeometryCache ExternalCache => _ptr->external_cache != null ? new(_ptr->external_cache) : throw new InvalidOperationException("ExternalCache is null."); + + public bool HasExternalChannel => _ptr->external_channel != null; + public CacheChannel ExternalChannel => _ptr->external_channel != null ? new(_ptr->external_channel) : throw new InvalidOperationException("ExternalChannel is null."); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_cache_deformer* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CacheDeformerList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheDeformerList.nativegen.cs new file mode 100644 index 0000000..872e09e --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheDeformerList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct CacheDeformerList +{ + private readonly ufbx_cache_deformer** _data; + public int Count { get; } + + internal CacheDeformerList(ufbx_cache_deformer** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public CacheDeformer this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_cache_deformer** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_cache_deformer** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public CacheDeformer Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CacheFile.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheFile.nativegen.cs new file mode 100644 index 0000000..b78d683 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheFile.nativegen.cs @@ -0,0 +1,46 @@ +namespace Ghost.Ufbx; + +public unsafe struct CacheFile +{ + private ufbx_cache_file* _ptr; + + internal CacheFile(ufbx_cache_file* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan FilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->filename); + public string Filename => NativeWrapperHelpers.GetString(_ptr->filename); + + public ReadOnlySpan AbsoluteFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->absolute_filename); + public string AbsoluteFilename => NativeWrapperHelpers.GetString(_ptr->absolute_filename); + + public ReadOnlySpan RelativeFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->relative_filename); + public string RelativeFilename => NativeWrapperHelpers.GetString(_ptr->relative_filename); + + public ReadOnlySpan RawFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_filename); + + public ReadOnlySpan RawAbsoluteFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_absolute_filename); + + public ReadOnlySpan RawRelativeFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_relative_filename); + + public ufbx_cache_file_format Format => _ptr->format; + + public bool HasExternalCache => _ptr->external_cache != null; + public GeometryCache ExternalCache => _ptr->external_cache != null ? new(_ptr->external_cache) : throw new InvalidOperationException("ExternalCache is null."); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_cache_file* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CacheFileList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheFileList.nativegen.cs new file mode 100644 index 0000000..c9e1427 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheFileList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct CacheFileList +{ + private readonly ufbx_cache_file** _data; + public int Count { get; } + + internal CacheFileList(ufbx_cache_file** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public CacheFile this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_cache_file** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_cache_file** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public CacheFile Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CacheFrame.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheFrame.nativegen.cs new file mode 100644 index 0000000..7ae8604 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CacheFrame.nativegen.cs @@ -0,0 +1,51 @@ +namespace Ghost.Ufbx; + +public unsafe struct CacheFrame +{ + private ufbx_cache_frame* _ptr; + + internal CacheFrame(ufbx_cache_frame* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public nuint ReadGeometryCacheReal(float* data, nuint numData, GeometryCacheDataOpts opts) + { + return Api.ufbx_read_geometry_cache_real(_ptr, data, numData, opts.GetUnsafePtr()); + } + + public nuint ReadGeometryCacheVec3(Misaki.HighPerformance.Mathematics.float3* data, nuint numData, GeometryCacheDataOpts opts) + { + return Api.ufbx_read_geometry_cache_vec3(_ptr, data, numData, opts.GetUnsafePtr()); + } + + public ReadOnlySpan ChannelBytes => NativeWrapperHelpers.AsByteSpan(_ptr->channel); + public string Channel => NativeWrapperHelpers.GetString(_ptr->channel); + + public double Time => _ptr->time; + + public ReadOnlySpan FilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->filename); + public string Filename => NativeWrapperHelpers.GetString(_ptr->filename); + + public ufbx_cache_file_format FileFormat => _ptr->file_format; + + public ufbx_mirror_axis MirrorAxis => _ptr->mirror_axis; + + public float ScaleFactor => _ptr->scale_factor; + + public ufbx_cache_data_format DataFormat => _ptr->data_format; + + public ufbx_cache_data_encoding DataEncoding => _ptr->data_encoding; + + public ulong DataOffset => _ptr->data_offset; + + public uint DataCount => _ptr->data_count; + + public uint DataElementBytes => _ptr->data_element_bytes; + + public ulong DataTotalBytes => _ptr->data_total_bytes; + + internal ufbx_cache_frame* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Camera.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Camera.nativegen.cs new file mode 100644 index 0000000..78ecb80 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Camera.nativegen.cs @@ -0,0 +1,68 @@ +namespace Ghost.Ufbx; + +public unsafe struct Camera +{ + private ufbx_camera* _ptr; + + internal Camera(ufbx_camera* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_projection_mode ProjectionMode => _ptr->projection_mode; + + public bool ResolutionIsPixels => _ptr->resolution_is_pixels; + + public Misaki.HighPerformance.Mathematics.float2 Resolution => _ptr->resolution; + + public Misaki.HighPerformance.Mathematics.float2 FieldOfViewDeg => _ptr->field_of_view_deg; + + public Misaki.HighPerformance.Mathematics.float2 FieldOfViewTan => _ptr->field_of_view_tan; + + public float OrthographicExtent => _ptr->orthographic_extent; + + public Misaki.HighPerformance.Mathematics.float2 OrthographicSize => _ptr->orthographic_size; + + public Misaki.HighPerformance.Mathematics.float2 ProjectionPlane => _ptr->projection_plane; + + public float AspectRatio => _ptr->aspect_ratio; + + public float NearPlane => _ptr->near_plane; + + public float FarPlane => _ptr->far_plane; + + public CoordinateAxes ProjectionAxes => new((ufbx_coordinate_axes*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->projection_axes)); + + public ufbx_aspect_mode AspectMode => _ptr->aspect_mode; + + public ufbx_aperture_mode ApertureMode => _ptr->aperture_mode; + + public ufbx_gate_fit GateFit => _ptr->gate_fit; + + public ufbx_aperture_format ApertureFormat => _ptr->aperture_format; + + public float FocalLengthMm => _ptr->focal_length_mm; + + public Misaki.HighPerformance.Mathematics.float2 FilmSizeInch => _ptr->film_size_inch; + + public Misaki.HighPerformance.Mathematics.float2 ApertureSizeInch => _ptr->aperture_size_inch; + + public float SqueezeRatio => _ptr->squeeze_ratio; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_camera* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CameraList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CameraList.nativegen.cs new file mode 100644 index 0000000..86c33d4 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CameraList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct CameraList +{ + private readonly ufbx_camera** _data; + public int Count { get; } + + internal CameraList(ufbx_camera** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Camera this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_camera** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_camera** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Camera Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CameraSwitcher.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CameraSwitcher.nativegen.cs new file mode 100644 index 0000000..9b93d49 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CameraSwitcher.nativegen.cs @@ -0,0 +1,28 @@ +namespace Ghost.Ufbx; + +public unsafe struct CameraSwitcher +{ + private ufbx_camera_switcher* _ptr; + + internal CameraSwitcher(ufbx_camera_switcher* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_camera_switcher* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CameraSwitcherList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CameraSwitcherList.nativegen.cs new file mode 100644 index 0000000..197aa97 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CameraSwitcherList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct CameraSwitcherList +{ + private readonly ufbx_camera_switcher** _data; + public int Count { get; } + + internal CameraSwitcherList(ufbx_camera_switcher** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public CameraSwitcher this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_camera_switcher** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_camera_switcher** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public CameraSwitcher Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Character.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Character.nativegen.cs new file mode 100644 index 0000000..9fe97f1 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Character.nativegen.cs @@ -0,0 +1,26 @@ +namespace Ghost.Ufbx; + +public unsafe struct Character +{ + private ufbx_character* _ptr; + + internal Character(ufbx_character* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_character* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CharacterList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CharacterList.nativegen.cs new file mode 100644 index 0000000..154a8ce --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CharacterList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct CharacterList +{ + private readonly ufbx_character** _data; + public int Count { get; } + + internal CharacterList(ufbx_character** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Character this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_character** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_character** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Character Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CloseMemoryCb.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CloseMemoryCb.nativegen.cs new file mode 100644 index 0000000..c80b3fe --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CloseMemoryCb.nativegen.cs @@ -0,0 +1,17 @@ +namespace Ghost.Ufbx; + +public unsafe struct CloseMemoryCb +{ + private ufbx_close_memory_cb* _ptr; + + internal CloseMemoryCb(ufbx_close_memory_cb* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public void* User => _ptr->user; + + internal ufbx_close_memory_cb* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ColorSet.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ColorSet.nativegen.cs new file mode 100644 index 0000000..8f26208 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ColorSet.nativegen.cs @@ -0,0 +1,22 @@ +namespace Ghost.Ufbx; + +public unsafe struct ColorSet +{ + private ufbx_color_set* _ptr; + + internal ColorSet(ufbx_color_set* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public uint Index => _ptr->index; + + public VertexVec4 VertexColor => new((ufbx_vertex_vec4*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_color)); + + internal ufbx_color_set* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Connection.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Connection.nativegen.cs new file mode 100644 index 0000000..2b3214d --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Connection.nativegen.cs @@ -0,0 +1,27 @@ +namespace Ghost.Ufbx; + +public unsafe struct Connection +{ + private ufbx_connection* _ptr; + + internal Connection(ufbx_connection* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool HasSrc => _ptr->src != null; + public Element Src => _ptr->src != null ? new(_ptr->src) : throw new InvalidOperationException("Src is null."); + + public bool HasDst => _ptr->dst != null; + public Element Dst => _ptr->dst != null ? new(_ptr->dst) : throw new InvalidOperationException("Dst is null."); + + public ReadOnlySpan SrcPropBytes => NativeWrapperHelpers.AsByteSpan(_ptr->src_prop); + public string SrcProp => NativeWrapperHelpers.GetString(_ptr->src_prop); + + public ReadOnlySpan DstPropBytes => NativeWrapperHelpers.AsByteSpan(_ptr->dst_prop); + public string DstProp => NativeWrapperHelpers.GetString(_ptr->dst_prop); + + internal ufbx_connection* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Constraint.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Constraint.nativegen.cs new file mode 100644 index 0000000..acedc62 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Constraint.nativegen.cs @@ -0,0 +1,59 @@ +namespace Ghost.Ufbx; + +public unsafe struct Constraint +{ + private ufbx_constraint* _ptr; + + internal Constraint(ufbx_constraint* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_constraint_type Type => _ptr->type; + + public ReadOnlySpan TypeNameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->type_name); + public string TypeName => NativeWrapperHelpers.GetString(_ptr->type_name); + + public bool HasNode => _ptr->node != null; + public Node Node => _ptr->node != null ? new(_ptr->node) : throw new InvalidOperationException("Node is null."); + + public ReadOnlySpan Targets => _ptr->targets.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->targets.data, checked((int)_ptr->targets.count)); + + public float Weight => _ptr->weight; + + public bool Active => _ptr->active; + + public Transform TransformOffset => new((ufbx_transform*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transform_offset)); + + public Misaki.HighPerformance.Mathematics.float3 AimVector => _ptr->aim_vector; + + public ufbx_constraint_aim_up_type AimUpType => _ptr->aim_up_type; + + public bool HasAimUpNode => _ptr->aim_up_node != null; + public Node AimUpNode => _ptr->aim_up_node != null ? new(_ptr->aim_up_node) : throw new InvalidOperationException("AimUpNode is null."); + + public Misaki.HighPerformance.Mathematics.float3 AimUpVector => _ptr->aim_up_vector; + + public bool HasIkEffector => _ptr->ik_effector != null; + public Node IkEffector => _ptr->ik_effector != null ? new(_ptr->ik_effector) : throw new InvalidOperationException("IkEffector is null."); + + public bool HasIkEndNode => _ptr->ik_end_node != null; + public Node IkEndNode => _ptr->ik_end_node != null ? new(_ptr->ik_end_node) : throw new InvalidOperationException("IkEndNode is null."); + + public Misaki.HighPerformance.Mathematics.float3 IkPoleVector => _ptr->ik_pole_vector; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_constraint* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ConstraintList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ConstraintList.nativegen.cs new file mode 100644 index 0000000..a31a21e --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ConstraintList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct ConstraintList +{ + private readonly ufbx_constraint** _data; + public int Count { get; } + + internal ConstraintList(ufbx_constraint** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Constraint this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_constraint** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_constraint** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Constraint Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ConstraintTarget.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ConstraintTarget.nativegen.cs new file mode 100644 index 0000000..58c3e84 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ConstraintTarget.nativegen.cs @@ -0,0 +1,22 @@ +namespace Ghost.Ufbx; + +public unsafe struct ConstraintTarget +{ + private ufbx_constraint_target* _ptr; + + internal ConstraintTarget(ufbx_constraint_target* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool HasNode => _ptr->node != null; + public Node Node => _ptr->node != null ? new(_ptr->node) : throw new InvalidOperationException("Node is null."); + + public float Weight => _ptr->weight; + + public Transform Transform => new((ufbx_transform*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transform)); + + internal ufbx_constraint_target* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CoordinateAxes.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CoordinateAxes.nativegen.cs new file mode 100644 index 0000000..7c3945a --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CoordinateAxes.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct CoordinateAxes +{ + private ufbx_coordinate_axes* _ptr; + + internal CoordinateAxes(ufbx_coordinate_axes* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_coordinate_axis Right => _ptr->right; + + public ufbx_coordinate_axis Up => _ptr->up; + + public ufbx_coordinate_axis Front => _ptr->front; + + internal ufbx_coordinate_axes* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/CurvePoint.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/CurvePoint.nativegen.cs new file mode 100644 index 0000000..edde6d2 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/CurvePoint.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct CurvePoint +{ + private ufbx_curve_point* _ptr; + + internal CurvePoint(ufbx_curve_point* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool Valid => _ptr->valid; + + public Misaki.HighPerformance.Mathematics.float3 Position => _ptr->position; + + public Misaki.HighPerformance.Mathematics.float3 Derivative => _ptr->derivative; + + internal ufbx_curve_point* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/DisplayLayer.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/DisplayLayer.nativegen.cs new file mode 100644 index 0000000..1e5182a --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/DisplayLayer.nativegen.cs @@ -0,0 +1,34 @@ +namespace Ghost.Ufbx; + +public unsafe struct DisplayLayer +{ + private ufbx_display_layer* _ptr; + + internal DisplayLayer(ufbx_display_layer* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public NodeList Nodes => new(_ptr->nodes.data, _ptr->nodes.count); + + public bool Visible => _ptr->visible; + + public bool Frozen => _ptr->frozen; + + public Misaki.HighPerformance.Mathematics.float3 UiColor => _ptr->ui_color; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_display_layer* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/DisplayLayerList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/DisplayLayerList.nativegen.cs new file mode 100644 index 0000000..1d718e5 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/DisplayLayerList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct DisplayLayerList +{ + private readonly ufbx_display_layer** _data; + public int Count { get; } + + internal DisplayLayerList(ufbx_display_layer** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public DisplayLayer this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_display_layer** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_display_layer** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public DisplayLayer Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/DomNode.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/DomNode.nativegen.cs new file mode 100644 index 0000000..36b04fc --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/DomNode.nativegen.cs @@ -0,0 +1,72 @@ +namespace Ghost.Ufbx; + +public unsafe struct DomNode +{ + private ufbx_dom_node* _ptr; + + internal DomNode(ufbx_dom_node* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public DomNode DomFindLen(sbyte* name, nuint nameLen) + { + return new(Api.ufbx_dom_find_len(_ptr, name, nameLen)); + } + + public DomNode DomFind(sbyte* name) + { + return new(Api.ufbx_dom_find(_ptr, name)); + } + + public bool DomIsArray() + { + return Api.ufbx_dom_is_array(_ptr); + } + + public nuint DomArraySize() + { + return Api.ufbx_dom_array_size(_ptr); + } + + public ufbx_int32_list DomAsInt32List() + { + return Api.ufbx_dom_as_int32_list(_ptr); + } + + public ufbx_int64_list DomAsInt64List() + { + return Api.ufbx_dom_as_int64_list(_ptr); + } + + public ufbx_float_list DomAsFloatList() + { + return Api.ufbx_dom_as_float_list(_ptr); + } + + public ufbx_double_list DomAsDoubleList() + { + return Api.ufbx_dom_as_double_list(_ptr); + } + + public ufbx_real_list DomAsRealList() + { + return Api.ufbx_dom_as_real_list(_ptr); + } + + public ufbx_blob_list DomAsBlobList() + { + return Api.ufbx_dom_as_blob_list(_ptr); + } + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public DomNodeList Children => new(_ptr->children.data, _ptr->children.count); + + public ReadOnlySpan Values => _ptr->values.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values.data, checked((int)_ptr->values.count)); + + internal ufbx_dom_node* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/DomNodeList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/DomNodeList.nativegen.cs new file mode 100644 index 0000000..8d0a0fb --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/DomNodeList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct DomNodeList +{ + private readonly ufbx_dom_node** _data; + public int Count { get; } + + internal DomNodeList(ufbx_dom_node** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public DomNode this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_dom_node** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_dom_node** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public DomNode Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/DomValue.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/DomValue.nativegen.cs new file mode 100644 index 0000000..9f1c00f --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/DomValue.nativegen.cs @@ -0,0 +1,26 @@ +namespace Ghost.Ufbx; + +public unsafe struct DomValue +{ + private ufbx_dom_value* _ptr; + + internal DomValue(ufbx_dom_value* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_dom_value_type Type => _ptr->type; + + public ReadOnlySpan ValueStrBytes => NativeWrapperHelpers.AsByteSpan(_ptr->value_str); + public string ValueStr => NativeWrapperHelpers.GetString(_ptr->value_str); + + public ReadOnlySpan ValueBlob => NativeWrapperHelpers.AsSpan(_ptr->value_blob); + + public long ValueInt => _ptr->value_int; + + public double ValueFloat => _ptr->value_float; + + internal ufbx_dom_value* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Edge.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Edge.nativegen.cs new file mode 100644 index 0000000..23ead45 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Edge.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct Edge +{ + private ufbx_edge* _ptr; + + internal Edge(ufbx_edge* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint A => _ptr->a; + + public uint B => _ptr->b; + + internal ufbx_edge* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Element.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Element.nativegen.cs new file mode 100644 index 0000000..71049ef --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Element.nativegen.cs @@ -0,0 +1,263 @@ +namespace Ghost.Ufbx; + +public unsafe ref struct Element +{ + private ufbx_element* _ptr; + + internal Element(ufbx_element* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Element GetPropElement(Prop prop, ufbx_element_type type) + { + return new(Api.ufbx_get_prop_element(_ptr, prop.GetUnsafePtr(), type)); + } + + public Element FindPropElementLen(sbyte* name, nuint nameLen, ufbx_element_type type) + { + return new(Api.ufbx_find_prop_element_len(_ptr, name, nameLen, type)); + } + + public Element FindPropElement(sbyte* name, ufbx_element_type type) + { + return new(Api.ufbx_find_prop_element(_ptr, name, type)); + } + + public Unknown AsUnknown() + { + return new(Api.ufbx_as_unknown(_ptr)); + } + + public Node AsNode() + { + return new(Api.ufbx_as_node(_ptr)); + } + + public Mesh AsMesh() + { + return new(Api.ufbx_as_mesh(_ptr)); + } + + public Light AsLight() + { + return new(Api.ufbx_as_light(_ptr)); + } + + public Camera AsCamera() + { + return new(Api.ufbx_as_camera(_ptr)); + } + + public Bone AsBone() + { + return new(Api.ufbx_as_bone(_ptr)); + } + + public Empty AsEmpty() + { + return new(Api.ufbx_as_empty(_ptr)); + } + + public LineCurve AsLineCurve() + { + return new(Api.ufbx_as_line_curve(_ptr)); + } + + public NurbsCurve AsNurbsCurve() + { + return new(Api.ufbx_as_nurbs_curve(_ptr)); + } + + public NurbsSurface AsNurbsSurface() + { + return new(Api.ufbx_as_nurbs_surface(_ptr)); + } + + public NurbsTrimSurface AsNurbsTrimSurface() + { + return new(Api.ufbx_as_nurbs_trim_surface(_ptr)); + } + + public NurbsTrimBoundary AsNurbsTrimBoundary() + { + return new(Api.ufbx_as_nurbs_trim_boundary(_ptr)); + } + + public ProceduralGeometry AsProceduralGeometry() + { + return new(Api.ufbx_as_procedural_geometry(_ptr)); + } + + public StereoCamera AsStereoCamera() + { + return new(Api.ufbx_as_stereo_camera(_ptr)); + } + + public CameraSwitcher AsCameraSwitcher() + { + return new(Api.ufbx_as_camera_switcher(_ptr)); + } + + public Marker AsMarker() + { + return new(Api.ufbx_as_marker(_ptr)); + } + + public LodGroup AsLodGroup() + { + return new(Api.ufbx_as_lod_group(_ptr)); + } + + public SkinDeformer AsSkinDeformer() + { + return new(Api.ufbx_as_skin_deformer(_ptr)); + } + + public SkinCluster AsSkinCluster() + { + return new(Api.ufbx_as_skin_cluster(_ptr)); + } + + public BlendDeformer AsBlendDeformer() + { + return new(Api.ufbx_as_blend_deformer(_ptr)); + } + + public BlendChannel AsBlendChannel() + { + return new(Api.ufbx_as_blend_channel(_ptr)); + } + + public BlendShape AsBlendShape() + { + return new(Api.ufbx_as_blend_shape(_ptr)); + } + + public CacheDeformer AsCacheDeformer() + { + return new(Api.ufbx_as_cache_deformer(_ptr)); + } + + public CacheFile AsCacheFile() + { + return new(Api.ufbx_as_cache_file(_ptr)); + } + + public Material AsMaterial() + { + return new(Api.ufbx_as_material(_ptr)); + } + + public Texture AsTexture() + { + return new(Api.ufbx_as_texture(_ptr)); + } + + public Video AsVideo() + { + return new(Api.ufbx_as_video(_ptr)); + } + + public Shader AsShader() + { + return new(Api.ufbx_as_shader(_ptr)); + } + + public ShaderBinding AsShaderBinding() + { + return new(Api.ufbx_as_shader_binding(_ptr)); + } + + public AnimStack AsAnimStack() + { + return new(Api.ufbx_as_anim_stack(_ptr)); + } + + public AnimLayer AsAnimLayer() + { + return new(Api.ufbx_as_anim_layer(_ptr)); + } + + public AnimValue AsAnimValue() + { + return new(Api.ufbx_as_anim_value(_ptr)); + } + + public AnimCurve AsAnimCurve() + { + return new(Api.ufbx_as_anim_curve(_ptr)); + } + + public DisplayLayer AsDisplayLayer() + { + return new(Api.ufbx_as_display_layer(_ptr)); + } + + public SelectionSet AsSelectionSet() + { + return new(Api.ufbx_as_selection_set(_ptr)); + } + + public SelectionNode AsSelectionNode() + { + return new(Api.ufbx_as_selection_node(_ptr)); + } + + public Character AsCharacter() + { + return new(Api.ufbx_as_character(_ptr)); + } + + public Constraint AsConstraint() + { + return new(Api.ufbx_as_constraint(_ptr)); + } + + public AudioLayer AsAudioLayer() + { + return new(Api.ufbx_as_audio_layer(_ptr)); + } + + public AudioClip AsAudioClip() + { + return new(Api.ufbx_as_audio_clip(_ptr)); + } + + public Pose AsPose() + { + return new(Api.ufbx_as_pose(_ptr)); + } + + public MetadataObject AsMetadataObject() + { + return new(Api.ufbx_as_metadata_object(_ptr)); + } + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + public ufbx_element_type Type => _ptr->type; + + public ReadOnlySpan ConnectionsSrc => _ptr->connections_src.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->connections_src.data, checked((int)_ptr->connections_src.count)); + + public ReadOnlySpan ConnectionsDst => _ptr->connections_dst.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->connections_dst.data, checked((int)_ptr->connections_dst.count)); + + public bool HasDomNode => _ptr->dom_node != null; + public DomNode DomNode => _ptr->dom_node != null ? new(_ptr->dom_node) : throw new InvalidOperationException("DomNode is null."); + + public bool HasScene => _ptr->scene != null; + public Scene Scene => _ptr->scene != null ? new(_ptr->scene) : throw new InvalidOperationException("Scene is null."); + + internal ufbx_element* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ElementList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ElementList.nativegen.cs new file mode 100644 index 0000000..21a89e7 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ElementList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct ElementList +{ + private readonly ufbx_element** _data; + public int Count { get; } + + internal ElementList(ufbx_element** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Element this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_element** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_element** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Element Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Empty.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Empty.nativegen.cs new file mode 100644 index 0000000..b0df3db --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Empty.nativegen.cs @@ -0,0 +1,28 @@ +namespace Ghost.Ufbx; + +public unsafe struct Empty +{ + private ufbx_empty* _ptr; + + internal Empty(ufbx_empty* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_empty* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/EmptyList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/EmptyList.nativegen.cs new file mode 100644 index 0000000..e31adfc --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/EmptyList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct EmptyList +{ + private readonly ufbx_empty** _data; + public int Count { get; } + + internal EmptyList(ufbx_empty** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Empty this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_empty** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_empty** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Empty Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Error.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Error.nativegen.cs new file mode 100644 index 0000000..26265d5 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Error.nativegen.cs @@ -0,0 +1,24 @@ +namespace Ghost.Ufbx; + +public unsafe struct Error +{ + private ufbx_error* _ptr; + + internal Error(ufbx_error* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_error_type Type => _ptr->type; + + public ReadOnlySpan DescriptionBytes => NativeWrapperHelpers.AsByteSpan(_ptr->description); + public string Description => NativeWrapperHelpers.GetString(_ptr->description); + + public uint StackSize => _ptr->stack_size; + + public nuint InfoLength => _ptr->info_length; + + internal ufbx_error* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ErrorFrame.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ErrorFrame.nativegen.cs new file mode 100644 index 0000000..088c72c --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ErrorFrame.nativegen.cs @@ -0,0 +1,23 @@ +namespace Ghost.Ufbx; + +public unsafe struct ErrorFrame +{ + private ufbx_error_frame* _ptr; + + internal ErrorFrame(ufbx_error_frame* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint SourceLine => _ptr->source_line; + + public ReadOnlySpan FunctionBytes => NativeWrapperHelpers.AsByteSpan(_ptr->function); + public string Function => NativeWrapperHelpers.GetString(_ptr->function); + + public ReadOnlySpan DescriptionBytes => NativeWrapperHelpers.AsByteSpan(_ptr->description); + public string Description => NativeWrapperHelpers.GetString(_ptr->description); + + internal ufbx_error_frame* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/EvaluateOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/EvaluateOpts.nativegen.cs new file mode 100644 index 0000000..7f7bb5c --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/EvaluateOpts.nativegen.cs @@ -0,0 +1,29 @@ +namespace Ghost.Ufbx; + +public unsafe struct EvaluateOpts +{ + private ufbx_evaluate_opts* _ptr; + + internal EvaluateOpts(ufbx_evaluate_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AllocatorOpts TempAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->temp_allocator)); + + public AllocatorOpts ResultAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->result_allocator)); + + public bool EvaluateSkinning => _ptr->evaluate_skinning; + + public bool EvaluateCaches => _ptr->evaluate_caches; + + public uint EvaluateFlags => _ptr->evaluate_flags; + + public bool LoadExternalFiles => _ptr->load_external_files; + + public OpenFileCb OpenFileCb => new((ufbx_open_file_cb*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->open_file_cb)); + + internal ufbx_evaluate_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Extrapolation.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Extrapolation.nativegen.cs new file mode 100644 index 0000000..a9935fd --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Extrapolation.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct Extrapolation +{ + private ufbx_extrapolation* _ptr; + + internal Extrapolation(ufbx_extrapolation* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_extrapolation_mode Mode => _ptr->mode; + + public int RepeatCount => _ptr->repeat_count; + + internal ufbx_extrapolation* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Face.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Face.nativegen.cs new file mode 100644 index 0000000..6758658 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Face.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct Face +{ + private ufbx_face* _ptr; + + internal Face(ufbx_face* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint IndexBegin => _ptr->index_begin; + + public uint NumIndices => _ptr->num_indices; + + internal ufbx_face* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/FaceGroup.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/FaceGroup.nativegen.cs new file mode 100644 index 0000000..e8e1ff0 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/FaceGroup.nativegen.cs @@ -0,0 +1,20 @@ +namespace Ghost.Ufbx; + +public unsafe struct FaceGroup +{ + private ufbx_face_group* _ptr; + + internal FaceGroup(ufbx_face_group* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public int Id => _ptr->id; + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + internal ufbx_face_group* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCache.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCache.nativegen.cs new file mode 100644 index 0000000..d69e4ea --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCache.nativegen.cs @@ -0,0 +1,44 @@ +namespace Ghost.Ufbx; + +public unsafe struct GeometryCache +{ + private ufbx_geometry_cache* _ptr; + + internal GeometryCache(ufbx_geometry_cache* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public static GeometryCache LoadGeometryCache(sbyte* filename, GeometryCacheOpts opts, Error error) + { + return new(Api.ufbx_load_geometry_cache(filename, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public static GeometryCache LoadGeometryCacheLen(sbyte* filename, nuint filenameLen, GeometryCacheOpts opts, Error error) + { + return new(Api.ufbx_load_geometry_cache_len(filename, filenameLen, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public void FreeGeometryCache() + { + Api.ufbx_free_geometry_cache(_ptr); + } + + public void RetainGeometryCache() + { + Api.ufbx_retain_geometry_cache(_ptr); + } + + public ReadOnlySpan RootFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->root_filename); + public string RootFilename => NativeWrapperHelpers.GetString(_ptr->root_filename); + + public ReadOnlySpan Channels => _ptr->channels.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->channels.data, checked((int)_ptr->channels.count)); + + public ReadOnlySpan Frames => _ptr->frames.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->frames.data, checked((int)_ptr->frames.count)); + + public ReadOnlySpan ExtraInfo => _ptr->extra_info.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->extra_info.data, checked((int)_ptr->extra_info.count)); + + internal ufbx_geometry_cache* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCacheDataOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCacheDataOpts.nativegen.cs new file mode 100644 index 0000000..6bbea69 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCacheDataOpts.nativegen.cs @@ -0,0 +1,25 @@ +namespace Ghost.Ufbx; + +public unsafe struct GeometryCacheDataOpts +{ + private ufbx_geometry_cache_data_opts* _ptr; + + internal GeometryCacheDataOpts(ufbx_geometry_cache_data_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public OpenFileCb OpenFileCb => new((ufbx_open_file_cb*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->open_file_cb)); + + public bool Additive => _ptr->additive; + + public bool UseWeight => _ptr->use_weight; + + public float Weight => _ptr->weight; + + public bool IgnoreTransform => _ptr->ignore_transform; + + internal ufbx_geometry_cache_data_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCacheOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCacheOpts.nativegen.cs new file mode 100644 index 0000000..ead2c9d --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/GeometryCacheOpts.nativegen.cs @@ -0,0 +1,29 @@ +namespace Ghost.Ufbx; + +public unsafe struct GeometryCacheOpts +{ + private ufbx_geometry_cache_opts* _ptr; + + internal GeometryCacheOpts(ufbx_geometry_cache_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AllocatorOpts TempAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->temp_allocator)); + + public AllocatorOpts ResultAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->result_allocator)); + + public OpenFileCb OpenFileCb => new((ufbx_open_file_cb*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->open_file_cb)); + + public double FramesPerSecond => _ptr->frames_per_second; + + public ufbx_mirror_axis MirrorAxis => _ptr->mirror_axis; + + public bool UseScaleFactor => _ptr->use_scale_factor; + + public float ScaleFactor => _ptr->scale_factor; + + internal ufbx_geometry_cache_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/InflateInput.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/InflateInput.nativegen.cs new file mode 100644 index 0000000..2ad8d5e --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/InflateInput.nativegen.cs @@ -0,0 +1,41 @@ +namespace Ghost.Ufbx; + +public unsafe struct InflateInput +{ + private ufbx_inflate_input* _ptr; + + internal InflateInput(ufbx_inflate_input* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public nuint TotalSize => _ptr->total_size; + + public void* Data => _ptr->data; + + public nuint DataSize => _ptr->data_size; + + public void* Buffer => _ptr->buffer; + + public nuint BufferSize => _ptr->buffer_size; + + public void* ReadUser => _ptr->read_user; + + public ProgressCb ProgressCb => new((ufbx_progress_cb*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->progress_cb)); + + public ulong ProgressIntervalHint => _ptr->progress_interval_hint; + + public ulong ProgressSizeBefore => _ptr->progress_size_before; + + public ulong ProgressSizeAfter => _ptr->progress_size_after; + + public bool NoHeader => _ptr->no_header; + + public bool NoChecksum => _ptr->no_checksum; + + public nuint InternalFastBits => _ptr->internal_fast_bits; + + internal ufbx_inflate_input* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/InflateRetain.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/InflateRetain.nativegen.cs new file mode 100644 index 0000000..25b867b --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/InflateRetain.nativegen.cs @@ -0,0 +1,17 @@ +namespace Ghost.Ufbx; + +public unsafe struct InflateRetain +{ + private ufbx_inflate_retain* _ptr; + + internal InflateRetain(ufbx_inflate_retain* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool Initialized => _ptr->initialized; + + internal ufbx_inflate_retain* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Keyframe.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Keyframe.nativegen.cs new file mode 100644 index 0000000..383dd77 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Keyframe.nativegen.cs @@ -0,0 +1,25 @@ +namespace Ghost.Ufbx; + +public unsafe struct Keyframe +{ + private ufbx_keyframe* _ptr; + + internal Keyframe(ufbx_keyframe* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public double Time => _ptr->time; + + public float Value => _ptr->value; + + public ufbx_interpolation Interpolation => _ptr->interpolation; + + public Tangent Left => new((ufbx_tangent*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->left)); + + public Tangent Right => new((ufbx_tangent*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->right)); + + internal ufbx_keyframe* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Light.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Light.nativegen.cs new file mode 100644 index 0000000..842a084 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Light.nativegen.cs @@ -0,0 +1,48 @@ +namespace Ghost.Ufbx; + +public unsafe struct Light +{ + private ufbx_light* _ptr; + + internal Light(ufbx_light* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Misaki.HighPerformance.Mathematics.float3 Color => _ptr->color; + + public float Intensity => _ptr->intensity; + + public Misaki.HighPerformance.Mathematics.float3 LocalDirection => _ptr->local_direction; + + public ufbx_light_type Type => _ptr->type; + + public ufbx_light_decay Decay => _ptr->decay; + + public ufbx_light_area_shape AreaShape => _ptr->area_shape; + + public float InnerAngle => _ptr->inner_angle; + + public float OuterAngle => _ptr->outer_angle; + + public bool CastLight => _ptr->cast_light; + + public bool CastShadows => _ptr->cast_shadows; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_light* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/LightList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/LightList.nativegen.cs new file mode 100644 index 0000000..86f73c3 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/LightList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct LightList +{ + private readonly ufbx_light** _data; + public int Count { get; } + + internal LightList(ufbx_light** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Light this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_light** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_light** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Light Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/LineCurve.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/LineCurve.nativegen.cs new file mode 100644 index 0000000..27f6cda --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/LineCurve.nativegen.cs @@ -0,0 +1,48 @@ +namespace Ghost.Ufbx; + +public unsafe struct LineCurve +{ + private ufbx_line_curve* _ptr; + + internal LineCurve(ufbx_line_curve* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public void FreeLineCurve() + { + Api.ufbx_free_line_curve(_ptr); + } + + public void RetainLineCurve() + { + Api.ufbx_retain_line_curve(_ptr); + } + + public Misaki.HighPerformance.Mathematics.float3 Color => _ptr->color; + + public ReadOnlySpan ControlPoints => _ptr->control_points.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->control_points.data, checked((int)_ptr->control_points.count)); + + public ReadOnlySpan PointIndices => _ptr->point_indices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->point_indices.data, checked((int)_ptr->point_indices.count)); + + public ReadOnlySpan Segments => _ptr->segments.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->segments.data, checked((int)_ptr->segments.count)); + + public bool FromTessellatedNurbs => _ptr->from_tessellated_nurbs; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_line_curve* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/LineCurveList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/LineCurveList.nativegen.cs new file mode 100644 index 0000000..f5ec600 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/LineCurveList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct LineCurveList +{ + private readonly ufbx_line_curve** _data; + public int Count { get; } + + internal LineCurveList(ufbx_line_curve** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public LineCurve this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_line_curve** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_line_curve** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public LineCurve Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/LineSegment.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/LineSegment.nativegen.cs new file mode 100644 index 0000000..f7c3ef2 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/LineSegment.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct LineSegment +{ + private ufbx_line_segment* _ptr; + + internal LineSegment(ufbx_line_segment* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint IndexBegin => _ptr->index_begin; + + public uint NumIndices => _ptr->num_indices; + + internal ufbx_line_segment* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/LoadOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/LoadOpts.nativegen.cs new file mode 100644 index 0000000..a48c30a --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/LoadOpts.nativegen.cs @@ -0,0 +1,167 @@ +namespace Ghost.Ufbx; + +public unsafe partial class LoadOpts : System.IDisposable +{ + private ufbx_load_opts* _ptr; + private bool _csAlloc; + + public LoadOpts() + { + _ptr = (ufbx_load_opts*)System.Runtime.InteropServices.NativeMemory.AllocZeroed((nuint)sizeof(ufbx_load_opts)); + _csAlloc = true; + } + + internal LoadOpts(ufbx_load_opts* ptr) + { + _ptr = ptr; + _csAlloc = false; + } + + public bool IsNull => _ptr == null; + + public partial void Dispose(); + + public ufbx_allocator_opts TempAllocator { get => _ptr->temp_allocator; set => _ptr->temp_allocator = value; } + + public ufbx_allocator_opts ResultAllocator { get => _ptr->result_allocator; set => _ptr->result_allocator = value; } + + public ufbx_thread_opts ThreadOpts { get => _ptr->thread_opts; set => _ptr->thread_opts = value; } + + public bool IgnoreGeometry { get => _ptr->ignore_geometry; set => _ptr->ignore_geometry = value; } + + public bool IgnoreAnimation { get => _ptr->ignore_animation; set => _ptr->ignore_animation = value; } + + public bool IgnoreEmbedded { get => _ptr->ignore_embedded; set => _ptr->ignore_embedded = value; } + + public bool IgnoreAllContent { get => _ptr->ignore_all_content; set => _ptr->ignore_all_content = value; } + + public bool EvaluateSkinning { get => _ptr->evaluate_skinning; set => _ptr->evaluate_skinning = value; } + + public bool EvaluateCaches { get => _ptr->evaluate_caches; set => _ptr->evaluate_caches = value; } + + public bool LoadExternalFiles { get => _ptr->load_external_files; set => _ptr->load_external_files = value; } + + public bool IgnoreMissingExternalFiles { get => _ptr->ignore_missing_external_files; set => _ptr->ignore_missing_external_files = value; } + + public bool SkipSkinVertices { get => _ptr->skip_skin_vertices; set => _ptr->skip_skin_vertices = value; } + + public bool SkipMeshParts { get => _ptr->skip_mesh_parts; set => _ptr->skip_mesh_parts = value; } + + public bool CleanSkinWeights { get => _ptr->clean_skin_weights; set => _ptr->clean_skin_weights = value; } + + public bool UseBlenderPbrMaterial { get => _ptr->use_blender_pbr_material; set => _ptr->use_blender_pbr_material = value; } + + public bool DisableQuirks { get => _ptr->disable_quirks; set => _ptr->disable_quirks = value; } + + public bool Strict { get => _ptr->strict; set => _ptr->strict = value; } + + public bool ForceSingleThreadAsciiParsing { get => _ptr->force_single_thread_ascii_parsing; set => _ptr->force_single_thread_ascii_parsing = value; } + + public bool AllowUnsafe { get => _ptr->allow_unsafe; set => _ptr->allow_unsafe = value; } + + public ufbx_index_error_handling IndexErrorHandling { get => _ptr->index_error_handling; set => _ptr->index_error_handling = value; } + + public bool ConnectBrokenElements { get => _ptr->connect_broken_elements; set => _ptr->connect_broken_elements = value; } + + public bool AllowNodesOutOfRoot { get => _ptr->allow_nodes_out_of_root; set => _ptr->allow_nodes_out_of_root = value; } + + public bool AllowMissingVertexPosition { get => _ptr->allow_missing_vertex_position; set => _ptr->allow_missing_vertex_position = value; } + + public bool AllowEmptyFaces { get => _ptr->allow_empty_faces; set => _ptr->allow_empty_faces = value; } + + public bool GenerateMissingNormals { get => _ptr->generate_missing_normals; set => _ptr->generate_missing_normals = value; } + + public bool OpenMainFileWithDefault { get => _ptr->open_main_file_with_default; set => _ptr->open_main_file_with_default = value; } + + public sbyte PathSeparator { get => _ptr->path_separator; set => _ptr->path_separator = value; } + + public uint NodeDepthLimit { get => _ptr->node_depth_limit; set => _ptr->node_depth_limit = value; } + + public ulong FileSizeEstimate { get => _ptr->file_size_estimate; set => _ptr->file_size_estimate = value; } + + public nuint ReadBufferSize { get => _ptr->read_buffer_size; set => _ptr->read_buffer_size = value; } + + private cstring _filename; + public partial cstring Filename { get; set; } + + public ReadOnlySpan RawFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_filename); + + public ufbx_progress_cb ProgressCb { get => _ptr->progress_cb; set => _ptr->progress_cb = value; } + + public ulong ProgressIntervalHint { get => _ptr->progress_interval_hint; set => _ptr->progress_interval_hint = value; } + + public ufbx_open_file_cb OpenFileCb { get => _ptr->open_file_cb; set => _ptr->open_file_cb = value; } + + public ufbx_geometry_transform_handling GeometryTransformHandling { get => _ptr->geometry_transform_handling; set => _ptr->geometry_transform_handling = value; } + + public ufbx_inherit_mode_handling InheritModeHandling { get => _ptr->inherit_mode_handling; set => _ptr->inherit_mode_handling = value; } + + public ufbx_space_conversion SpaceConversion { get => _ptr->space_conversion; set => _ptr->space_conversion = value; } + + public ufbx_pivot_handling PivotHandling { get => _ptr->pivot_handling; set => _ptr->pivot_handling = value; } + + public bool PivotHandlingRetainEmpties { get => _ptr->pivot_handling_retain_empties; set => _ptr->pivot_handling_retain_empties = value; } + + public ufbx_mirror_axis HandednessConversionAxis { get => _ptr->handedness_conversion_axis; set => _ptr->handedness_conversion_axis = value; } + + public bool HandednessConversionRetainWinding { get => _ptr->handedness_conversion_retain_winding; set => _ptr->handedness_conversion_retain_winding = value; } + + public bool ReverseWinding { get => _ptr->reverse_winding; set => _ptr->reverse_winding = value; } + + public ufbx_coordinate_axes TargetAxes { get => _ptr->target_axes; set => _ptr->target_axes = value; } + + public float TargetUnitMeters { get => _ptr->target_unit_meters; set => _ptr->target_unit_meters = value; } + + public ufbx_coordinate_axes TargetCameraAxes { get => _ptr->target_camera_axes; set => _ptr->target_camera_axes = value; } + + public ufbx_coordinate_axes TargetLightAxes { get => _ptr->target_light_axes; set => _ptr->target_light_axes = value; } + + public ReadOnlySpan GeometryTransformHelperNameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->geometry_transform_helper_name); + public string GeometryTransformHelperName => NativeWrapperHelpers.GetString(_ptr->geometry_transform_helper_name); + + public ReadOnlySpan ScaleHelperNameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->scale_helper_name); + public string ScaleHelperName => NativeWrapperHelpers.GetString(_ptr->scale_helper_name); + + public bool NormalizeNormals { get => _ptr->normalize_normals; set => _ptr->normalize_normals = value; } + + public bool NormalizeTangents { get => _ptr->normalize_tangents; set => _ptr->normalize_tangents = value; } + + public bool UseRootTransform { get => _ptr->use_root_transform; set => _ptr->use_root_transform = value; } + + public ufbx_transform RootTransform { get => _ptr->root_transform; set => _ptr->root_transform = value; } + + public double KeyClampThreshold { get => _ptr->key_clamp_threshold; set => _ptr->key_clamp_threshold = value; } + + public ufbx_unicode_error_handling UnicodeErrorHandling { get => _ptr->unicode_error_handling; set => _ptr->unicode_error_handling = value; } + + public bool RetainVertexAttribW { get => _ptr->retain_vertex_attrib_w; set => _ptr->retain_vertex_attrib_w = value; } + + public bool RetainDom { get => _ptr->retain_dom; set => _ptr->retain_dom = value; } + + public ufbx_file_format FileFormat { get => _ptr->file_format; set => _ptr->file_format = value; } + + public nuint FileFormatLookahead { get => _ptr->file_format_lookahead; set => _ptr->file_format_lookahead = value; } + + public bool NoFormatFromContent { get => _ptr->no_format_from_content; set => _ptr->no_format_from_content = value; } + + public bool NoFormatFromExtension { get => _ptr->no_format_from_extension; set => _ptr->no_format_from_extension = value; } + + public bool ObjSearchMtlByFilename { get => _ptr->obj_search_mtl_by_filename; set => _ptr->obj_search_mtl_by_filename = value; } + + public bool ObjMergeObjects { get => _ptr->obj_merge_objects; set => _ptr->obj_merge_objects = value; } + + public bool ObjMergeGroups { get => _ptr->obj_merge_groups; set => _ptr->obj_merge_groups = value; } + + public bool ObjSplitGroups { get => _ptr->obj_split_groups; set => _ptr->obj_split_groups = value; } + + private cstring _objMtlPath; + public partial cstring ObjMtlPath { get; set; } + + public ReadOnlySpan ObjMtlData => NativeWrapperHelpers.AsSpan(_ptr->obj_mtl_data); + + public float ObjUnitMeters { get => _ptr->obj_unit_meters; set => _ptr->obj_unit_meters = value; } + + public ufbx_coordinate_axes ObjAxes { get => _ptr->obj_axes; set => _ptr->obj_axes = value; } + + internal ufbx_load_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/LodGroup.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/LodGroup.nativegen.cs new file mode 100644 index 0000000..4a6ced9 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/LodGroup.nativegen.cs @@ -0,0 +1,40 @@ +namespace Ghost.Ufbx; + +public unsafe struct LodGroup +{ + private ufbx_lod_group* _ptr; + + internal LodGroup(ufbx_lod_group* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool RelativeDistances => _ptr->relative_distances; + + public ReadOnlySpan LodLevels => _ptr->lod_levels.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->lod_levels.data, checked((int)_ptr->lod_levels.count)); + + public bool IgnoreParentTransform => _ptr->ignore_parent_transform; + + public bool UseDistanceLimit => _ptr->use_distance_limit; + + public float DistanceLimitMin => _ptr->distance_limit_min; + + public float DistanceLimitMax => _ptr->distance_limit_max; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_lod_group* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/LodGroupList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/LodGroupList.nativegen.cs new file mode 100644 index 0000000..0ccb9db --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/LodGroupList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct LodGroupList +{ + private readonly ufbx_lod_group** _data; + public int Count { get; } + + internal LodGroupList(ufbx_lod_group** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public LodGroup this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_lod_group** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_lod_group** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public LodGroup Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/LodLevel.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/LodLevel.nativegen.cs new file mode 100644 index 0000000..d2f1bdb --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/LodLevel.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct LodLevel +{ + private ufbx_lod_level* _ptr; + + internal LodLevel(ufbx_lod_level* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public float Distance => _ptr->distance; + + public ufbx_lod_display Display => _ptr->display; + + internal ufbx_lod_level* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Marker.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Marker.nativegen.cs new file mode 100644 index 0000000..9ce4c30 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Marker.nativegen.cs @@ -0,0 +1,30 @@ +namespace Ghost.Ufbx; + +public unsafe struct Marker +{ + private ufbx_marker* _ptr; + + internal Marker(ufbx_marker* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_marker_type Type => _ptr->type; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_marker* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MarkerList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MarkerList.nativegen.cs new file mode 100644 index 0000000..b34eb76 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MarkerList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct MarkerList +{ + private readonly ufbx_marker** _data; + public int Count { get; } + + internal MarkerList(ufbx_marker** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Marker this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_marker** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_marker** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Marker Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Material.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Material.nativegen.cs new file mode 100644 index 0000000..abaa1ac --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Material.nativegen.cs @@ -0,0 +1,55 @@ +namespace Ghost.Ufbx; + +public unsafe ref struct Material +{ + private ufbx_material* _ptr; + + internal Material(ufbx_material* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Texture FindPropTextureLen(sbyte* name, nuint nameLen) + { + return new(Api.ufbx_find_prop_texture_len(_ptr, name, nameLen)); + } + + public Texture FindPropTexture(sbyte* name) + { + return new(Api.ufbx_find_prop_texture(_ptr, name)); + } + + public MaterialFbxMaps Fbx => new((ufbx_material_fbx_maps*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->fbx)); + + public MaterialPbrMaps Pbr => new((ufbx_material_pbr_maps*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->pbr)); + + public MaterialFeatures Features => new((ufbx_material_features*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->features)); + + public ufbx_shader_type ShaderType => _ptr->shader_type; + + public bool HasShader => _ptr->shader != null; + public Shader Shader => _ptr->shader != null ? new(_ptr->shader) : throw new InvalidOperationException("Shader is null."); + + public ReadOnlySpan ShadingModelNameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->shading_model_name); + public string ShadingModelName => NativeWrapperHelpers.GetString(_ptr->shading_model_name); + + public ReadOnlySpan ShaderPropPrefixBytes => NativeWrapperHelpers.AsByteSpan(_ptr->shader_prop_prefix); + public string ShaderPropPrefix => NativeWrapperHelpers.GetString(_ptr->shader_prop_prefix); + + public ReadOnlySpan Textures => _ptr->textures.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->textures.data, checked((int)_ptr->textures.count)); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_material* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFbxMaps.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFbxMaps.nativegen.cs new file mode 100644 index 0000000..995ce8c --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFbxMaps.nativegen.cs @@ -0,0 +1,55 @@ +namespace Ghost.Ufbx; + +public unsafe struct MaterialFbxMaps +{ + private ufbx_material_fbx_maps* _ptr; + + internal MaterialFbxMaps(ufbx_material_fbx_maps* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public MaterialMap DiffuseFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->diffuse_factor)); + + public MaterialMap DiffuseColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->diffuse_color)); + + public MaterialMap SpecularFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->specular_factor)); + + public MaterialMap SpecularColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->specular_color)); + + public MaterialMap SpecularExponent => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->specular_exponent)); + + public MaterialMap ReflectionFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->reflection_factor)); + + public MaterialMap ReflectionColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->reflection_color)); + + public MaterialMap TransparencyFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transparency_factor)); + + public MaterialMap TransparencyColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transparency_color)); + + public MaterialMap EmissionFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->emission_factor)); + + public MaterialMap EmissionColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->emission_color)); + + public MaterialMap AmbientFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->ambient_factor)); + + public MaterialMap AmbientColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->ambient_color)); + + public MaterialMap NormalMap => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->normal_map)); + + public MaterialMap Bump => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->bump)); + + public MaterialMap BumpFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->bump_factor)); + + public MaterialMap DisplacementFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->displacement_factor)); + + public MaterialMap Displacement => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->displacement)); + + public MaterialMap VectorDisplacementFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vector_displacement_factor)); + + public MaterialMap VectorDisplacement => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vector_displacement)); + + internal ufbx_material_fbx_maps* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFeatureInfo.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFeatureInfo.nativegen.cs new file mode 100644 index 0000000..0cce45b --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFeatureInfo.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct MaterialFeatureInfo +{ + private ufbx_material_feature_info* _ptr; + + internal MaterialFeatureInfo(ufbx_material_feature_info* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool Enabled => _ptr->enabled; + + public bool IsExplicit => _ptr->is_explicit; + + internal ufbx_material_feature_info* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFeatures.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFeatures.nativegen.cs new file mode 100644 index 0000000..f08cb6c --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialFeatures.nativegen.cs @@ -0,0 +1,61 @@ +namespace Ghost.Ufbx; + +public unsafe struct MaterialFeatures +{ + private ufbx_material_features* _ptr; + + internal MaterialFeatures(ufbx_material_features* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public MaterialFeatureInfo Pbr => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->pbr)); + + public MaterialFeatureInfo Metalness => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->metalness)); + + public MaterialFeatureInfo Diffuse => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->diffuse)); + + public MaterialFeatureInfo Specular => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->specular)); + + public MaterialFeatureInfo Emission => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->emission)); + + public MaterialFeatureInfo Transmission => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission)); + + public MaterialFeatureInfo Coat => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat)); + + public MaterialFeatureInfo Sheen => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->sheen)); + + public MaterialFeatureInfo Opacity => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->opacity)); + + public MaterialFeatureInfo AmbientOcclusion => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->ambient_occlusion)); + + public MaterialFeatureInfo Matte => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->matte)); + + public MaterialFeatureInfo Unlit => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->unlit)); + + public MaterialFeatureInfo Ior => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->ior)); + + public MaterialFeatureInfo DiffuseRoughness => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->diffuse_roughness)); + + public MaterialFeatureInfo TransmissionRoughness => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_roughness)); + + public MaterialFeatureInfo ThinWalled => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->thin_walled)); + + public MaterialFeatureInfo Caustics => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->caustics)); + + public MaterialFeatureInfo ExitToBackground => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->exit_to_background)); + + public MaterialFeatureInfo InternalReflections => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->internal_reflections)); + + public MaterialFeatureInfo DoubleSided => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->double_sided)); + + public MaterialFeatureInfo RoughnessAsGlossiness => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->roughness_as_glossiness)); + + public MaterialFeatureInfo CoatRoughnessAsGlossiness => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_roughness_as_glossiness)); + + public MaterialFeatureInfo TransmissionRoughnessAsGlossiness => new((ufbx_material_feature_info*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_roughness_as_glossiness)); + + internal ufbx_material_features* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialList.nativegen.cs new file mode 100644 index 0000000..ef01070 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct MaterialList +{ + private readonly ufbx_material** _data; + public int Count { get; } + + internal MaterialList(ufbx_material** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Material this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_material** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_material** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Material Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialMap.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialMap.nativegen.cs new file mode 100644 index 0000000..5871e7b --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialMap.nativegen.cs @@ -0,0 +1,36 @@ +namespace Ghost.Ufbx; + +public unsafe struct MaterialMap +{ + private ufbx_material_map* _ptr; + + internal MaterialMap(ufbx_material_map* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public long ValueInt => _ptr->value_int; + + public bool HasTexture => _ptr->texture != null; + public Texture Texture => _ptr->texture != null ? new(_ptr->texture) : throw new InvalidOperationException("Texture is null."); + + public bool HasValue => _ptr->has_value; + + public bool TextureEnabled => _ptr->texture_enabled; + + public bool FeatureDisabled => _ptr->feature_disabled; + + public byte ValueComponents => _ptr->value_components; + + public float ValueReal => _ptr->value_real; + + public Misaki.HighPerformance.Mathematics.float2 ValueVec2 => _ptr->value_vec2; + + public Misaki.HighPerformance.Mathematics.float3 ValueVec3 => _ptr->value_vec3; + + public Misaki.HighPerformance.Mathematics.float4 ValueVec4 => _ptr->value_vec4; + + internal ufbx_material_map* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialPbrMaps.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialPbrMaps.nativegen.cs new file mode 100644 index 0000000..c179f41 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialPbrMaps.nativegen.cs @@ -0,0 +1,127 @@ +namespace Ghost.Ufbx; + +public unsafe struct MaterialPbrMaps +{ + private ufbx_material_pbr_maps* _ptr; + + internal MaterialPbrMaps(ufbx_material_pbr_maps* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public MaterialMap BaseFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->base_factor)); + + public MaterialMap BaseColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->base_color)); + + public MaterialMap Roughness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->roughness)); + + public MaterialMap Metalness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->metalness)); + + public MaterialMap DiffuseRoughness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->diffuse_roughness)); + + public MaterialMap SpecularFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->specular_factor)); + + public MaterialMap SpecularColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->specular_color)); + + public MaterialMap SpecularIor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->specular_ior)); + + public MaterialMap SpecularAnisotropy => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->specular_anisotropy)); + + public MaterialMap SpecularRotation => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->specular_rotation)); + + public MaterialMap TransmissionFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_factor)); + + public MaterialMap TransmissionColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_color)); + + public MaterialMap TransmissionDepth => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_depth)); + + public MaterialMap TransmissionScatter => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_scatter)); + + public MaterialMap TransmissionScatterAnisotropy => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_scatter_anisotropy)); + + public MaterialMap TransmissionDispersion => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_dispersion)); + + public MaterialMap TransmissionRoughness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_roughness)); + + public MaterialMap TransmissionExtraRoughness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_extra_roughness)); + + public MaterialMap TransmissionPriority => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_priority)); + + public MaterialMap TransmissionEnableInAov => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_enable_in_aov)); + + public MaterialMap SubsurfaceFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->subsurface_factor)); + + public MaterialMap SubsurfaceColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->subsurface_color)); + + public MaterialMap SubsurfaceRadius => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->subsurface_radius)); + + public MaterialMap SubsurfaceScale => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->subsurface_scale)); + + public MaterialMap SubsurfaceAnisotropy => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->subsurface_anisotropy)); + + public MaterialMap SubsurfaceTintColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->subsurface_tint_color)); + + public MaterialMap SubsurfaceType => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->subsurface_type)); + + public MaterialMap SheenFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->sheen_factor)); + + public MaterialMap SheenColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->sheen_color)); + + public MaterialMap SheenRoughness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->sheen_roughness)); + + public MaterialMap CoatFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_factor)); + + public MaterialMap CoatColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_color)); + + public MaterialMap CoatRoughness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_roughness)); + + public MaterialMap CoatIor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_ior)); + + public MaterialMap CoatAnisotropy => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_anisotropy)); + + public MaterialMap CoatRotation => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_rotation)); + + public MaterialMap CoatNormal => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_normal)); + + public MaterialMap CoatAffectBaseColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_affect_base_color)); + + public MaterialMap CoatAffectBaseRoughness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_affect_base_roughness)); + + public MaterialMap ThinFilmFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->thin_film_factor)); + + public MaterialMap ThinFilmThickness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->thin_film_thickness)); + + public MaterialMap ThinFilmIor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->thin_film_ior)); + + public MaterialMap EmissionFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->emission_factor)); + + public MaterialMap EmissionColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->emission_color)); + + public MaterialMap Opacity => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->opacity)); + + public MaterialMap IndirectDiffuse => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->indirect_diffuse)); + + public MaterialMap IndirectSpecular => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->indirect_specular)); + + public MaterialMap NormalMap => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->normal_map)); + + public MaterialMap TangentMap => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->tangent_map)); + + public MaterialMap DisplacementMap => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->displacement_map)); + + public MaterialMap MatteFactor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->matte_factor)); + + public MaterialMap MatteColor => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->matte_color)); + + public MaterialMap AmbientOcclusion => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->ambient_occlusion)); + + public MaterialMap Glossiness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->glossiness)); + + public MaterialMap CoatGlossiness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->coat_glossiness)); + + public MaterialMap TransmissionGlossiness => new((ufbx_material_map*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transmission_glossiness)); + + internal ufbx_material_pbr_maps* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialTexture.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialTexture.nativegen.cs new file mode 100644 index 0000000..16c6371 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MaterialTexture.nativegen.cs @@ -0,0 +1,24 @@ +namespace Ghost.Ufbx; + +public unsafe struct MaterialTexture +{ + private ufbx_material_texture* _ptr; + + internal MaterialTexture(ufbx_material_texture* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan MaterialPropBytes => NativeWrapperHelpers.AsByteSpan(_ptr->material_prop); + public string MaterialProp => NativeWrapperHelpers.GetString(_ptr->material_prop); + + public ReadOnlySpan ShaderPropBytes => NativeWrapperHelpers.AsByteSpan(_ptr->shader_prop); + public string ShaderProp => NativeWrapperHelpers.GetString(_ptr->shader_prop); + + public bool HasTexture => _ptr->texture != null; + public Texture Texture => _ptr->texture != null ? new(_ptr->texture) : throw new InvalidOperationException("Texture is null."); + + internal ufbx_material_texture* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Matrix.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Matrix.nativegen.cs new file mode 100644 index 0000000..4cc5e8f --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Matrix.nativegen.cs @@ -0,0 +1,39 @@ +namespace Ghost.Ufbx; + +public unsafe struct Matrix +{ + private ufbx_matrix* _ptr; + + internal Matrix(ufbx_matrix* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public float M00 => _ptr->m00; + + public float M10 => _ptr->m10; + + public float M20 => _ptr->m20; + + public float M01 => _ptr->m01; + + public float M11 => _ptr->m11; + + public float M21 => _ptr->m21; + + public float M02 => _ptr->m02; + + public float M12 => _ptr->m12; + + public float M22 => _ptr->m22; + + public float M03 => _ptr->m03; + + public float M13 => _ptr->m13; + + public float M23 => _ptr->m23; + + internal ufbx_matrix* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Mesh.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Mesh.nativegen.cs new file mode 100644 index 0000000..e1f13ce --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Mesh.nativegen.cs @@ -0,0 +1,168 @@ +namespace Ghost.Ufbx; + +public unsafe ref struct Mesh +{ + private ufbx_mesh* _ptr; + + internal Mesh(ufbx_mesh* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint FindFaceIndex(nuint index) + { + return Api.ufbx_find_face_index(_ptr, index); + } + + public void ComputeTopology(TopoEdge topo, nuint numTopo) + { + Api.ufbx_compute_topology(_ptr, topo.GetUnsafePtr(), numTopo); + } + + public nuint GenerateNormalMapping(TopoEdge topo, nuint numTopo, uint* normalIndices, nuint numNormalIndices, bool assumeSmooth) + { + return Api.ufbx_generate_normal_mapping(_ptr, topo.GetUnsafePtr(), numTopo, normalIndices, numNormalIndices, assumeSmooth); + } + + public void ComputeNormals(VertexVec3 positions, uint* normalIndices, nuint numNormalIndices, Misaki.HighPerformance.Mathematics.float3* normals, nuint numNormals) + { + Api.ufbx_compute_normals(_ptr, positions.GetUnsafePtr(), normalIndices, numNormalIndices, normals, numNormals); + } + + public Mesh SubdivideMesh(nuint level, SubdivideOpts opts, Error error) + { + return new(Api.ufbx_subdivide_mesh(_ptr, level, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public void FreeMesh() + { + Api.ufbx_free_mesh(_ptr); + } + + public void RetainMesh() + { + Api.ufbx_retain_mesh(_ptr); + } + + public nuint NumVertices => _ptr->num_vertices; + + public nuint NumIndices => _ptr->num_indices; + + public nuint NumFaces => _ptr->num_faces; + + public nuint NumTriangles => _ptr->num_triangles; + + public nuint NumEdges => _ptr->num_edges; + + public nuint MaxFaceTriangles => _ptr->max_face_triangles; + + public nuint NumEmptyFaces => _ptr->num_empty_faces; + + public nuint NumPointFaces => _ptr->num_point_faces; + + public nuint NumLineFaces => _ptr->num_line_faces; + + public ReadOnlySpan Faces => _ptr->faces.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->faces.data, checked((int)_ptr->faces.count)); + + public ReadOnlySpan FaceSmoothing => _ptr->face_smoothing.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->face_smoothing.data, checked((int)_ptr->face_smoothing.count)); + + public ReadOnlySpan FaceMaterial => _ptr->face_material.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->face_material.data, checked((int)_ptr->face_material.count)); + + public ReadOnlySpan FaceGroup => _ptr->face_group.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->face_group.data, checked((int)_ptr->face_group.count)); + + public ReadOnlySpan FaceHole => _ptr->face_hole.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->face_hole.data, checked((int)_ptr->face_hole.count)); + + public ReadOnlySpan Edges => _ptr->edges.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->edges.data, checked((int)_ptr->edges.count)); + + public ReadOnlySpan EdgeSmoothing => _ptr->edge_smoothing.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->edge_smoothing.data, checked((int)_ptr->edge_smoothing.count)); + + public ReadOnlySpan EdgeCrease => _ptr->edge_crease.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->edge_crease.data, checked((int)_ptr->edge_crease.count)); + + public ReadOnlySpan EdgeVisibility => _ptr->edge_visibility.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->edge_visibility.data, checked((int)_ptr->edge_visibility.count)); + + public ReadOnlySpan VertexIndices => _ptr->vertex_indices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->vertex_indices.data, checked((int)_ptr->vertex_indices.count)); + + public ReadOnlySpan Vertices => _ptr->vertices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->vertices.data, checked((int)_ptr->vertices.count)); + + public ReadOnlySpan VertexFirstIndex => _ptr->vertex_first_index.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->vertex_first_index.data, checked((int)_ptr->vertex_first_index.count)); + + public VertexVec3 VertexPosition => new((ufbx_vertex_vec3*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_position)); + + public VertexVec3 VertexNormal => new((ufbx_vertex_vec3*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_normal)); + + public VertexVec2 VertexUv => new((ufbx_vertex_vec2*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_uv)); + + public VertexVec3 VertexTangent => new((ufbx_vertex_vec3*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_tangent)); + + public VertexVec3 VertexBitangent => new((ufbx_vertex_vec3*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_bitangent)); + + public VertexVec4 VertexColor => new((ufbx_vertex_vec4*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_color)); + + public VertexReal VertexCrease => new((ufbx_vertex_real*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_crease)); + + public ReadOnlySpan UvSets => _ptr->uv_sets.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->uv_sets.data, checked((int)_ptr->uv_sets.count)); + + public ReadOnlySpan ColorSets => _ptr->color_sets.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->color_sets.data, checked((int)_ptr->color_sets.count)); + + public MaterialList Materials => new(_ptr->materials.data, _ptr->materials.count); + + public ReadOnlySpan FaceGroups => _ptr->face_groups.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->face_groups.data, checked((int)_ptr->face_groups.count)); + + public ReadOnlySpan MaterialParts => _ptr->material_parts.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->material_parts.data, checked((int)_ptr->material_parts.count)); + + public ReadOnlySpan FaceGroupParts => _ptr->face_group_parts.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->face_group_parts.data, checked((int)_ptr->face_group_parts.count)); + + public ReadOnlySpan MaterialPartUsageOrder => _ptr->material_part_usage_order.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->material_part_usage_order.data, checked((int)_ptr->material_part_usage_order.count)); + + public bool SkinnedIsLocal => _ptr->skinned_is_local; + + public VertexVec3 SkinnedPosition => new((ufbx_vertex_vec3*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->skinned_position)); + + public VertexVec3 SkinnedNormal => new((ufbx_vertex_vec3*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->skinned_normal)); + + public SkinDeformerList SkinDeformers => new(_ptr->skin_deformers.data, _ptr->skin_deformers.count); + + public BlendDeformerList BlendDeformers => new(_ptr->blend_deformers.data, _ptr->blend_deformers.count); + + public CacheDeformerList CacheDeformers => new(_ptr->cache_deformers.data, _ptr->cache_deformers.count); + + public ElementList AllDeformers => new(_ptr->all_deformers.data, _ptr->all_deformers.count); + + public uint SubdivisionPreviewLevels => _ptr->subdivision_preview_levels; + + public uint SubdivisionRenderLevels => _ptr->subdivision_render_levels; + + public ufbx_subdivision_display_mode SubdivisionDisplayMode => _ptr->subdivision_display_mode; + + public ufbx_subdivision_boundary SubdivisionBoundary => _ptr->subdivision_boundary; + + public ufbx_subdivision_boundary SubdivisionUvBoundary => _ptr->subdivision_uv_boundary; + + public bool ReversedWinding => _ptr->reversed_winding; + + public bool GeneratedNormals => _ptr->generated_normals; + + public bool SubdivisionEvaluated => _ptr->subdivision_evaluated; + + public bool HasSubdivisionResult => _ptr->subdivision_result != null; + public SubdivisionResult SubdivisionResult => _ptr->subdivision_result != null ? new(_ptr->subdivision_result) : throw new InvalidOperationException("SubdivisionResult is null."); + + public bool FromTessellatedNurbs => _ptr->from_tessellated_nurbs; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_mesh* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MeshList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MeshList.nativegen.cs new file mode 100644 index 0000000..4dfbe33 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MeshList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct MeshList +{ + private readonly ufbx_mesh** _data; + public int Count { get; } + + internal MeshList(ufbx_mesh** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Mesh this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_mesh** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_mesh** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Mesh Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MeshPart.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MeshPart.nativegen.cs new file mode 100644 index 0000000..ccc4d32 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MeshPart.nativegen.cs @@ -0,0 +1,29 @@ +namespace Ghost.Ufbx; + +public unsafe struct MeshPart +{ + private ufbx_mesh_part* _ptr; + + internal MeshPart(ufbx_mesh_part* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint Index => _ptr->index; + + public nuint NumFaces => _ptr->num_faces; + + public nuint NumTriangles => _ptr->num_triangles; + + public nuint NumEmptyFaces => _ptr->num_empty_faces; + + public nuint NumPointFaces => _ptr->num_point_faces; + + public nuint NumLineFaces => _ptr->num_line_faces; + + public ReadOnlySpan FaceIndices => _ptr->face_indices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->face_indices.data, checked((int)_ptr->face_indices.count)); + + internal ufbx_mesh_part* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Metadata.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Metadata.nativegen.cs new file mode 100644 index 0000000..453895b --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Metadata.nativegen.cs @@ -0,0 +1,109 @@ +namespace Ghost.Ufbx; + +public unsafe struct Metadata +{ + private ufbx_metadata* _ptr; + + internal Metadata(ufbx_metadata* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan Warnings => _ptr->warnings.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->warnings.data, checked((int)_ptr->warnings.count)); + + public bool Ascii => _ptr->ascii; + + public uint Version => _ptr->version; + + public ufbx_file_format FileFormat => _ptr->file_format; + + public bool MayContainNoIndex => _ptr->may_contain_no_index; + + public bool MayContainMissingVertexPosition => _ptr->may_contain_missing_vertex_position; + + public bool MayContainBrokenElements => _ptr->may_contain_broken_elements; + + public bool IsUnsafe => _ptr->is_unsafe; + + public ReadOnlySpan CreatorBytes => NativeWrapperHelpers.AsByteSpan(_ptr->creator); + public string Creator => NativeWrapperHelpers.GetString(_ptr->creator); + + public bool BigEndian => _ptr->big_endian; + + public ReadOnlySpan FilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->filename); + public string Filename => NativeWrapperHelpers.GetString(_ptr->filename); + + public ReadOnlySpan RelativeRootBytes => NativeWrapperHelpers.AsByteSpan(_ptr->relative_root); + public string RelativeRoot => NativeWrapperHelpers.GetString(_ptr->relative_root); + + public ReadOnlySpan RawFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_filename); + + public ReadOnlySpan RawRelativeRoot => NativeWrapperHelpers.AsSpan(_ptr->raw_relative_root); + + public ufbx_exporter Exporter => _ptr->exporter; + + public uint ExporterVersion => _ptr->exporter_version; + + public Props SceneProps => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->scene_props)); + + public Application OriginalApplication => new((ufbx_application*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->original_application)); + + public Application LatestApplication => new((ufbx_application*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->latest_application)); + + public Thumbnail Thumbnail => new((ufbx_thumbnail*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->thumbnail)); + + public bool GeometryIgnored => _ptr->geometry_ignored; + + public bool AnimationIgnored => _ptr->animation_ignored; + + public bool EmbeddedIgnored => _ptr->embedded_ignored; + + public nuint MaxFaceTriangles => _ptr->max_face_triangles; + + public nuint ResultMemoryUsed => _ptr->result_memory_used; + + public nuint TempMemoryUsed => _ptr->temp_memory_used; + + public nuint ResultAllocs => _ptr->result_allocs; + + public nuint TempAllocs => _ptr->temp_allocs; + + public nuint ElementBufferSize => _ptr->element_buffer_size; + + public nuint NumShaderTextures => _ptr->num_shader_textures; + + public float BonePropSizeUnit => _ptr->bone_prop_size_unit; + + public bool BonePropLimbLengthRelative => _ptr->bone_prop_limb_length_relative; + + public float OrthoSizeUnit => _ptr->ortho_size_unit; + + public long KtimeSecond => _ptr->ktime_second; + + public ReadOnlySpan OriginalFilePathBytes => NativeWrapperHelpers.AsByteSpan(_ptr->original_file_path); + public string OriginalFilePath => NativeWrapperHelpers.GetString(_ptr->original_file_path); + + public ReadOnlySpan RawOriginalFilePath => NativeWrapperHelpers.AsSpan(_ptr->raw_original_file_path); + + public ufbx_space_conversion SpaceConversion => _ptr->space_conversion; + + public ufbx_geometry_transform_handling GeometryTransformHandling => _ptr->geometry_transform_handling; + + public ufbx_inherit_mode_handling InheritModeHandling => _ptr->inherit_mode_handling; + + public ufbx_pivot_handling PivotHandling => _ptr->pivot_handling; + + public ufbx_mirror_axis HandednessConversionAxis => _ptr->handedness_conversion_axis; + + public Misaki.HighPerformance.Mathematics.quaternion RootRotation => _ptr->root_rotation; + + public float RootScale => _ptr->root_scale; + + public ufbx_mirror_axis MirrorAxis => _ptr->mirror_axis; + + public float GeometryScale => _ptr->geometry_scale; + + internal ufbx_metadata* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MetadataObject.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MetadataObject.nativegen.cs new file mode 100644 index 0000000..461d2cb --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MetadataObject.nativegen.cs @@ -0,0 +1,26 @@ +namespace Ghost.Ufbx; + +public unsafe struct MetadataObject +{ + private ufbx_metadata_object* _ptr; + + internal MetadataObject(ufbx_metadata_object* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_metadata_object* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/MetadataObjectList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/MetadataObjectList.nativegen.cs new file mode 100644 index 0000000..3a41bac --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/MetadataObjectList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct MetadataObjectList +{ + private readonly ufbx_metadata_object** _data; + public int Count { get; } + + internal MetadataObjectList(ufbx_metadata_object** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public MetadataObject this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_metadata_object** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_metadata_object** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public MetadataObject Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NameElement.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NameElement.nativegen.cs new file mode 100644 index 0000000..1088355 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NameElement.nativegen.cs @@ -0,0 +1,23 @@ +namespace Ghost.Ufbx; + +public unsafe struct NameElement +{ + private ufbx_name_element* _ptr; + + internal NameElement(ufbx_name_element* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public ufbx_element_type Type => _ptr->type; + + public bool HasElement => _ptr->element != null; + public Element Element => _ptr->element != null ? new(_ptr->element) : throw new InvalidOperationException("Element is null."); + + internal ufbx_name_element* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NativeWrapperHelpers.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NativeWrapperHelpers.nativegen.cs new file mode 100644 index 0000000..969d959 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NativeWrapperHelpers.nativegen.cs @@ -0,0 +1,45 @@ +using System.Text; + +namespace Ghost.Ufbx; + +internal static unsafe class NativeWrapperHelpers +{ + public static ReadOnlySpan AsByteSpan(ufbx_string value) + { + if (value.data == null || value.length == 0) + { + return ReadOnlySpan.Empty; + } + + return new ReadOnlySpan((byte*)value.data, checked((int)value.length) * 1); + } + + public static string GetString(ufbx_string value) + { + var bytes = AsByteSpan(value); + if (bytes.IsEmpty) + { + return string.Empty; + } + + return Encoding.UTF8.GetString(bytes); + } + + public static ReadOnlySpan AsSpan(ufbx_blob value) + { + if (value.data == null || value.size == 0) + { + return ReadOnlySpan.Empty; + } + + return new ReadOnlySpan(value.data, checked((int)value.size)); + } + + public static void ThrowIfOutOfRange(int index, int count) + { + if ((uint)index >= (uint)count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Node.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Node.nativegen.cs new file mode 100644 index 0000000..e687e1d --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Node.nativegen.cs @@ -0,0 +1,125 @@ +namespace Ghost.Ufbx; + +public unsafe ref struct Node +{ + private ufbx_node* _ptr; + + internal Node(ufbx_node* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Misaki.HighPerformance.Mathematics.float3x4 GetCompatibleMatrixForNormals() + { + return Api.ufbx_get_compatible_matrix_for_normals(_ptr); + } + + public bool HasParent => _ptr->parent != null; + public Node Parent => _ptr->parent != null ? new(_ptr->parent) : throw new InvalidOperationException("Parent is null."); + + public NodeList Children => new(_ptr->children.data, _ptr->children.count); + + public bool HasMesh => _ptr->mesh != null; + public Mesh Mesh => _ptr->mesh != null ? new(_ptr->mesh) : throw new InvalidOperationException("Mesh is null."); + + public bool HasLight => _ptr->light != null; + public Light Light => _ptr->light != null ? new(_ptr->light) : throw new InvalidOperationException("Light is null."); + + public bool HasCamera => _ptr->camera != null; + public Camera Camera => _ptr->camera != null ? new(_ptr->camera) : throw new InvalidOperationException("Camera is null."); + + public bool HasBone => _ptr->bone != null; + public Bone Bone => _ptr->bone != null ? new(_ptr->bone) : throw new InvalidOperationException("Bone is null."); + + public bool HasAttrib => _ptr->attrib != null; + public Element Attrib => _ptr->attrib != null ? new(_ptr->attrib) : throw new InvalidOperationException("Attrib is null."); + + public bool HasGeometryTransformHelper => _ptr->geometry_transform_helper != null; + public Node GeometryTransformHelper => _ptr->geometry_transform_helper != null ? new(_ptr->geometry_transform_helper) : throw new InvalidOperationException("GeometryTransformHelper is null."); + + public bool HasScaleHelper => _ptr->scale_helper != null; + public Node ScaleHelper => _ptr->scale_helper != null ? new(_ptr->scale_helper) : throw new InvalidOperationException("ScaleHelper is null."); + + public ufbx_element_type AttribType => _ptr->attrib_type; + + public ElementList AllAttribs => new(_ptr->all_attribs.data, _ptr->all_attribs.count); + + public ufbx_inherit_mode InheritMode => _ptr->inherit_mode; + + public ufbx_inherit_mode OriginalInheritMode => _ptr->original_inherit_mode; + + public Transform LocalTransform => new((ufbx_transform*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->local_transform)); + + public Transform GeometryTransform => new((ufbx_transform*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->geometry_transform)); + + public Misaki.HighPerformance.Mathematics.float3 InheritScale => _ptr->inherit_scale; + + public bool HasInheritScaleNode => _ptr->inherit_scale_node != null; + public Node InheritScaleNode => _ptr->inherit_scale_node != null ? new(_ptr->inherit_scale_node) : throw new InvalidOperationException("InheritScaleNode is null."); + + public ufbx_rotation_order RotationOrder => _ptr->rotation_order; + + public Misaki.HighPerformance.Mathematics.float3 EulerRotation => _ptr->euler_rotation; + + public Misaki.HighPerformance.Mathematics.float3x4 NodeToParent => _ptr->node_to_parent; + + public Misaki.HighPerformance.Mathematics.float3x4 NodeToWorld => _ptr->node_to_world; + + public Misaki.HighPerformance.Mathematics.float3x4 GeometryToNode => _ptr->geometry_to_node; + + public Misaki.HighPerformance.Mathematics.float3x4 GeometryToWorld => _ptr->geometry_to_world; + + public Misaki.HighPerformance.Mathematics.float3x4 UnscaledNodeToWorld => _ptr->unscaled_node_to_world; + + public Misaki.HighPerformance.Mathematics.float3 AdjustPreTranslation => _ptr->adjust_pre_translation; + + public Misaki.HighPerformance.Mathematics.quaternion AdjustPreRotation => _ptr->adjust_pre_rotation; + + public float AdjustPreScale => _ptr->adjust_pre_scale; + + public Misaki.HighPerformance.Mathematics.quaternion AdjustPostRotation => _ptr->adjust_post_rotation; + + public float AdjustPostScale => _ptr->adjust_post_scale; + + public float AdjustTranslationScale => _ptr->adjust_translation_scale; + + public ufbx_mirror_axis AdjustMirrorAxis => _ptr->adjust_mirror_axis; + + public MaterialList Materials => new(_ptr->materials.data, _ptr->materials.count); + + public bool HasBindPose => _ptr->bind_pose != null; + public Pose BindPose => _ptr->bind_pose != null ? new(_ptr->bind_pose) : throw new InvalidOperationException("BindPose is null."); + + public bool Visible => _ptr->visible; + + public bool IsRoot => _ptr->is_root; + + public bool HasGeometryTransform => _ptr->has_geometry_transform; + + public bool HasAdjustTransform => _ptr->has_adjust_transform; + + public bool HasRootAdjustTransform => _ptr->has_root_adjust_transform; + + public bool IsGeometryTransformHelper => _ptr->is_geometry_transform_helper; + + public bool IsScaleHelper => _ptr->is_scale_helper; + + public bool IsScaleCompensateParent => _ptr->is_scale_compensate_parent; + + public uint NodeDepth => _ptr->node_depth; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_node* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NodeList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NodeList.nativegen.cs new file mode 100644 index 0000000..289babf --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NodeList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct NodeList +{ + private readonly ufbx_node** _data; + public int Count { get; } + + internal NodeList(ufbx_node** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Node this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_node** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_node** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Node Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsBasis.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsBasis.nativegen.cs new file mode 100644 index 0000000..61a8247 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsBasis.nativegen.cs @@ -0,0 +1,38 @@ +namespace Ghost.Ufbx; + +public unsafe struct NurbsBasis +{ + private ufbx_nurbs_basis* _ptr; + + internal NurbsBasis(ufbx_nurbs_basis* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public nuint EvaluateNurbsBasis(float u, float* weights, nuint numWeights, float* derivatives, nuint numDerivatives) + { + return Api.ufbx_evaluate_nurbs_basis(_ptr, u, weights, numWeights, derivatives, numDerivatives); + } + + public uint Order => _ptr->order; + + public ufbx_nurbs_topology Topology => _ptr->topology; + + public ReadOnlySpan KnotVector => _ptr->knot_vector.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->knot_vector.data, checked((int)_ptr->knot_vector.count)); + + public float TMin => _ptr->t_min; + + public float TMax => _ptr->t_max; + + public ReadOnlySpan Spans => _ptr->spans.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->spans.data, checked((int)_ptr->spans.count)); + + public bool Is2d => _ptr->is_2d; + + public nuint NumWrapControlPoints => _ptr->num_wrap_control_points; + + public bool Valid => _ptr->valid; + + internal ufbx_nurbs_basis* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsCurve.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsCurve.nativegen.cs new file mode 100644 index 0000000..007ce84 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsCurve.nativegen.cs @@ -0,0 +1,42 @@ +namespace Ghost.Ufbx; + +public unsafe struct NurbsCurve +{ + private ufbx_nurbs_curve* _ptr; + + internal NurbsCurve(ufbx_nurbs_curve* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_curve_point EvaluateNurbsCurve(float u) + { + return Api.ufbx_evaluate_nurbs_curve(_ptr, u); + } + + public LineCurve TessellateNurbsCurve(TessellateCurveOpts opts, Error error) + { + return new(Api.ufbx_tessellate_nurbs_curve(_ptr, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public NurbsBasis Basis => new((ufbx_nurbs_basis*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->basis)); + + public ReadOnlySpan ControlPoints => _ptr->control_points.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->control_points.data, checked((int)_ptr->control_points.count)); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_nurbs_curve* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsCurveList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsCurveList.nativegen.cs new file mode 100644 index 0000000..35d2e61 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsCurveList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct NurbsCurveList +{ + private readonly ufbx_nurbs_curve** _data; + public int Count { get; } + + internal NurbsCurveList(ufbx_nurbs_curve** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public NurbsCurve this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_nurbs_curve** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_nurbs_curve** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public NurbsCurve Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsSurface.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsSurface.nativegen.cs new file mode 100644 index 0000000..672ffa5 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsSurface.nativegen.cs @@ -0,0 +1,57 @@ +namespace Ghost.Ufbx; + +public unsafe struct NurbsSurface +{ + private ufbx_nurbs_surface* _ptr; + + internal NurbsSurface(ufbx_nurbs_surface* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_surface_point EvaluateNurbsSurface(float u, float v) + { + return Api.ufbx_evaluate_nurbs_surface(_ptr, u, v); + } + + public Mesh TessellateNurbsSurface(TessellateSurfaceOpts opts, Error error) + { + return new(Api.ufbx_tessellate_nurbs_surface(_ptr, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public NurbsBasis BasisU => new((ufbx_nurbs_basis*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->basis_u)); + + public NurbsBasis BasisV => new((ufbx_nurbs_basis*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->basis_v)); + + public nuint NumControlPointsU => _ptr->num_control_points_u; + + public nuint NumControlPointsV => _ptr->num_control_points_v; + + public ReadOnlySpan ControlPoints => _ptr->control_points.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->control_points.data, checked((int)_ptr->control_points.count)); + + public uint SpanSubdivisionU => _ptr->span_subdivision_u; + + public uint SpanSubdivisionV => _ptr->span_subdivision_v; + + public bool FlipNormals => _ptr->flip_normals; + + public bool HasMaterial => _ptr->material != null; + public Material Material => _ptr->material != null ? new(_ptr->material) : throw new InvalidOperationException("Material is null."); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_nurbs_surface* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsSurfaceList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsSurfaceList.nativegen.cs new file mode 100644 index 0000000..ad8d5db --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsSurfaceList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct NurbsSurfaceList +{ + private readonly ufbx_nurbs_surface** _data; + public int Count { get; } + + internal NurbsSurfaceList(ufbx_nurbs_surface** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public NurbsSurface this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_nurbs_surface** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_nurbs_surface** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public NurbsSurface Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimBoundary.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimBoundary.nativegen.cs new file mode 100644 index 0000000..bee5200 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimBoundary.nativegen.cs @@ -0,0 +1,28 @@ +namespace Ghost.Ufbx; + +public unsafe struct NurbsTrimBoundary +{ + private ufbx_nurbs_trim_boundary* _ptr; + + internal NurbsTrimBoundary(ufbx_nurbs_trim_boundary* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_nurbs_trim_boundary* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimBoundaryList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimBoundaryList.nativegen.cs new file mode 100644 index 0000000..0025b26 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimBoundaryList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct NurbsTrimBoundaryList +{ + private readonly ufbx_nurbs_trim_boundary** _data; + public int Count { get; } + + internal NurbsTrimBoundaryList(ufbx_nurbs_trim_boundary** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public NurbsTrimBoundary this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_nurbs_trim_boundary** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_nurbs_trim_boundary** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public NurbsTrimBoundary Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimSurface.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimSurface.nativegen.cs new file mode 100644 index 0000000..053928f --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimSurface.nativegen.cs @@ -0,0 +1,28 @@ +namespace Ghost.Ufbx; + +public unsafe struct NurbsTrimSurface +{ + private ufbx_nurbs_trim_surface* _ptr; + + internal NurbsTrimSurface(ufbx_nurbs_trim_surface* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_nurbs_trim_surface* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimSurfaceList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimSurfaceList.nativegen.cs new file mode 100644 index 0000000..c898880 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/NurbsTrimSurfaceList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct NurbsTrimSurfaceList +{ + private readonly ufbx_nurbs_trim_surface** _data; + public int Count { get; } + + internal NurbsTrimSurfaceList(ufbx_nurbs_trim_surface** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public NurbsTrimSurface this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_nurbs_trim_surface** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_nurbs_trim_surface** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public NurbsTrimSurface Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileCb.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileCb.nativegen.cs new file mode 100644 index 0000000..43dd45b --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileCb.nativegen.cs @@ -0,0 +1,17 @@ +namespace Ghost.Ufbx; + +public unsafe struct OpenFileCb +{ + private ufbx_open_file_cb* _ptr; + + internal OpenFileCb(ufbx_open_file_cb* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public void* User => _ptr->user; + + internal ufbx_open_file_cb* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileInfo.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileInfo.nativegen.cs new file mode 100644 index 0000000..a754ced --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileInfo.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct OpenFileInfo +{ + private ufbx_open_file_info* _ptr; + + internal OpenFileInfo(ufbx_open_file_info* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public nuint Context => _ptr->context; + + public ufbx_open_file_type Type => _ptr->type; + + public ReadOnlySpan OriginalFilename => NativeWrapperHelpers.AsSpan(_ptr->original_filename); + + internal ufbx_open_file_info* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileOpts.nativegen.cs new file mode 100644 index 0000000..684e7db --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/OpenFileOpts.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct OpenFileOpts +{ + private ufbx_open_file_opts* _ptr; + + internal OpenFileOpts(ufbx_open_file_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AllocatorOpts Allocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->allocator)); + + public bool FilenameNullTerminated => _ptr->filename_null_terminated; + + internal ufbx_open_file_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/OpenMemoryOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/OpenMemoryOpts.nativegen.cs new file mode 100644 index 0000000..05a3516 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/OpenMemoryOpts.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct OpenMemoryOpts +{ + private ufbx_open_memory_opts* _ptr; + + internal OpenMemoryOpts(ufbx_open_memory_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AllocatorOpts Allocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->allocator)); + + public bool NoCopy => _ptr->no_copy; + + public CloseMemoryCb CloseCb => new((ufbx_close_memory_cb*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->close_cb)); + + internal ufbx_open_memory_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Panic.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Panic.nativegen.cs new file mode 100644 index 0000000..b350a31 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Panic.nativegen.cs @@ -0,0 +1,84 @@ +namespace Ghost.Ufbx; + +public unsafe struct Panic +{ + private ufbx_panic* _ptr; + + internal Panic(ufbx_panic* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Misaki.HighPerformance.Mathematics.float3x4 CatchGetSkinVertexMatrix(SkinDeformer skin, nuint vertex, Misaki.HighPerformance.Mathematics.float3x4* fallback) + { + return Api.ufbx_catch_get_skin_vertex_matrix(_ptr, skin.GetUnsafePtr(), vertex, fallback); + } + + public uint CatchTriangulateFace(uint* indices, nuint numIndices, Mesh mesh, ufbx_face face) + { + return Api.ufbx_catch_triangulate_face(_ptr, indices, numIndices, mesh.GetUnsafePtr(), face); + } + + public void CatchComputeTopology(Mesh mesh, TopoEdge topo, nuint numTopo) + { + Api.ufbx_catch_compute_topology(_ptr, mesh.GetUnsafePtr(), topo.GetUnsafePtr(), numTopo); + } + + public uint CatchTopoNextVertexEdge(TopoEdge topo, nuint numTopo, uint index) + { + return Api.ufbx_catch_topo_next_vertex_edge(_ptr, topo.GetUnsafePtr(), numTopo, index); + } + + public uint CatchTopoPrevVertexEdge(TopoEdge topo, nuint numTopo, uint index) + { + return Api.ufbx_catch_topo_prev_vertex_edge(_ptr, topo.GetUnsafePtr(), numTopo, index); + } + + public Misaki.HighPerformance.Mathematics.float3 CatchGetWeightedFaceNormal(VertexVec3 positions, ufbx_face face) + { + return Api.ufbx_catch_get_weighted_face_normal(_ptr, positions.GetUnsafePtr(), face); + } + + public nuint CatchGenerateNormalMapping(Mesh mesh, TopoEdge topo, nuint numTopo, uint* normalIndices, nuint numNormalIndices, bool assumeSmooth) + { + return Api.ufbx_catch_generate_normal_mapping(_ptr, mesh.GetUnsafePtr(), topo.GetUnsafePtr(), numTopo, normalIndices, numNormalIndices, assumeSmooth); + } + + public void CatchComputeNormals(Mesh mesh, VertexVec3 positions, uint* normalIndices, nuint numNormalIndices, Misaki.HighPerformance.Mathematics.float3* normals, nuint numNormals) + { + Api.ufbx_catch_compute_normals(_ptr, mesh.GetUnsafePtr(), positions.GetUnsafePtr(), normalIndices, numNormalIndices, normals, numNormals); + } + + public float CatchGetVertexReal(VertexReal v, nuint index) + { + return Api.ufbx_catch_get_vertex_real(_ptr, v.GetUnsafePtr(), index); + } + + public Misaki.HighPerformance.Mathematics.float2 CatchGetVertexVec2(VertexVec2 v, nuint index) + { + return Api.ufbx_catch_get_vertex_vec2(_ptr, v.GetUnsafePtr(), index); + } + + public Misaki.HighPerformance.Mathematics.float3 CatchGetVertexVec3(VertexVec3 v, nuint index) + { + return Api.ufbx_catch_get_vertex_vec3(_ptr, v.GetUnsafePtr(), index); + } + + public Misaki.HighPerformance.Mathematics.float4 CatchGetVertexVec4(VertexVec4 v, nuint index) + { + return Api.ufbx_catch_get_vertex_vec4(_ptr, v.GetUnsafePtr(), index); + } + + public float CatchGetVertexWVec3(VertexVec3 v, nuint index) + { + return Api.ufbx_catch_get_vertex_w_vec3(_ptr, v.GetUnsafePtr(), index); + } + + public bool DidPanic => _ptr->did_panic; + + public nuint MessageLength => _ptr->message_length; + + internal ufbx_panic* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Pose.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Pose.nativegen.cs new file mode 100644 index 0000000..9233eff --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Pose.nativegen.cs @@ -0,0 +1,35 @@ +namespace Ghost.Ufbx; + +public unsafe struct Pose +{ + private ufbx_pose* _ptr; + + internal Pose(ufbx_pose* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public BonePose GetBonePose(Node node) + { + return new(Api.ufbx_get_bone_pose(_ptr, node.GetUnsafePtr())); + } + + public bool IsBindPose => _ptr->is_bind_pose; + + public ReadOnlySpan BonePoses => _ptr->bone_poses.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->bone_poses.data, checked((int)_ptr->bone_poses.count)); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_pose* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/PoseList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/PoseList.nativegen.cs new file mode 100644 index 0000000..ff265dc --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/PoseList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct PoseList +{ + private readonly ufbx_pose** _data; + public int Count { get; } + + internal PoseList(ufbx_pose** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Pose this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_pose** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_pose** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Pose Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ProceduralGeometry.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ProceduralGeometry.nativegen.cs new file mode 100644 index 0000000..167a601 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ProceduralGeometry.nativegen.cs @@ -0,0 +1,28 @@ +namespace Ghost.Ufbx; + +public unsafe struct ProceduralGeometry +{ + private ufbx_procedural_geometry* _ptr; + + internal ProceduralGeometry(ufbx_procedural_geometry* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_procedural_geometry* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ProceduralGeometryList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ProceduralGeometryList.nativegen.cs new file mode 100644 index 0000000..5cc7281 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ProceduralGeometryList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct ProceduralGeometryList +{ + private readonly ufbx_procedural_geometry** _data; + public int Count { get; } + + internal ProceduralGeometryList(ufbx_procedural_geometry** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public ProceduralGeometry this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_procedural_geometry** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_procedural_geometry** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public ProceduralGeometry Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Progress.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Progress.nativegen.cs new file mode 100644 index 0000000..b4234aa --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Progress.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct Progress +{ + private ufbx_progress* _ptr; + + internal Progress(ufbx_progress* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ulong BytesRead => _ptr->bytes_read; + + public ulong BytesTotal => _ptr->bytes_total; + + internal ufbx_progress* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ProgressCb.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ProgressCb.nativegen.cs new file mode 100644 index 0000000..dfa6156 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ProgressCb.nativegen.cs @@ -0,0 +1,17 @@ +namespace Ghost.Ufbx; + +public unsafe struct ProgressCb +{ + private ufbx_progress_cb* _ptr; + + internal ProgressCb(ufbx_progress_cb* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public void* User => _ptr->user; + + internal ufbx_progress_cb* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Prop.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Prop.nativegen.cs new file mode 100644 index 0000000..1fc47de --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Prop.nativegen.cs @@ -0,0 +1,37 @@ +namespace Ghost.Ufbx; + +public unsafe ref struct Prop +{ + private ufbx_prop* _ptr; + + internal Prop(ufbx_prop* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public ufbx_prop_type Type => _ptr->type; + + public ufbx_prop_flags Flags => _ptr->flags; + + public ReadOnlySpan ValueStrBytes => NativeWrapperHelpers.AsByteSpan(_ptr->value_str); + public string ValueStr => NativeWrapperHelpers.GetString(_ptr->value_str); + + public ReadOnlySpan ValueBlob => NativeWrapperHelpers.AsSpan(_ptr->value_blob); + + public long ValueInt => _ptr->value_int; + + public float ValueReal => _ptr->value_real; + + public Misaki.HighPerformance.Mathematics.float2 ValueVec2 => _ptr->value_vec2; + + public Misaki.HighPerformance.Mathematics.float3 ValueVec3 => _ptr->value_vec3; + + public Misaki.HighPerformance.Mathematics.float4 ValueVec4 => _ptr->value_vec4; + + internal ufbx_prop* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/PropOverride.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/PropOverride.nativegen.cs new file mode 100644 index 0000000..deaa9b8 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/PropOverride.nativegen.cs @@ -0,0 +1,27 @@ +namespace Ghost.Ufbx; + +public unsafe struct PropOverride +{ + private ufbx_prop_override* _ptr; + + internal PropOverride(ufbx_prop_override* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint ElementId => _ptr->element_id; + + public ReadOnlySpan PropNameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->prop_name); + public string PropName => NativeWrapperHelpers.GetString(_ptr->prop_name); + + public Misaki.HighPerformance.Mathematics.float4 Value => _ptr->value; + + public ReadOnlySpan ValueStrBytes => NativeWrapperHelpers.AsByteSpan(_ptr->value_str); + public string ValueStr => NativeWrapperHelpers.GetString(_ptr->value_str); + + public long ValueInt => _ptr->value_int; + + internal ufbx_prop_override* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/PropOverrideDesc.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/PropOverrideDesc.nativegen.cs new file mode 100644 index 0000000..9fa9442 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/PropOverrideDesc.nativegen.cs @@ -0,0 +1,27 @@ +namespace Ghost.Ufbx; + +public unsafe struct PropOverrideDesc +{ + private ufbx_prop_override_desc* _ptr; + + internal PropOverrideDesc(ufbx_prop_override_desc* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint ElementId => _ptr->element_id; + + public ReadOnlySpan PropNameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->prop_name); + public string PropName => NativeWrapperHelpers.GetString(_ptr->prop_name); + + public Misaki.HighPerformance.Mathematics.float4 Value => _ptr->value; + + public ReadOnlySpan ValueStrBytes => NativeWrapperHelpers.AsByteSpan(_ptr->value_str); + public string ValueStr => NativeWrapperHelpers.GetString(_ptr->value_str); + + public long ValueInt => _ptr->value_int; + + internal ufbx_prop_override_desc* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Props.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Props.nativegen.cs new file mode 100644 index 0000000..ae66327 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Props.nativegen.cs @@ -0,0 +1,101 @@ +namespace Ghost.Ufbx; + +public unsafe ref struct Props +{ + private ufbx_props* _ptr; + + internal Props(ufbx_props* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Prop FindProp(ReadOnlySpan name) + { + fixed (byte* namePtr = name) + { + var value = Api.ufbx_find_prop_len(_ptr, (sbyte*)namePtr, (nuint)name.Length); + return new(value); + } + } + + public Prop FindProp(sbyte* name) + { + return new(Api.ufbx_find_prop(_ptr, name)); + } + + public float FindRealLen(sbyte* name, nuint nameLen, float def) + { + return Api.ufbx_find_real_len(_ptr, name, nameLen, def); + } + + public float FindReal(sbyte* name, float def) + { + return Api.ufbx_find_real(_ptr, name, def); + } + + public Misaki.HighPerformance.Mathematics.float3 FindVec3Len(sbyte* name, nuint nameLen, Misaki.HighPerformance.Mathematics.float3 def) + { + return Api.ufbx_find_vec3_len(_ptr, name, nameLen, def); + } + + public Misaki.HighPerformance.Mathematics.float3 FindVec3(sbyte* name, Misaki.HighPerformance.Mathematics.float3 def) + { + return Api.ufbx_find_vec3(_ptr, name, def); + } + + public long FindIntLen(sbyte* name, nuint nameLen, long def) + { + return Api.ufbx_find_int_len(_ptr, name, nameLen, def); + } + + public long FindInt(sbyte* name, long def) + { + return Api.ufbx_find_int(_ptr, name, def); + } + + public bool FindBoolLen(sbyte* name, nuint nameLen, bool def) + { + return Api.ufbx_find_bool_len(_ptr, name, nameLen, def); + } + + public bool FindBool(sbyte* name, bool def) + { + return Api.ufbx_find_bool(_ptr, name, def); + } + + public string FindStringLen(sbyte* name, nuint nameLen, ufbx_string def) + { + return NativeWrapperHelpers.GetString(Api.ufbx_find_string_len(_ptr, name, nameLen, def)); + } + + public string FindString(sbyte* name, ufbx_string def) + { + return NativeWrapperHelpers.GetString(Api.ufbx_find_string(_ptr, name, def)); + } + + public ReadOnlySpan FindBlobLen(sbyte* name, nuint nameLen, ufbx_blob def) + { + return NativeWrapperHelpers.AsSpan(Api.ufbx_find_blob_len(_ptr, name, nameLen, def)); + } + + public ReadOnlySpan FindBlob(sbyte* name, ufbx_blob def) + { + return NativeWrapperHelpers.AsSpan(Api.ufbx_find_blob(_ptr, name, def)); + } + + public Prop FindPropConcat(UfbxString parts, nuint numParts) + { + return new(Api.ufbx_find_prop_concat(_ptr, parts.GetUnsafePtr(), numParts)); + } + + public ReadOnlySpan PropsValue => _ptr->props.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->props.data, checked((int)_ptr->props.count)); + + public nuint NumAnimated => _ptr->num_animated; + + public bool HasDefaults => _ptr->defaults != null; + public Props Defaults => _ptr->defaults != null ? new(_ptr->defaults) : throw new InvalidOperationException("Defaults is null."); + + internal ufbx_props* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Quat.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Quat.nativegen.cs new file mode 100644 index 0000000..650e2e8 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Quat.nativegen.cs @@ -0,0 +1,23 @@ +namespace Ghost.Ufbx; + +public unsafe struct Quat +{ + private ufbx_quat* _ptr; + + internal Quat(ufbx_quat* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public float X => _ptr->x; + + public float Y => _ptr->y; + + public float Z => _ptr->z; + + public float W => _ptr->w; + + internal ufbx_quat* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Scene.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Scene.nativegen.cs new file mode 100644 index 0000000..ade9d72 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Scene.nativegen.cs @@ -0,0 +1,256 @@ +namespace Ghost.Ufbx; + +public unsafe class Scene : IDisposable +{ + private ufbx_scene* _ptr; + + internal Scene(ufbx_scene* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public void Dispose() + { + if (_ptr != null) + { + Api.ufbx_free_scene(_ptr); + _ptr = null; + } + } + + public static Scene LoadMemory(ReadOnlySpan data, in ufbx_load_opts options = default) + { + var optionsLocal = options; + ufbx_error error = default; + fixed (byte* dataPtr = data) + { + var value = Api.ufbx_load_memory(dataPtr, (nuint)data.Length, &optionsLocal, &error); + if (value == null) + { + throw new InvalidOperationException(NativeWrapperHelpers.GetString(error.description)); + } + return new(value); + } + } + + public static Scene LoadFile(sbyte* filename, LoadOpts opts, Error error) + { + return new(Api.ufbx_load_file(filename, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public static Scene LoadFile(ReadOnlySpan pathUtf8, LoadOpts options) + { + ufbx_error error = default; + fixed (byte* pathUtf8Ptr = pathUtf8) + { + var value = Api.ufbx_load_file_len((sbyte*)pathUtf8Ptr, (nuint)pathUtf8.Length, options.GetUnsafePtr(), &error); + if (value == null) + { + throw new InvalidOperationException(NativeWrapperHelpers.GetString(error.description)); + } + return new(value); + } + } + + public static Scene LoadStdio(void* file, LoadOpts opts, Error error) + { + return new(Api.ufbx_load_stdio(file, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public static Scene LoadStdioPrefix(void* file, void* prefix, nuint prefixSize, LoadOpts opts, Error error) + { + return new(Api.ufbx_load_stdio_prefix(file, prefix, prefixSize, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public void FreeScene() + { + Api.ufbx_free_scene(_ptr); + } + + public void RetainScene() + { + Api.ufbx_retain_scene(_ptr); + } + + public Element FindElement(ufbx_element_type type, ReadOnlySpan name) + { + fixed (byte* namePtr = name) + { + var value = Api.ufbx_find_element_len(_ptr, type, (sbyte*)namePtr, (nuint)name.Length); + return new(value); + } + } + + public Element FindElement(ufbx_element_type type, sbyte* name) + { + return new(Api.ufbx_find_element(_ptr, type, name)); + } + + public Node FindNode(ReadOnlySpan name) + { + fixed (byte* namePtr = name) + { + var value = Api.ufbx_find_node_len(_ptr, (sbyte*)namePtr, (nuint)name.Length); + return new(value); + } + } + + public Node FindNode(sbyte* name) + { + return new(Api.ufbx_find_node(_ptr, name)); + } + + public AnimStack FindAnimStack(ReadOnlySpan name) + { + fixed (byte* namePtr = name) + { + var value = Api.ufbx_find_anim_stack_len(_ptr, (sbyte*)namePtr, (nuint)name.Length); + return new(value); + } + } + + public AnimStack FindAnimStack(sbyte* name) + { + return new(Api.ufbx_find_anim_stack(_ptr, name)); + } + + public Material FindMaterial(ReadOnlySpan name) + { + fixed (byte* namePtr = name) + { + var value = Api.ufbx_find_material_len(_ptr, (sbyte*)namePtr, (nuint)name.Length); + return new(value); + } + } + + public Material FindMaterial(sbyte* name) + { + return new(Api.ufbx_find_material(_ptr, name)); + } + + public Scene EvaluateScene(Anim anim, double time, EvaluateOpts opts, Error error) + { + return new(Api.ufbx_evaluate_scene(_ptr, anim.GetUnsafePtr(), time, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public Anim CreateAnim(AnimOpts opts, Error error) + { + return new(Api.ufbx_create_anim(_ptr, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public BakedAnim BakeAnim(Anim anim, BakeOpts opts, Error error) + { + return new(Api.ufbx_bake_anim(_ptr, anim.GetUnsafePtr(), opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public Metadata Metadata => new((ufbx_metadata*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->metadata)); + + public SceneSettings Settings => new((ufbx_scene_settings*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->settings)); + + public bool HasRootNode => _ptr->root_node != null; + public Node RootNode => _ptr->root_node != null ? new(_ptr->root_node) : throw new InvalidOperationException("RootNode is null."); + + public bool HasAnim => _ptr->anim != null; + public Anim Anim => _ptr->anim != null ? new(_ptr->anim) : throw new InvalidOperationException("Anim is null."); + + public ReadOnlySpan TextureFiles => _ptr->texture_files.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->texture_files.data, checked((int)_ptr->texture_files.count)); + + public ElementList Elements => new(_ptr->elements.data, _ptr->elements.count); + + public ReadOnlySpan ConnectionsSrc => _ptr->connections_src.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->connections_src.data, checked((int)_ptr->connections_src.count)); + + public ReadOnlySpan ConnectionsDst => _ptr->connections_dst.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->connections_dst.data, checked((int)_ptr->connections_dst.count)); + + public ReadOnlySpan ElementsByName => _ptr->elements_by_name.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->elements_by_name.data, checked((int)_ptr->elements_by_name.count)); + + public bool HasDomRoot => _ptr->dom_root != null; + public DomNode DomRoot => _ptr->dom_root != null ? new(_ptr->dom_root) : throw new InvalidOperationException("DomRoot is null."); + + public UnknownList Unknowns => new(_ptr->unknowns.data, _ptr->unknowns.count); + + public NodeList Nodes => new(_ptr->nodes.data, _ptr->nodes.count); + + public MeshList Meshes => new(_ptr->meshes.data, _ptr->meshes.count); + + public LightList Lights => new(_ptr->lights.data, _ptr->lights.count); + + public CameraList Cameras => new(_ptr->cameras.data, _ptr->cameras.count); + + public BoneList Bones => new(_ptr->bones.data, _ptr->bones.count); + + public EmptyList Empties => new(_ptr->empties.data, _ptr->empties.count); + + public LineCurveList LineCurves => new(_ptr->line_curves.data, _ptr->line_curves.count); + + public NurbsCurveList NurbsCurves => new(_ptr->nurbs_curves.data, _ptr->nurbs_curves.count); + + public NurbsSurfaceList NurbsSurfaces => new(_ptr->nurbs_surfaces.data, _ptr->nurbs_surfaces.count); + + public NurbsTrimSurfaceList NurbsTrimSurfaces => new(_ptr->nurbs_trim_surfaces.data, _ptr->nurbs_trim_surfaces.count); + + public NurbsTrimBoundaryList NurbsTrimBoundaries => new(_ptr->nurbs_trim_boundaries.data, _ptr->nurbs_trim_boundaries.count); + + public ProceduralGeometryList ProceduralGeometries => new(_ptr->procedural_geometries.data, _ptr->procedural_geometries.count); + + public StereoCameraList StereoCameras => new(_ptr->stereo_cameras.data, _ptr->stereo_cameras.count); + + public CameraSwitcherList CameraSwitchers => new(_ptr->camera_switchers.data, _ptr->camera_switchers.count); + + public MarkerList Markers => new(_ptr->markers.data, _ptr->markers.count); + + public LodGroupList LodGroups => new(_ptr->lod_groups.data, _ptr->lod_groups.count); + + public SkinDeformerList SkinDeformers => new(_ptr->skin_deformers.data, _ptr->skin_deformers.count); + + public SkinClusterList SkinClusters => new(_ptr->skin_clusters.data, _ptr->skin_clusters.count); + + public BlendDeformerList BlendDeformers => new(_ptr->blend_deformers.data, _ptr->blend_deformers.count); + + public BlendChannelList BlendChannels => new(_ptr->blend_channels.data, _ptr->blend_channels.count); + + public BlendShapeList BlendShapes => new(_ptr->blend_shapes.data, _ptr->blend_shapes.count); + + public CacheDeformerList CacheDeformers => new(_ptr->cache_deformers.data, _ptr->cache_deformers.count); + + public CacheFileList CacheFiles => new(_ptr->cache_files.data, _ptr->cache_files.count); + + public MaterialList Materials => new(_ptr->materials.data, _ptr->materials.count); + + public TextureList Textures => new(_ptr->textures.data, _ptr->textures.count); + + public VideoList Videos => new(_ptr->videos.data, _ptr->videos.count); + + public ShaderList Shaders => new(_ptr->shaders.data, _ptr->shaders.count); + + public ShaderBindingList ShaderBindings => new(_ptr->shader_bindings.data, _ptr->shader_bindings.count); + + public AnimStackList AnimStacks => new(_ptr->anim_stacks.data, _ptr->anim_stacks.count); + + public AnimLayerList AnimLayers => new(_ptr->anim_layers.data, _ptr->anim_layers.count); + + public AnimValueList AnimValues => new(_ptr->anim_values.data, _ptr->anim_values.count); + + public AnimCurveList AnimCurves => new(_ptr->anim_curves.data, _ptr->anim_curves.count); + + public DisplayLayerList DisplayLayers => new(_ptr->display_layers.data, _ptr->display_layers.count); + + public SelectionSetList SelectionSets => new(_ptr->selection_sets.data, _ptr->selection_sets.count); + + public SelectionNodeList SelectionNodes => new(_ptr->selection_nodes.data, _ptr->selection_nodes.count); + + public CharacterList Characters => new(_ptr->characters.data, _ptr->characters.count); + + public ConstraintList Constraints => new(_ptr->constraints.data, _ptr->constraints.count); + + public AudioLayerList AudioLayers => new(_ptr->audio_layers.data, _ptr->audio_layers.count); + + public AudioClipList AudioClips => new(_ptr->audio_clips.data, _ptr->audio_clips.count); + + public PoseList Poses => new(_ptr->poses.data, _ptr->poses.count); + + public MetadataObjectList MetadataObjects => new(_ptr->metadata_objects.data, _ptr->metadata_objects.count); + + internal ufbx_scene* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SceneSettings.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SceneSettings.nativegen.cs new file mode 100644 index 0000000..b943840 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SceneSettings.nativegen.cs @@ -0,0 +1,38 @@ +namespace Ghost.Ufbx; + +public unsafe struct SceneSettings +{ + private ufbx_scene_settings* _ptr; + + internal SceneSettings(ufbx_scene_settings* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public CoordinateAxes Axes => new((ufbx_coordinate_axes*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->axes)); + + public float UnitMeters => _ptr->unit_meters; + + public double FramesPerSecond => _ptr->frames_per_second; + + public Misaki.HighPerformance.Mathematics.float3 AmbientColor => _ptr->ambient_color; + + public ReadOnlySpan DefaultCameraBytes => NativeWrapperHelpers.AsByteSpan(_ptr->default_camera); + public string DefaultCamera => NativeWrapperHelpers.GetString(_ptr->default_camera); + + public ufbx_time_mode TimeMode => _ptr->time_mode; + + public ufbx_time_protocol TimeProtocol => _ptr->time_protocol; + + public ufbx_snap_mode SnapMode => _ptr->snap_mode; + + public ufbx_coordinate_axis OriginalAxisUp => _ptr->original_axis_up; + + public float OriginalUnitMeters => _ptr->original_unit_meters; + + internal ufbx_scene_settings* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionNode.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionNode.nativegen.cs new file mode 100644 index 0000000..0ee46ff --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionNode.nativegen.cs @@ -0,0 +1,40 @@ +namespace Ghost.Ufbx; + +public unsafe struct SelectionNode +{ + private ufbx_selection_node* _ptr; + + internal SelectionNode(ufbx_selection_node* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool HasTargetNode => _ptr->target_node != null; + public Node TargetNode => _ptr->target_node != null ? new(_ptr->target_node) : throw new InvalidOperationException("TargetNode is null."); + + public bool HasTargetMesh => _ptr->target_mesh != null; + public Mesh TargetMesh => _ptr->target_mesh != null ? new(_ptr->target_mesh) : throw new InvalidOperationException("TargetMesh is null."); + + public bool IncludeNode => _ptr->include_node; + + public ReadOnlySpan Vertices => _ptr->vertices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->vertices.data, checked((int)_ptr->vertices.count)); + + public ReadOnlySpan Edges => _ptr->edges.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->edges.data, checked((int)_ptr->edges.count)); + + public ReadOnlySpan Faces => _ptr->faces.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->faces.data, checked((int)_ptr->faces.count)); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_selection_node* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionNodeList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionNodeList.nativegen.cs new file mode 100644 index 0000000..250ae9e --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionNodeList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct SelectionNodeList +{ + private readonly ufbx_selection_node** _data; + public int Count { get; } + + internal SelectionNodeList(ufbx_selection_node** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public SelectionNode this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_selection_node** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_selection_node** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public SelectionNode Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionSet.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionSet.nativegen.cs new file mode 100644 index 0000000..dcb492c --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionSet.nativegen.cs @@ -0,0 +1,28 @@ +namespace Ghost.Ufbx; + +public unsafe struct SelectionSet +{ + private ufbx_selection_set* _ptr; + + internal SelectionSet(ufbx_selection_set* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public SelectionNodeList Nodes => new(_ptr->nodes.data, _ptr->nodes.count); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_selection_set* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionSetList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionSetList.nativegen.cs new file mode 100644 index 0000000..213e8e3 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SelectionSetList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct SelectionSetList +{ + private readonly ufbx_selection_set** _data; + public int Count { get; } + + internal SelectionSetList(ufbx_selection_set** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public SelectionSet this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_selection_set** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_selection_set** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public SelectionSet Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Shader.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Shader.nativegen.cs new file mode 100644 index 0000000..db0fee9 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Shader.nativegen.cs @@ -0,0 +1,50 @@ +namespace Ghost.Ufbx; + +public unsafe struct Shader +{ + private ufbx_shader* _ptr; + + internal Shader(ufbx_shader* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public string FindShaderPropLen(sbyte* name, nuint nameLen) + { + return NativeWrapperHelpers.GetString(Api.ufbx_find_shader_prop_len(_ptr, name, nameLen)); + } + + public string FindShaderProp(sbyte* name) + { + return NativeWrapperHelpers.GetString(Api.ufbx_find_shader_prop(_ptr, name)); + } + + public ufbx_shader_prop_binding_list FindShaderPropBindingsLen(sbyte* name, nuint nameLen) + { + return Api.ufbx_find_shader_prop_bindings_len(_ptr, name, nameLen); + } + + public ufbx_shader_prop_binding_list FindShaderPropBindings(sbyte* name) + { + return Api.ufbx_find_shader_prop_bindings(_ptr, name); + } + + public ufbx_shader_type Type => _ptr->type; + + public ShaderBindingList Bindings => new(_ptr->bindings.data, _ptr->bindings.count); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_shader* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderBinding.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderBinding.nativegen.cs new file mode 100644 index 0000000..8a86f93 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderBinding.nativegen.cs @@ -0,0 +1,28 @@ +namespace Ghost.Ufbx; + +public unsafe struct ShaderBinding +{ + private ufbx_shader_binding* _ptr; + + internal ShaderBinding(ufbx_shader_binding* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan PropBindings => _ptr->prop_bindings.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->prop_bindings.data, checked((int)_ptr->prop_bindings.count)); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_shader_binding* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderBindingList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderBindingList.nativegen.cs new file mode 100644 index 0000000..cbbeebf --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderBindingList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct ShaderBindingList +{ + private readonly ufbx_shader_binding** _data; + public int Count { get; } + + internal ShaderBindingList(ufbx_shader_binding** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public ShaderBinding this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_shader_binding** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_shader_binding** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public ShaderBinding Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderList.nativegen.cs new file mode 100644 index 0000000..42717b9 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct ShaderList +{ + private readonly ufbx_shader** _data; + public int Count { get; } + + internal ShaderList(ufbx_shader** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Shader this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_shader** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_shader** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Shader Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderPropBinding.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderPropBinding.nativegen.cs new file mode 100644 index 0000000..abce8a9 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderPropBinding.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct ShaderPropBinding +{ + private ufbx_shader_prop_binding* _ptr; + + internal ShaderPropBinding(ufbx_shader_prop_binding* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan ShaderPropBytes => NativeWrapperHelpers.AsByteSpan(_ptr->shader_prop); + public string ShaderProp => NativeWrapperHelpers.GetString(_ptr->shader_prop); + + public ReadOnlySpan MaterialPropBytes => NativeWrapperHelpers.AsByteSpan(_ptr->material_prop); + public string MaterialProp => NativeWrapperHelpers.GetString(_ptr->material_prop); + + internal ufbx_shader_prop_binding* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderTexture.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderTexture.nativegen.cs new file mode 100644 index 0000000..c11a0ad --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderTexture.nativegen.cs @@ -0,0 +1,47 @@ +namespace Ghost.Ufbx; + +public unsafe struct ShaderTexture +{ + private ufbx_shader_texture* _ptr; + + internal ShaderTexture(ufbx_shader_texture* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ShaderTextureInput FindShaderTextureInputLen(sbyte* name, nuint nameLen) + { + return new(Api.ufbx_find_shader_texture_input_len(_ptr, name, nameLen)); + } + + public ShaderTextureInput FindShaderTextureInput(sbyte* name) + { + return new(Api.ufbx_find_shader_texture_input(_ptr, name)); + } + + public ufbx_shader_texture_type Type => _ptr->type; + + public ReadOnlySpan ShaderNameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->shader_name); + public string ShaderName => NativeWrapperHelpers.GetString(_ptr->shader_name); + + public ulong ShaderTypeId => _ptr->shader_type_id; + + public ReadOnlySpan Inputs => _ptr->inputs.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->inputs.data, checked((int)_ptr->inputs.count)); + + public ReadOnlySpan ShaderSourceBytes => NativeWrapperHelpers.AsByteSpan(_ptr->shader_source); + public string ShaderSource => NativeWrapperHelpers.GetString(_ptr->shader_source); + + public ReadOnlySpan RawShaderSource => NativeWrapperHelpers.AsSpan(_ptr->raw_shader_source); + + public bool HasMainTexture => _ptr->main_texture != null; + public Texture MainTexture => _ptr->main_texture != null ? new(_ptr->main_texture) : throw new InvalidOperationException("MainTexture is null."); + + public long MainTextureOutputIndex => _ptr->main_texture_output_index; + + public ReadOnlySpan PropPrefixBytes => NativeWrapperHelpers.AsByteSpan(_ptr->prop_prefix); + public string PropPrefix => NativeWrapperHelpers.GetString(_ptr->prop_prefix); + + internal ufbx_shader_texture* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderTextureInput.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderTextureInput.nativegen.cs new file mode 100644 index 0000000..6a50e77 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ShaderTextureInput.nativegen.cs @@ -0,0 +1,49 @@ +namespace Ghost.Ufbx; + +public unsafe struct ShaderTextureInput +{ + private ufbx_shader_texture_input* _ptr; + + internal ShaderTextureInput(ufbx_shader_texture_input* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public long ValueInt => _ptr->value_int; + + public ReadOnlySpan ValueStrBytes => NativeWrapperHelpers.AsByteSpan(_ptr->value_str); + public string ValueStr => NativeWrapperHelpers.GetString(_ptr->value_str); + + public ReadOnlySpan ValueBlob => NativeWrapperHelpers.AsSpan(_ptr->value_blob); + + public bool HasTexture => _ptr->texture != null; + public Texture Texture => _ptr->texture != null ? new(_ptr->texture) : throw new InvalidOperationException("Texture is null."); + + public long TextureOutputIndex => _ptr->texture_output_index; + + public bool TextureEnabled => _ptr->texture_enabled; + + public bool HasProp => _ptr->prop != null; + public Prop Prop => _ptr->prop != null ? new(_ptr->prop) : throw new InvalidOperationException("Prop is null."); + + public bool HasTextureProp => _ptr->texture_prop != null; + public Prop TextureProp => _ptr->texture_prop != null ? new(_ptr->texture_prop) : throw new InvalidOperationException("TextureProp is null."); + + public bool HasTextureEnabledProp => _ptr->texture_enabled_prop != null; + public Prop TextureEnabledProp => _ptr->texture_enabled_prop != null ? new(_ptr->texture_enabled_prop) : throw new InvalidOperationException("TextureEnabledProp is null."); + + public float ValueReal => _ptr->value_real; + + public Misaki.HighPerformance.Mathematics.float2 ValueVec2 => _ptr->value_vec2; + + public Misaki.HighPerformance.Mathematics.float3 ValueVec3 => _ptr->value_vec3; + + public Misaki.HighPerformance.Mathematics.float4 ValueVec4 => _ptr->value_vec4; + + internal ufbx_shader_texture_input* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SkinCluster.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinCluster.nativegen.cs new file mode 100644 index 0000000..aae5a90 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinCluster.nativegen.cs @@ -0,0 +1,45 @@ +namespace Ghost.Ufbx; + +public unsafe struct SkinCluster +{ + private ufbx_skin_cluster* _ptr; + + internal SkinCluster(ufbx_skin_cluster* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool HasBoneNode => _ptr->bone_node != null; + public Node BoneNode => _ptr->bone_node != null ? new(_ptr->bone_node) : throw new InvalidOperationException("BoneNode is null."); + + public Misaki.HighPerformance.Mathematics.float3x4 GeometryToBone => _ptr->geometry_to_bone; + + public Misaki.HighPerformance.Mathematics.float3x4 MeshNodeToBone => _ptr->mesh_node_to_bone; + + public Misaki.HighPerformance.Mathematics.float3x4 BindToWorld => _ptr->bind_to_world; + + public Misaki.HighPerformance.Mathematics.float3x4 GeometryToWorld => _ptr->geometry_to_world; + + public Transform GeometryToWorldTransform => new((ufbx_transform*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->geometry_to_world_transform)); + + public nuint NumWeights => _ptr->num_weights; + + public ReadOnlySpan Vertices => _ptr->vertices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->vertices.data, checked((int)_ptr->vertices.count)); + + public ReadOnlySpan Weights => _ptr->weights.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->weights.data, checked((int)_ptr->weights.count)); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_skin_cluster* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SkinClusterList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinClusterList.nativegen.cs new file mode 100644 index 0000000..8ed4af4 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinClusterList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct SkinClusterList +{ + private readonly ufbx_skin_cluster** _data; + public int Count { get; } + + internal SkinClusterList(ufbx_skin_cluster** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public SkinCluster this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_skin_cluster** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_skin_cluster** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public SkinCluster Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SkinDeformer.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinDeformer.nativegen.cs new file mode 100644 index 0000000..e38a275 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinDeformer.nativegen.cs @@ -0,0 +1,42 @@ +namespace Ghost.Ufbx; + +public unsafe struct SkinDeformer +{ + private ufbx_skin_deformer* _ptr; + + internal SkinDeformer(ufbx_skin_deformer* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_skinning_method SkinningMethod => _ptr->skinning_method; + + public SkinClusterList Clusters => new(_ptr->clusters.data, _ptr->clusters.count); + + public ReadOnlySpan Vertices => _ptr->vertices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->vertices.data, checked((int)_ptr->vertices.count)); + + public ReadOnlySpan Weights => _ptr->weights.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->weights.data, checked((int)_ptr->weights.count)); + + public nuint MaxWeightsPerVertex => _ptr->max_weights_per_vertex; + + public nuint NumDqWeights => _ptr->num_dq_weights; + + public ReadOnlySpan DqVertices => _ptr->dq_vertices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->dq_vertices.data, checked((int)_ptr->dq_vertices.count)); + + public ReadOnlySpan DqWeights => _ptr->dq_weights.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->dq_weights.data, checked((int)_ptr->dq_weights.count)); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_skin_deformer* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SkinDeformerList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinDeformerList.nativegen.cs new file mode 100644 index 0000000..09816c2 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinDeformerList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct SkinDeformerList +{ + private readonly ufbx_skin_deformer** _data; + public int Count { get; } + + internal SkinDeformerList(ufbx_skin_deformer** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public SkinDeformer this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_skin_deformer** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_skin_deformer** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public SkinDeformer Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SkinVertex.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinVertex.nativegen.cs new file mode 100644 index 0000000..24441a2 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinVertex.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct SkinVertex +{ + private ufbx_skin_vertex* _ptr; + + internal SkinVertex(ufbx_skin_vertex* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint WeightBegin => _ptr->weight_begin; + + public uint NumWeights => _ptr->num_weights; + + public float DqWeight => _ptr->dq_weight; + + internal ufbx_skin_vertex* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SkinWeight.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinWeight.nativegen.cs new file mode 100644 index 0000000..ea1ddac --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SkinWeight.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct SkinWeight +{ + private ufbx_skin_weight* _ptr; + + internal SkinWeight(ufbx_skin_weight* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint ClusterIndex => _ptr->cluster_index; + + public float Weight => _ptr->weight; + + internal ufbx_skin_weight* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/StereoCamera.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/StereoCamera.nativegen.cs new file mode 100644 index 0000000..c4bfd5e --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/StereoCamera.nativegen.cs @@ -0,0 +1,34 @@ +namespace Ghost.Ufbx; + +public unsafe struct StereoCamera +{ + private ufbx_stereo_camera* _ptr; + + internal StereoCamera(ufbx_stereo_camera* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool HasLeft => _ptr->left != null; + public Camera Left => _ptr->left != null ? new(_ptr->left) : throw new InvalidOperationException("Left is null."); + + public bool HasRight => _ptr->right != null; + public Camera Right => _ptr->right != null ? new(_ptr->right) : throw new InvalidOperationException("Right is null."); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + public NodeList Instances => new(_ptr->instances.data, _ptr->instances.count); + + internal ufbx_stereo_camera* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/StereoCameraList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/StereoCameraList.nativegen.cs new file mode 100644 index 0000000..faafbe7 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/StereoCameraList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct StereoCameraList +{ + private readonly ufbx_stereo_camera** _data; + public int Count { get; } + + internal StereoCameraList(ufbx_stereo_camera** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public StereoCamera this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_stereo_camera** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_stereo_camera** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public StereoCamera Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Stream.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Stream.nativegen.cs new file mode 100644 index 0000000..5219e2e --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Stream.nativegen.cs @@ -0,0 +1,47 @@ +namespace Ghost.Ufbx; + +public unsafe struct Stream +{ + private ufbx_stream* _ptr; + + internal Stream(ufbx_stream* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Scene LoadStream(LoadOpts opts, Error error) + { + return new(Api.ufbx_load_stream(_ptr, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public Scene LoadStreamPrefix(void* prefix, nuint prefixSize, LoadOpts opts, Error error) + { + return new(Api.ufbx_load_stream_prefix(_ptr, prefix, prefixSize, opts.GetUnsafePtr(), error.GetUnsafePtr())); + } + + public bool OpenFile(sbyte* path, nuint pathLen, OpenFileOpts opts, Error error) + { + return Api.ufbx_open_file(_ptr, path, pathLen, opts.GetUnsafePtr(), error.GetUnsafePtr()); + } + + public bool OpenFileCtx(nuint ctx, sbyte* path, nuint pathLen, OpenFileOpts opts, Error error) + { + return Api.ufbx_open_file_ctx(_ptr, ctx, path, pathLen, opts.GetUnsafePtr(), error.GetUnsafePtr()); + } + + public bool OpenMemory(void* data, nuint dataSize, OpenMemoryOpts opts, Error error) + { + return Api.ufbx_open_memory(_ptr, data, dataSize, opts.GetUnsafePtr(), error.GetUnsafePtr()); + } + + public bool OpenMemoryCtx(nuint ctx, void* data, nuint dataSize, OpenMemoryOpts opts, Error error) + { + return Api.ufbx_open_memory_ctx(_ptr, ctx, data, dataSize, opts.GetUnsafePtr(), error.GetUnsafePtr()); + } + + public void* User => _ptr->user; + + internal ufbx_stream* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivideOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivideOpts.nativegen.cs new file mode 100644 index 0000000..bfd9d2f --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivideOpts.nativegen.cs @@ -0,0 +1,39 @@ +namespace Ghost.Ufbx; + +public unsafe struct SubdivideOpts +{ + private ufbx_subdivide_opts* _ptr; + + internal SubdivideOpts(ufbx_subdivide_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AllocatorOpts TempAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->temp_allocator)); + + public AllocatorOpts ResultAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->result_allocator)); + + public ufbx_subdivision_boundary Boundary => _ptr->boundary; + + public ufbx_subdivision_boundary UvBoundary => _ptr->uv_boundary; + + public bool IgnoreNormals => _ptr->ignore_normals; + + public bool InterpolateNormals => _ptr->interpolate_normals; + + public bool InterpolateTangents => _ptr->interpolate_tangents; + + public bool EvaluateSourceVertices => _ptr->evaluate_source_vertices; + + public nuint MaxSourceVertices => _ptr->max_source_vertices; + + public bool EvaluateSkinWeights => _ptr->evaluate_skin_weights; + + public nuint MaxSkinWeights => _ptr->max_skin_weights; + + public nuint SkinDeformerIndex => _ptr->skin_deformer_index; + + internal ufbx_subdivide_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionResult.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionResult.nativegen.cs new file mode 100644 index 0000000..3aef4c1 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionResult.nativegen.cs @@ -0,0 +1,31 @@ +namespace Ghost.Ufbx; + +public unsafe struct SubdivisionResult +{ + private ufbx_subdivision_result* _ptr; + + internal SubdivisionResult(ufbx_subdivision_result* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public nuint ResultMemoryUsed => _ptr->result_memory_used; + + public nuint TempMemoryUsed => _ptr->temp_memory_used; + + public nuint ResultAllocs => _ptr->result_allocs; + + public nuint TempAllocs => _ptr->temp_allocs; + + public ReadOnlySpan SourceVertexRanges => _ptr->source_vertex_ranges.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->source_vertex_ranges.data, checked((int)_ptr->source_vertex_ranges.count)); + + public ReadOnlySpan SourceVertexWeights => _ptr->source_vertex_weights.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->source_vertex_weights.data, checked((int)_ptr->source_vertex_weights.count)); + + public ReadOnlySpan SkinClusterRanges => _ptr->skin_cluster_ranges.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->skin_cluster_ranges.data, checked((int)_ptr->skin_cluster_ranges.count)); + + public ReadOnlySpan SkinClusterWeights => _ptr->skin_cluster_weights.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->skin_cluster_weights.data, checked((int)_ptr->skin_cluster_weights.count)); + + internal ufbx_subdivision_result* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionWeight.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionWeight.nativegen.cs new file mode 100644 index 0000000..b1fd3bc --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionWeight.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct SubdivisionWeight +{ + private ufbx_subdivision_weight* _ptr; + + internal SubdivisionWeight(ufbx_subdivision_weight* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public float Weight => _ptr->weight; + + public uint Index => _ptr->index; + + internal ufbx_subdivision_weight* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionWeightRange.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionWeightRange.nativegen.cs new file mode 100644 index 0000000..c2a9206 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SubdivisionWeightRange.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct SubdivisionWeightRange +{ + private ufbx_subdivision_weight_range* _ptr; + + internal SubdivisionWeightRange(ufbx_subdivision_weight_range* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint WeightBegin => _ptr->weight_begin; + + public uint NumWeights => _ptr->num_weights; + + internal ufbx_subdivision_weight_range* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/SurfacePoint.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/SurfacePoint.nativegen.cs new file mode 100644 index 0000000..abed725 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/SurfacePoint.nativegen.cs @@ -0,0 +1,23 @@ +namespace Ghost.Ufbx; + +public unsafe struct SurfacePoint +{ + private ufbx_surface_point* _ptr; + + internal SurfacePoint(ufbx_surface_point* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool Valid => _ptr->valid; + + public Misaki.HighPerformance.Mathematics.float3 Position => _ptr->position; + + public Misaki.HighPerformance.Mathematics.float3 DerivativeU => _ptr->derivative_u; + + public Misaki.HighPerformance.Mathematics.float3 DerivativeV => _ptr->derivative_v; + + internal ufbx_surface_point* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Tangent.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Tangent.nativegen.cs new file mode 100644 index 0000000..5d5cdcf --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Tangent.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct Tangent +{ + private ufbx_tangent* _ptr; + + internal Tangent(ufbx_tangent* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public float Dx => _ptr->dx; + + public float Dy => _ptr->dy; + + internal ufbx_tangent* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/TessellateCurveOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/TessellateCurveOpts.nativegen.cs new file mode 100644 index 0000000..31bff2c --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/TessellateCurveOpts.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct TessellateCurveOpts +{ + private ufbx_tessellate_curve_opts* _ptr; + + internal TessellateCurveOpts(ufbx_tessellate_curve_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AllocatorOpts TempAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->temp_allocator)); + + public AllocatorOpts ResultAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->result_allocator)); + + public nuint SpanSubdivision => _ptr->span_subdivision; + + internal ufbx_tessellate_curve_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/TessellateSurfaceOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/TessellateSurfaceOpts.nativegen.cs new file mode 100644 index 0000000..aba0d96 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/TessellateSurfaceOpts.nativegen.cs @@ -0,0 +1,25 @@ +namespace Ghost.Ufbx; + +public unsafe struct TessellateSurfaceOpts +{ + private ufbx_tessellate_surface_opts* _ptr; + + internal TessellateSurfaceOpts(ufbx_tessellate_surface_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public AllocatorOpts TempAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->temp_allocator)); + + public AllocatorOpts ResultAllocator => new((ufbx_allocator_opts*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->result_allocator)); + + public nuint SpanSubdivisionU => _ptr->span_subdivision_u; + + public nuint SpanSubdivisionV => _ptr->span_subdivision_v; + + public bool SkipMeshParts => _ptr->skip_mesh_parts; + + internal ufbx_tessellate_surface_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Texture.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Texture.nativegen.cs new file mode 100644 index 0000000..590fed7 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Texture.nativegen.cs @@ -0,0 +1,74 @@ +namespace Ghost.Ufbx; + +public unsafe ref struct Texture +{ + private ufbx_texture* _ptr; + + internal Texture(ufbx_texture* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_texture_type Type => _ptr->type; + + public ReadOnlySpan FilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->filename); + public string Filename => NativeWrapperHelpers.GetString(_ptr->filename); + + public ReadOnlySpan AbsoluteFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->absolute_filename); + public string AbsoluteFilename => NativeWrapperHelpers.GetString(_ptr->absolute_filename); + + public ReadOnlySpan RelativeFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->relative_filename); + public string RelativeFilename => NativeWrapperHelpers.GetString(_ptr->relative_filename); + + public ReadOnlySpan RawFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_filename); + + public ReadOnlySpan RawAbsoluteFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_absolute_filename); + + public ReadOnlySpan RawRelativeFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_relative_filename); + + public ReadOnlySpan Content => NativeWrapperHelpers.AsSpan(_ptr->content); + + public bool HasVideo => _ptr->video != null; + public Video Video => _ptr->video != null ? new(_ptr->video) : throw new InvalidOperationException("Video is null."); + + public uint FileIndex => _ptr->file_index; + + public bool HasFile => _ptr->has_file; + + public ReadOnlySpan Layers => _ptr->layers.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->layers.data, checked((int)_ptr->layers.count)); + + public bool HasShader => _ptr->shader != null; + public ShaderTexture Shader => _ptr->shader != null ? new(_ptr->shader) : throw new InvalidOperationException("Shader is null."); + + public TextureList FileTextures => new(_ptr->file_textures.data, _ptr->file_textures.count); + + public ReadOnlySpan UvSetBytes => NativeWrapperHelpers.AsByteSpan(_ptr->uv_set); + public string UvSet => NativeWrapperHelpers.GetString(_ptr->uv_set); + + public ufbx_wrap_mode WrapU => _ptr->wrap_u; + + public ufbx_wrap_mode WrapV => _ptr->wrap_v; + + public bool HasUvTransform => _ptr->has_uv_transform; + + public Transform UvTransform => new((ufbx_transform*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->uv_transform)); + + public Misaki.HighPerformance.Mathematics.float3x4 TextureToUv => _ptr->texture_to_uv; + + public Misaki.HighPerformance.Mathematics.float3x4 UvToTexture => _ptr->uv_to_texture; + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_texture* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/TextureFile.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/TextureFile.nativegen.cs new file mode 100644 index 0000000..f5520c0 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/TextureFile.nativegen.cs @@ -0,0 +1,34 @@ +namespace Ghost.Ufbx; + +public unsafe struct TextureFile +{ + private ufbx_texture_file* _ptr; + + internal TextureFile(ufbx_texture_file* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint Index => _ptr->index; + + public ReadOnlySpan FilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->filename); + public string Filename => NativeWrapperHelpers.GetString(_ptr->filename); + + public ReadOnlySpan AbsoluteFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->absolute_filename); + public string AbsoluteFilename => NativeWrapperHelpers.GetString(_ptr->absolute_filename); + + public ReadOnlySpan RelativeFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->relative_filename); + public string RelativeFilename => NativeWrapperHelpers.GetString(_ptr->relative_filename); + + public ReadOnlySpan RawFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_filename); + + public ReadOnlySpan RawAbsoluteFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_absolute_filename); + + public ReadOnlySpan RawRelativeFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_relative_filename); + + public ReadOnlySpan Content => NativeWrapperHelpers.AsSpan(_ptr->content); + + internal ufbx_texture_file* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/TextureLayer.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/TextureLayer.nativegen.cs new file mode 100644 index 0000000..c038196 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/TextureLayer.nativegen.cs @@ -0,0 +1,22 @@ +namespace Ghost.Ufbx; + +public unsafe struct TextureLayer +{ + private ufbx_texture_layer* _ptr; + + internal TextureLayer(ufbx_texture_layer* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool HasTexture => _ptr->texture != null; + public Texture Texture => _ptr->texture != null ? new(_ptr->texture) : throw new InvalidOperationException("Texture is null."); + + public ufbx_blend_mode BlendMode => _ptr->blend_mode; + + public float Alpha => _ptr->alpha; + + internal ufbx_texture_layer* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/TextureList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/TextureList.nativegen.cs new file mode 100644 index 0000000..dbd5350 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/TextureList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct TextureList +{ + private readonly ufbx_texture** _data; + public int Count { get; } + + internal TextureList(ufbx_texture** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Texture this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_texture** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_texture** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Texture Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ThreadOpts.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ThreadOpts.nativegen.cs new file mode 100644 index 0000000..0a63268 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ThreadOpts.nativegen.cs @@ -0,0 +1,21 @@ +namespace Ghost.Ufbx; + +public unsafe struct ThreadOpts +{ + private ufbx_thread_opts* _ptr; + + internal ThreadOpts(ufbx_thread_opts* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ThreadPool Pool => new((ufbx_thread_pool*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->pool)); + + public nuint NumTasks => _ptr->num_tasks; + + public nuint MemoryLimit => _ptr->memory_limit; + + internal ufbx_thread_opts* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ThreadPool.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ThreadPool.nativegen.cs new file mode 100644 index 0000000..1bff93c --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ThreadPool.nativegen.cs @@ -0,0 +1,17 @@ +namespace Ghost.Ufbx; + +public unsafe struct ThreadPool +{ + private ufbx_thread_pool* _ptr; + + internal ThreadPool(ufbx_thread_pool* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public void* User => _ptr->user; + + internal ufbx_thread_pool* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/ThreadPoolInfo.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/ThreadPoolInfo.nativegen.cs new file mode 100644 index 0000000..26cd8b7 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/ThreadPoolInfo.nativegen.cs @@ -0,0 +1,17 @@ +namespace Ghost.Ufbx; + +public unsafe struct ThreadPoolInfo +{ + private ufbx_thread_pool_info* _ptr; + + internal ThreadPoolInfo(ufbx_thread_pool_info* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint MaxConcurrentTasks => _ptr->max_concurrent_tasks; + + internal ufbx_thread_pool_info* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Thumbnail.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Thumbnail.nativegen.cs new file mode 100644 index 0000000..9e22077 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Thumbnail.nativegen.cs @@ -0,0 +1,25 @@ +namespace Ghost.Ufbx; + +public unsafe struct Thumbnail +{ + private ufbx_thumbnail* _ptr; + + internal Thumbnail(ufbx_thumbnail* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint Width => _ptr->width; + + public uint Height => _ptr->height; + + public ufbx_thumbnail_format Format => _ptr->format; + + public ReadOnlySpan Data => NativeWrapperHelpers.AsSpan(_ptr->data); + + internal ufbx_thumbnail* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/TopoEdge.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/TopoEdge.nativegen.cs new file mode 100644 index 0000000..4413639 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/TopoEdge.nativegen.cs @@ -0,0 +1,39 @@ +namespace Ghost.Ufbx; + +public unsafe struct TopoEdge +{ + private ufbx_topo_edge* _ptr; + + internal TopoEdge(ufbx_topo_edge* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint TopoNextVertexEdge(nuint numTopo, uint index) + { + return Api.ufbx_topo_next_vertex_edge(_ptr, numTopo, index); + } + + public uint TopoPrevVertexEdge(nuint numTopo, uint index) + { + return Api.ufbx_topo_prev_vertex_edge(_ptr, numTopo, index); + } + + public uint Index => _ptr->index; + + public uint Next => _ptr->next; + + public uint Prev => _ptr->prev; + + public uint Twin => _ptr->twin; + + public uint Face => _ptr->face; + + public uint Edge => _ptr->edge; + + public ufbx_topo_flags Flags => _ptr->flags; + + internal ufbx_topo_edge* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Transform.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Transform.nativegen.cs new file mode 100644 index 0000000..27dc3bd --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Transform.nativegen.cs @@ -0,0 +1,26 @@ +namespace Ghost.Ufbx; + +public unsafe struct Transform +{ + private ufbx_transform* _ptr; + + internal Transform(ufbx_transform* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Misaki.HighPerformance.Mathematics.float3x4 TransformToMatrix() + { + return Api.ufbx_transform_to_matrix(_ptr); + } + + public Misaki.HighPerformance.Mathematics.float3 Translation => _ptr->translation; + + public Misaki.HighPerformance.Mathematics.quaternion Rotation => _ptr->rotation; + + public Misaki.HighPerformance.Mathematics.float3 Scale => _ptr->scale; + + internal ufbx_transform* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/TransformOverride.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/TransformOverride.nativegen.cs new file mode 100644 index 0000000..1694950 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/TransformOverride.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct TransformOverride +{ + private ufbx_transform_override* _ptr; + + internal TransformOverride(ufbx_transform_override* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public uint NodeId => _ptr->node_id; + + public Transform Transform => new((ufbx_transform*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->transform)); + + internal ufbx_transform_override* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Ufbx.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Ufbx.nativegen.cs new file mode 100644 index 0000000..043ff1a --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Ufbx.nativegen.cs @@ -0,0 +1,140 @@ +namespace Ghost.Ufbx; + +public static unsafe class Ufbx +{ + public static bool CoordinateAxesValid(ufbx_coordinate_axes axes) + { + return Api.ufbx_coordinate_axes_valid(axes); + } + + public static bool DefaultOpenFile(void* user, Stream stream, sbyte* path, nuint pathLen, OpenFileInfo info) + { + return Api.ufbx_default_open_file(user, stream.GetUnsafePtr(), path, pathLen, info.GetUnsafePtr()); + } + + public static Misaki.HighPerformance.Mathematics.quaternion EulerToQuat(Misaki.HighPerformance.Mathematics.float3 v, ufbx_rotation_order order) + { + return Api.ufbx_euler_to_quat(v, order); + } + + public static Misaki.HighPerformance.Mathematics.quaternion EvaluateBakedQuat(ufbx_baked_quat_list keyframes, double time) + { + return Api.ufbx_evaluate_baked_quat(keyframes, time); + } + + public static Misaki.HighPerformance.Mathematics.float3 EvaluateBakedVec3(ufbx_baked_vec3_list keyframes, double time) + { + return Api.ufbx_evaluate_baked_vec3(keyframes, time); + } + + public static nuint FormatError(sbyte* dst, nuint dstSize, Error error) + { + return Api.ufbx_format_error(dst, dstSize, error.GetUnsafePtr()); + } + + public static nint Inflate(void* dst, nuint dstSize, InflateInput input, InflateRetain retain) + { + return Api.ufbx_inflate(dst, dstSize, input.GetUnsafePtr(), retain.GetUnsafePtr()); + } + + public static bool IsThreadSafe() + { + return Api.ufbx_is_thread_safe(); + } + + public static float MatrixDeterminant(Misaki.HighPerformance.Mathematics.float3x4* m) + { + return Api.ufbx_matrix_determinant(m); + } + + public static Misaki.HighPerformance.Mathematics.float3x4 MatrixForNormals(Misaki.HighPerformance.Mathematics.float3x4* m) + { + return Api.ufbx_matrix_for_normals(m); + } + + public static Misaki.HighPerformance.Mathematics.float3x4 MatrixInvert(Misaki.HighPerformance.Mathematics.float3x4* m) + { + return Api.ufbx_matrix_invert(m); + } + + public static Misaki.HighPerformance.Mathematics.float3x4 MatrixMul(Misaki.HighPerformance.Mathematics.float3x4* a, Misaki.HighPerformance.Mathematics.float3x4* b) + { + return Api.ufbx_matrix_mul(a, b); + } + + public static ufbx_transform MatrixToTransform(Misaki.HighPerformance.Mathematics.float3x4* m) + { + return Api.ufbx_matrix_to_transform(m); + } + + public static float QuatDot(Misaki.HighPerformance.Mathematics.quaternion a, Misaki.HighPerformance.Mathematics.quaternion b) + { + return Api.ufbx_quat_dot(a, b); + } + + public static Misaki.HighPerformance.Mathematics.quaternion QuatFixAntipodal(Misaki.HighPerformance.Mathematics.quaternion q, Misaki.HighPerformance.Mathematics.quaternion reference) + { + return Api.ufbx_quat_fix_antipodal(q, reference); + } + + public static Misaki.HighPerformance.Mathematics.quaternion QuatMul(Misaki.HighPerformance.Mathematics.quaternion a, Misaki.HighPerformance.Mathematics.quaternion b) + { + return Api.ufbx_quat_mul(a, b); + } + + public static Misaki.HighPerformance.Mathematics.quaternion QuatNormalize(Misaki.HighPerformance.Mathematics.quaternion q) + { + return Api.ufbx_quat_normalize(q); + } + + public static Misaki.HighPerformance.Mathematics.float3 QuatRotateVec3(Misaki.HighPerformance.Mathematics.quaternion q, Misaki.HighPerformance.Mathematics.float3 v) + { + return Api.ufbx_quat_rotate_vec3(q, v); + } + + public static Misaki.HighPerformance.Mathematics.quaternion QuatSlerp(Misaki.HighPerformance.Mathematics.quaternion a, Misaki.HighPerformance.Mathematics.quaternion b, float t) + { + return Api.ufbx_quat_slerp(a, b, t); + } + + public static Misaki.HighPerformance.Mathematics.float3 QuatToEuler(Misaki.HighPerformance.Mathematics.quaternion q, ufbx_rotation_order order) + { + return Api.ufbx_quat_to_euler(q, order); + } + + public static void* ThreadPoolGetUserPtr(nuint ctx) + { + return Api.ufbx_thread_pool_get_user_ptr(ctx); + } + + public static void ThreadPoolRunTask(nuint ctx, uint index) + { + Api.ufbx_thread_pool_run_task(ctx, index); + } + + public static void ThreadPoolSetUserPtr(nuint ctx, void* userPtr) + { + Api.ufbx_thread_pool_set_user_ptr(ctx, userPtr); + } + + public static Misaki.HighPerformance.Mathematics.float3 TransformDirection(Misaki.HighPerformance.Mathematics.float3x4* m, Misaki.HighPerformance.Mathematics.float3 v) + { + return Api.ufbx_transform_direction(m, v); + } + + public static Misaki.HighPerformance.Mathematics.float3 TransformPosition(Misaki.HighPerformance.Mathematics.float3x4* m, Misaki.HighPerformance.Mathematics.float3 v) + { + return Api.ufbx_transform_position(m, v); + } + + public static uint TriangulateFace(uint* indices, nuint numIndices, Mesh mesh, ufbx_face face) + { + return Api.ufbx_triangulate_face(indices, numIndices, mesh.GetUnsafePtr(), face); + } + + public static Misaki.HighPerformance.Mathematics.float3 Vec3Normalize(Misaki.HighPerformance.Mathematics.float3 v) + { + return Api.ufbx_vec3_normalize(v); + } + +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/UfbxBlob.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/UfbxBlob.nativegen.cs new file mode 100644 index 0000000..eb002ed --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/UfbxBlob.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct UfbxBlob +{ + private ufbx_blob* _ptr; + + internal UfbxBlob(ufbx_blob* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public void* Data => _ptr->data; + + public nuint Size => _ptr->size; + + internal ufbx_blob* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/UfbxString.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/UfbxString.nativegen.cs new file mode 100644 index 0000000..c3d0189 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/UfbxString.nativegen.cs @@ -0,0 +1,19 @@ +namespace Ghost.Ufbx; + +public unsafe struct UfbxString +{ + private ufbx_string* _ptr; + + internal UfbxString(ufbx_string* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public sbyte* Data => _ptr->data; + + public nuint Length => _ptr->length; + + internal ufbx_string* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Unknown.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Unknown.nativegen.cs new file mode 100644 index 0000000..c9eaa24 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Unknown.nativegen.cs @@ -0,0 +1,35 @@ +namespace Ghost.Ufbx; + +public unsafe struct Unknown +{ + private ufbx_unknown* _ptr; + + internal Unknown(ufbx_unknown* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan TypeBytes => NativeWrapperHelpers.AsByteSpan(_ptr->type); + public string Type => NativeWrapperHelpers.GetString(_ptr->type); + + public ReadOnlySpan SuperTypeBytes => NativeWrapperHelpers.AsByteSpan(_ptr->super_type); + public string SuperType => NativeWrapperHelpers.GetString(_ptr->super_type); + + public ReadOnlySpan SubTypeBytes => NativeWrapperHelpers.AsByteSpan(_ptr->sub_type); + public string SubType => NativeWrapperHelpers.GetString(_ptr->sub_type); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_unknown* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/UnknownList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/UnknownList.nativegen.cs new file mode 100644 index 0000000..eaca4cc --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/UnknownList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct UnknownList +{ + private readonly ufbx_unknown** _data; + public int Count { get; } + + internal UnknownList(ufbx_unknown** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Unknown this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_unknown** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_unknown** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Unknown Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/UvSet.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/UvSet.nativegen.cs new file mode 100644 index 0000000..aeab21d --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/UvSet.nativegen.cs @@ -0,0 +1,26 @@ +namespace Ghost.Ufbx; + +public unsafe struct UvSet +{ + private ufbx_uv_set* _ptr; + + internal UvSet(ufbx_uv_set* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public uint Index => _ptr->index; + + public VertexVec2 VertexUv => new((ufbx_vertex_vec2*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_uv)); + + public VertexVec3 VertexTangent => new((ufbx_vertex_vec3*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_tangent)); + + public VertexVec3 VertexBitangent => new((ufbx_vertex_vec3*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->vertex_bitangent)); + + internal ufbx_uv_set* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/VertexAttrib.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexAttrib.nativegen.cs new file mode 100644 index 0000000..b7f3671 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexAttrib.nativegen.cs @@ -0,0 +1,27 @@ +namespace Ghost.Ufbx; + +public unsafe struct VertexAttrib +{ + private ufbx_vertex_attrib* _ptr; + + internal VertexAttrib(ufbx_vertex_attrib* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool Exists => _ptr->exists; + + public VoidList Values => new(_ptr->values.data, _ptr->values.count); + + public ReadOnlySpan Indices => _ptr->indices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->indices.data, checked((int)_ptr->indices.count)); + + public nuint ValueReals => _ptr->value_reals; + + public bool UniquePerVertex => _ptr->unique_per_vertex; + + public ReadOnlySpan ValuesW => _ptr->values_w.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values_w.data, checked((int)_ptr->values_w.count)); + + internal ufbx_vertex_attrib* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/VertexReal.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexReal.nativegen.cs new file mode 100644 index 0000000..7194ea4 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexReal.nativegen.cs @@ -0,0 +1,27 @@ +namespace Ghost.Ufbx; + +public unsafe struct VertexReal +{ + private ufbx_vertex_real* _ptr; + + internal VertexReal(ufbx_vertex_real* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool Exists => _ptr->exists; + + public ReadOnlySpan Values => _ptr->values.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values.data, checked((int)_ptr->values.count)); + + public ReadOnlySpan Indices => _ptr->indices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->indices.data, checked((int)_ptr->indices.count)); + + public nuint ValueReals => _ptr->value_reals; + + public bool UniquePerVertex => _ptr->unique_per_vertex; + + public ReadOnlySpan ValuesW => _ptr->values_w.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values_w.data, checked((int)_ptr->values_w.count)); + + internal ufbx_vertex_real* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/VertexStream.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexStream.nativegen.cs new file mode 100644 index 0000000..26d295c --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexStream.nativegen.cs @@ -0,0 +1,26 @@ +namespace Ghost.Ufbx; + +public unsafe struct VertexStream +{ + private ufbx_vertex_stream* _ptr; + + internal VertexStream(ufbx_vertex_stream* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public nuint GenerateIndices(nuint numStreams, uint* indices, nuint numIndices, AllocatorOpts allocator, Error error) + { + return Api.ufbx_generate_indices(_ptr, numStreams, indices, numIndices, allocator.GetUnsafePtr(), error.GetUnsafePtr()); + } + + public void* Data => _ptr->data; + + public nuint VertexCount => _ptr->vertex_count; + + public nuint VertexSize => _ptr->vertex_size; + + internal ufbx_vertex_stream* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec2.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec2.nativegen.cs new file mode 100644 index 0000000..0496d20 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec2.nativegen.cs @@ -0,0 +1,27 @@ +namespace Ghost.Ufbx; + +public unsafe struct VertexVec2 +{ + private ufbx_vertex_vec2* _ptr; + + internal VertexVec2(ufbx_vertex_vec2* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool Exists => _ptr->exists; + + public ReadOnlySpan Values => _ptr->values.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values.data, checked((int)_ptr->values.count)); + + public ReadOnlySpan Indices => _ptr->indices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->indices.data, checked((int)_ptr->indices.count)); + + public nuint ValueReals => _ptr->value_reals; + + public bool UniquePerVertex => _ptr->unique_per_vertex; + + public ReadOnlySpan ValuesW => _ptr->values_w.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values_w.data, checked((int)_ptr->values_w.count)); + + internal ufbx_vertex_vec2* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec3.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec3.nativegen.cs new file mode 100644 index 0000000..a11c94d --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec3.nativegen.cs @@ -0,0 +1,32 @@ +namespace Ghost.Ufbx; + +public unsafe struct VertexVec3 +{ + private ufbx_vertex_vec3* _ptr; + + internal VertexVec3(ufbx_vertex_vec3* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public Misaki.HighPerformance.Mathematics.float3 GetWeightedFaceNormal(ufbx_face face) + { + return Api.ufbx_get_weighted_face_normal(_ptr, face); + } + + public bool Exists => _ptr->exists; + + public ReadOnlySpan Values => _ptr->values.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values.data, checked((int)_ptr->values.count)); + + public ReadOnlySpan Indices => _ptr->indices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->indices.data, checked((int)_ptr->indices.count)); + + public nuint ValueReals => _ptr->value_reals; + + public bool UniquePerVertex => _ptr->unique_per_vertex; + + public ReadOnlySpan ValuesW => _ptr->values_w.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values_w.data, checked((int)_ptr->values_w.count)); + + internal ufbx_vertex_vec3* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec4.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec4.nativegen.cs new file mode 100644 index 0000000..9ab591e --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/VertexVec4.nativegen.cs @@ -0,0 +1,27 @@ +namespace Ghost.Ufbx; + +public unsafe struct VertexVec4 +{ + private ufbx_vertex_vec4* _ptr; + + internal VertexVec4(ufbx_vertex_vec4* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public bool Exists => _ptr->exists; + + public ReadOnlySpan Values => _ptr->values.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values.data, checked((int)_ptr->values.count)); + + public ReadOnlySpan Indices => _ptr->indices.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->indices.data, checked((int)_ptr->indices.count)); + + public nuint ValueReals => _ptr->value_reals; + + public bool UniquePerVertex => _ptr->unique_per_vertex; + + public ReadOnlySpan ValuesW => _ptr->values_w.data == null ? ReadOnlySpan.Empty : new ReadOnlySpan(_ptr->values_w.data, checked((int)_ptr->values_w.count)); + + internal ufbx_vertex_vec4* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Video.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Video.nativegen.cs new file mode 100644 index 0000000..691c172 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Video.nativegen.cs @@ -0,0 +1,43 @@ +namespace Ghost.Ufbx; + +public unsafe struct Video +{ + private ufbx_video* _ptr; + + internal Video(ufbx_video* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ReadOnlySpan FilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->filename); + public string Filename => NativeWrapperHelpers.GetString(_ptr->filename); + + public ReadOnlySpan AbsoluteFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->absolute_filename); + public string AbsoluteFilename => NativeWrapperHelpers.GetString(_ptr->absolute_filename); + + public ReadOnlySpan RelativeFilenameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->relative_filename); + public string RelativeFilename => NativeWrapperHelpers.GetString(_ptr->relative_filename); + + public ReadOnlySpan RawFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_filename); + + public ReadOnlySpan RawAbsoluteFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_absolute_filename); + + public ReadOnlySpan RawRelativeFilename => NativeWrapperHelpers.AsSpan(_ptr->raw_relative_filename); + + public ReadOnlySpan Content => NativeWrapperHelpers.AsSpan(_ptr->content); + + public Element Element => new((ufbx_element*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->element)); + + public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); + public string Name => NativeWrapperHelpers.GetString(_ptr->name); + + public Props Props => new((ufbx_props*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->props)); + + public uint ElementId => _ptr->element_id; + + public uint TypedId => _ptr->typed_id; + + internal ufbx_video* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/VideoList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/VideoList.nativegen.cs new file mode 100644 index 0000000..4617658 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/VideoList.nativegen.cs @@ -0,0 +1,52 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct VideoList +{ + private readonly ufbx_video** _data; + public int Count { get; } + + internal VideoList(ufbx_video** data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public Video this[int index] + { + get + { + NativeWrapperHelpers.ThrowIfOutOfRange(index, Count); + return new(_data[index]); + } + } + + public Enumerator GetEnumerator() => new(_data, Count); + + public unsafe ref struct Enumerator + { + private readonly ufbx_video** _data; + private readonly int _count; + private int _index; + + internal Enumerator(ufbx_video** data, int count) + { + _data = data; + _count = count; + _index = -1; + } + + public Video Current => new(_data[_index]); + + public bool MoveNext() + { + var next = _index + 1; + if (next >= _count) + { + return false; + } + + _index = next; + return true; + } + } +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/VoidList.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/VoidList.nativegen.cs new file mode 100644 index 0000000..230fe38 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/VoidList.nativegen.cs @@ -0,0 +1,15 @@ +namespace Ghost.Ufbx; + +public unsafe readonly ref struct VoidList +{ + private readonly void* _data; + public int Count { get; } + + internal VoidList(void* data, nuint count) + { + _data = data; + Count = checked((int)count); + } + + public void* Data => _data; +} diff --git a/src/ThridParty/Ghost.Ufbx/Wrapper/Warning.nativegen.cs b/src/ThridParty/Ghost.Ufbx/Wrapper/Warning.nativegen.cs new file mode 100644 index 0000000..826c950 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/Wrapper/Warning.nativegen.cs @@ -0,0 +1,24 @@ +namespace Ghost.Ufbx; + +public unsafe struct Warning +{ + private ufbx_warning* _ptr; + + internal Warning(ufbx_warning* ptr) + { + _ptr = ptr; + } + + public bool IsNull => _ptr == null; + + public ufbx_warning_type Type => _ptr->type; + + public ReadOnlySpan DescriptionBytes => NativeWrapperHelpers.AsByteSpan(_ptr->description); + public string Description => NativeWrapperHelpers.GetString(_ptr->description); + + public uint ElementId => _ptr->element_id; + + public nuint Count => _ptr->count; + + internal ufbx_warning* GetUnsafePtr() => _ptr; +} diff --git a/src/ThridParty/Ghost.Ufbx/cstring.cs b/src/ThridParty/Ghost.Ufbx/cstring.cs new file mode 100644 index 0000000..5706491 --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/cstring.cs @@ -0,0 +1,104 @@ +using System.Runtime.InteropServices; +using System.Text; + +namespace Ghost.Ufbx; + +public unsafe struct cstring : IDisposable, IEquatable +{ + public byte* ptr; + public int length; + + public cstring(byte* ptr, nuint length) + { + if (length == 0) + { + return; + } + + this.ptr = (byte*)NativeMemory.Alloc(length); + this.length = (int)length; + } + + public cstring(ReadOnlySpan str) + { + if (str.Length == 0) + { + return; + } + + length = Encoding.UTF8.GetByteCount(str); + ptr = (byte*)NativeMemory.Alloc((nuint)length); + fixed (char* p = str) + { + Encoding.UTF8.GetBytes(p, str.Length, ptr, length); + } + } + + public cstring(ReadOnlySpan str) + { + if (str.Length == 0) + { + return; + } + + length = str.Length; + ptr = (byte*)NativeMemory.Alloc((nuint)length); + fixed (byte* p = str) + { + NativeMemory.Copy(p, ptr, (nuint)length); + } + } + + public cstring(cstring other) + { + if (other.length == 0) + { + return; + } + + length = other.length; + ptr = (byte*)NativeMemory.Alloc((nuint)length); + NativeMemory.Copy(other.ptr, ptr, (nuint)length); + } + + public void Dispose() + { + if (ptr != null) + { + NativeMemory.Free(ptr); + } + + ptr = null; + length = 0; + } + + public readonly bool Equals(cstring other) + { + return length == other.length && ptr == other.ptr; + } + + public override bool Equals(object? obj) + { + return obj is cstring cstring && Equals(cstring); + } + + public override readonly int GetHashCode() + { + return HashCode.Combine((nint)ptr, length); + } + + public override readonly string ToString() + { + return Encoding.UTF8.GetString(ptr, length); + } + + public static bool operator ==(cstring left, cstring right) + { + return left.Equals(right); + } + + public static bool operator !=(cstring left, cstring right) + { + return !(left == right); + } +} diff --git a/src/ThridParty/Ghost.Ufbx/ufbx_string.cs b/src/ThridParty/Ghost.Ufbx/ufbx_string.cs new file mode 100644 index 0000000..2df28fb --- /dev/null +++ b/src/ThridParty/Ghost.Ufbx/ufbx_string.cs @@ -0,0 +1,21 @@ +using System.Text; + +namespace Ghost.Ufbx; + +public unsafe partial struct ufbx_string +{ + public readonly ReadOnlySpan AsSpan() + { + if (data == null || length == 0) + return ReadOnlySpan.Empty; + return new ReadOnlySpan((byte*)data, checked((int)length)); + } + + public static implicit operator ReadOnlySpan(ufbx_string s) => s.AsSpan(); + + public override readonly string ToString() + { + var span = AsSpan(); + return span.IsEmpty ? string.Empty : Encoding.UTF8.GetString(span); + } +} \ No newline at end of file diff --git a/src/Tools/Ghost.NativeWrapperGen/Config/WrapperConfig.cs b/src/Tools/Ghost.NativeWrapperGen/Config/WrapperConfig.cs new file mode 100644 index 0000000..d5f6100 --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Config/WrapperConfig.cs @@ -0,0 +1,108 @@ +namespace Ghost.NativeWrapperGen.Config; + +public sealed class WrapperConfig +{ + public required string LibraryName { get; init; } + public required string NativeNamespace { get; init; } + public required string WrapperNamespace { get; init; } + public required string NativeTypePrefix { get; init; } + public string? StaticApiClassName { get; init; } + public List SkipTypes { get; init; } = []; + public Dictionary TypeNameOverrides { get; init; } = new(StringComparer.Ordinal); + public Dictionary PublicTypeOverrides { get; init; } = new(StringComparer.Ordinal); + public WrapperKindsConfig Wrappers { get; init; } = new(); + public SpecialTypesConfig SpecialTypes { get; init; } = new(); + public List OwnedTypes { get; init; } = []; + /// + /// Manual overrides for specific functions (adapters, special parameters, etc.). + /// Functions not listed here are auto-routed by the 3-rule dispatch logic. + /// + public List StaticMethods { get; init; } = []; + public List MarshalledTypes { get; init; } = []; + public List PartialTypes { get; init; } = []; + /// + /// Native types that are treated as plain value types in wrapper land (not wrapped in a pointer struct). + /// Functions returning or taking these as non-pointer params pass them by value. + /// + public List SkipFunctionPrefixes { get; init; } = []; +} + +public sealed class WrapperKindsConfig +{ + public string DefaultKind { get; init; } = "struct"; + public string DefaultOwnedKind { get; init; } = "class"; + public Dictionary Kinds { get; init; } = new(StringComparer.Ordinal); +} + +public sealed class SpecialTypesConfig +{ + public List Strings { get; init; } = []; + public List Blobs { get; init; } = []; +} + +public sealed class StringTypeConfig +{ + public required string Type { get; init; } + public string DataField { get; init; } = "data"; + public string LengthField { get; init; } = "length"; + public int CharSize { get; init; } = 8; + public string Encoding { get; init; } = "utf8"; + public bool EmitRawSpanProperty { get; init; } = true; + public bool EmitStringProperty { get; init; } = true; +} + +public sealed class BlobTypeConfig +{ + public required string Type { get; init; } + public string DataField { get; init; } = "data"; + public string LengthField { get; init; } = "size"; + public string ElementType { get; init; } = "byte"; +} + +public sealed class OwnedTypeConfig +{ + public required string NativeType { get; init; } + public string? FreeFunction { get; init; } + public string? RetainFunction { get; init; } + public string? WrapperKind { get; init; } + public string? StaticType { get; init; } +} + +public sealed class StaticMethodConfig +{ + public required string NativeFunction { get; init; } + public string? MethodName { get; init; } + public string? StaticType { get; init; } + public bool ThrowOnNullReturn { get; init; } + public string? FailureMessageMember { get; init; } + public List Parameters { get; init; } = []; +} + +public sealed class StaticParameterConfig +{ + public required string Native { get; init; } + public required string Adapter { get; init; } + public string? PublicName { get; init; } + public string? Type { get; init; } + public string? Source { get; init; } + public bool OptionalDefault { get; init; } +} + +public sealed class MarshalledTypeConfig +{ + public required string NativeType { get; init; } + /// + /// Fields that need special (user-implemented partial) marshalling logic. + /// The generator emits a backing field + partial property stub for these; + /// the Dispose() partial stub is always emitted so the user can free them. + /// + public List MarshalledProperties { get; init; } = []; +} + +public sealed class MarshalledPropertyConfig +{ + /// Native field name (snake_case). + public required string Native { get; init; } + /// The C# wrapper type for this field (e.g. "cstring"). + public required string Type { get; init; } +} diff --git a/src/Tools/Ghost.NativeWrapperGen/Emit/CodeWriter.cs b/src/Tools/Ghost.NativeWrapperGen/Emit/CodeWriter.cs new file mode 100644 index 0000000..49df06a --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Emit/CodeWriter.cs @@ -0,0 +1,44 @@ +using System.Text; + +namespace Ghost.NativeWrapperGen.Emit; + +internal sealed class CodeWriter +{ + private readonly StringBuilder _builder = new(); + private int _indent; + + public void WriteLine(string line = "") + { + if (line.Length == 0) + { + _builder.AppendLine(); + return; + } + + _builder.Append(' ', _indent * 4); + _builder.AppendLine(line); + } + + public IDisposable IndentScope() + { + _indent++; + return new Scope(this); + } + + public override string ToString() => _builder.ToString(); + + private sealed class Scope : IDisposable + { + private readonly CodeWriter _writer; + + public Scope(CodeWriter writer) + { + _writer = writer; + } + + public void Dispose() + { + _writer._indent--; + } + } +} diff --git a/src/Tools/Ghost.NativeWrapperGen/Emit/GeneratedFile.cs b/src/Tools/Ghost.NativeWrapperGen/Emit/GeneratedFile.cs new file mode 100644 index 0000000..5d8204e --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Emit/GeneratedFile.cs @@ -0,0 +1,7 @@ +namespace Ghost.NativeWrapperGen.Emit; + +public sealed class GeneratedFile +{ + public required string FileName { get; init; } + public required string Content { get; init; } +} diff --git a/src/Tools/Ghost.NativeWrapperGen/Emit/WrapperGeneratorEmitter.cs b/src/Tools/Ghost.NativeWrapperGen/Emit/WrapperGeneratorEmitter.cs new file mode 100644 index 0000000..bce31a3 --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Emit/WrapperGeneratorEmitter.cs @@ -0,0 +1,1090 @@ +using Ghost.NativeWrapperGen.Config; +using Ghost.NativeWrapperGen.Model; +using Ghost.NativeWrapperGen.Parsing; +using Ghost.NativeWrapperGen.Transform; + +namespace Ghost.NativeWrapperGen.Emit; + +public sealed class WrapperGeneratorEmitter +{ + public IEnumerable Emit(NativeLibrary library, WrapperConfig config) + { + var naming = new NamingConventions(config); + var resolver = new PublicTypeResolver(library, config, naming); + var ownedTypes = config.OwnedTypes.ToDictionary(static o => o.NativeType, StringComparer.Ordinal); + var marshalledTypes = config.MarshalledTypes.ToDictionary(static m => m.NativeType, StringComparer.Ordinal); + var partialTypes = new HashSet(config.PartialTypes, StringComparer.Ordinal); + var manualMethods = config.StaticMethods.ToDictionary(static m => m.NativeFunction, StringComparer.Ordinal); + + yield return EmitHelpers(config); + + foreach (var @struct in library.Structs.Where(static s => !s.Name.StartsWith("_", StringComparison.Ordinal)).OrderBy(static s => s.Name, StringComparer.Ordinal)) + { + if (@struct.IsList) + { + if (@struct.IsPointerList && @struct.ListElementType is not null && resolver.HasWrapper(@struct.ListElementType)) + { + yield return EmitPointerList(config, naming, @struct); + } + else if (string.Equals(@struct.ListElementType, "void", StringComparison.Ordinal)) + { + yield return EmitVoidList(config, naming, @struct); + } + + continue; + } + + ownedTypes.TryGetValue(@struct.Name, out var owned); + marshalledTypes.TryGetValue(@struct.Name, out var marshalled); + var isPartialType = partialTypes.Contains(@struct.Name); + + if (marshalled is not null) + { + yield return EmitMarshalledWrapper(library, config, naming, resolver, @struct, marshalled, owned); + } + else + { + yield return EmitWrapper(library, config, naming, resolver, @struct, owned, isPartialType, manualMethods); + } + } + + yield return EmitAutoStaticApi(library, config, naming, resolver, manualMethods); + } + + // ─── Helpers file ──────────────────────────────────────────────────────── + + private static GeneratedFile EmitHelpers(WrapperConfig config) + { + var writer = new CodeWriter(); + writer.WriteLine("using System.Text;"); + writer.WriteLine(); + writer.WriteLine($"namespace {config.WrapperNamespace};"); + writer.WriteLine(); + writer.WriteLine("internal static unsafe class NativeWrapperHelpers"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + foreach (var stringType in config.SpecialTypes.Strings) + { + EmitStringHelpers(writer, stringType); + writer.WriteLine(); + } + + foreach (var blobType in config.SpecialTypes.Blobs) + { + EmitBlobHelpers(writer, blobType); + writer.WriteLine(); + } + + writer.WriteLine("public static void ThrowIfOutOfRange(int index, int count)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("if ((uint)index >= (uint)count)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("throw new ArgumentOutOfRangeException(nameof(index));"); + } + writer.WriteLine("}"); + } + writer.WriteLine("}"); + } + writer.WriteLine("}"); + + return new GeneratedFile + { + FileName = "NativeWrapperHelpers.nativegen.cs", + Content = writer.ToString(), + }; + } + + private static void EmitStringHelpers(CodeWriter writer, StringTypeConfig config) + { + writer.WriteLine($"public static ReadOnlySpan AsByteSpan({config.Type} value)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine($"if (value.{config.DataField} == null || value.{config.LengthField} == 0)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("return ReadOnlySpan.Empty;"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine($"return new ReadOnlySpan((byte*)value.{config.DataField}, checked((int)value.{config.LengthField}) * {Math.Max(1, config.CharSize / 8)});"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine($"public static string GetString({config.Type} value)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("var bytes = AsByteSpan(value);"); + writer.WriteLine("if (bytes.IsEmpty)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("return string.Empty;"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine(config.Encoding.ToLowerInvariant() switch + { + "utf16" => "return Encoding.Unicode.GetString(bytes);", + "utf32" => "return Encoding.UTF32.GetString(bytes);", + _ => "return Encoding.UTF8.GetString(bytes);", + }); + } + writer.WriteLine("}"); + } + + private static void EmitBlobHelpers(CodeWriter writer, BlobTypeConfig config) + { + writer.WriteLine($"public static ReadOnlySpan<{config.ElementType}> AsSpan({config.Type} value)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine($"if (value.{config.DataField} == null || value.{config.LengthField} == 0)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine($"return ReadOnlySpan<{config.ElementType}>.Empty;"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine($"return new ReadOnlySpan<{config.ElementType}>(value.{config.DataField}, checked((int)value.{config.LengthField}));"); + } + writer.WriteLine("}"); + } + + // ─── Marshalled type wrapper (heap-pointer struct) ──────────────────────── + + private static GeneratedFile EmitMarshalledWrapper(NativeLibrary library, WrapperConfig config, NamingConventions naming, PublicTypeResolver resolver, NativeStruct @struct, MarshalledTypeConfig marshalled, OwnedTypeConfig? owned) + { + var writer = new CodeWriter(); + writer.WriteLine($"namespace {config.WrapperNamespace};"); + writer.WriteLine(); + + var wrapperName = naming.GetWrapperTypeName(@struct.Name); + var wrapperKind = GetWrapperKind(config, @struct.Name, owned); + var marshalledPropsByNative = marshalled.MarshalledProperties.ToDictionary(static p => p.Native, StringComparer.Ordinal); + + writer.WriteLine($"public unsafe partial {wrapperKind} {wrapperName} : System.IDisposable"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + // Pointer + alloc flag + writer.WriteLine($"private {@struct.Name}* _ptr;"); + writer.WriteLine("private bool _csAlloc;"); + writer.WriteLine(); + + // Default constructor — alloc on heap, zero-fill + writer.WriteLine($"public {wrapperName}()"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine($"_ptr = ({@struct.Name}*)System.Runtime.InteropServices.NativeMemory.AllocZeroed((nuint)sizeof({@struct.Name}));"); + writer.WriteLine("_csAlloc = true;"); + } + writer.WriteLine("}"); + writer.WriteLine(); + + // Internal constructor from existing pointer (e.g. native API returned it) + writer.WriteLine($"internal {wrapperName}({@struct.Name}* ptr)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("_ptr = ptr;"); + writer.WriteLine("_csAlloc = false;"); + } + writer.WriteLine("}"); + writer.WriteLine(); + + writer.WriteLine("public bool IsNull => _ptr == null;"); + writer.WriteLine(); + + // Partial Dispose stub — hand-written impl frees cstrings + conditionally frees _ptr + writer.WriteLine("public partial void Dispose();"); + writer.WriteLine(); + + // Emit properties for each member + foreach (var member in @struct.Members.Where(static m => + m.Name != "Anonymous" + && !m.Name.StartsWith("_", StringComparison.Ordinal) + && !m.TypeName.StartsWith("_", StringComparison.Ordinal) + && !m.TypeName.Contains("<", StringComparison.Ordinal) + && !m.TypeName.Contains("ref ", StringComparison.Ordinal))) + { + EmitMarshalledMember(writer, config, naming, resolver, wrapperName, member, marshalledPropsByNative); + } + + writer.WriteLine($"internal {@struct.Name}* GetUnsafePtr() => _ptr;"); + } + writer.WriteLine("}"); + + return new GeneratedFile + { + FileName = $"{wrapperName}.nativegen.cs", + Content = writer.ToString(), + }; + } + + private static void EmitMarshalledMember(CodeWriter writer, WrapperConfig config, NamingConventions naming, PublicTypeResolver resolver, string wrapperName, NativeMember member, Dictionary marshalledProps) + { + var propertyName = GetSafePropertyName(wrapperName, naming.GetPropertyName(member.Name)); + + // Marshalled property → emit partial property stub + backing field (hand-written impl manages cstring lifetime) + if (marshalledProps.TryGetValue(member.Name, out var marshalledProp)) + { + var fieldName = "_" + char.ToLowerInvariant(propertyName[0]) + propertyName[1..]; + writer.WriteLine($"private {marshalledProp.Type} {fieldName};"); + writer.WriteLine($"public partial {marshalledProp.Type} {propertyName} {{ get; set; }}"); + writer.WriteLine(); + return; + } + + var pointerDepth = BindingParser.GetPointerDepth(member.TypeName); + + // Skip function pointer and deep pointer fields + if (pointerDepth > 1) + { + return; + } + + // String special type → read-only helpers via pointer dereference + var stringType = config.SpecialTypes.Strings.FirstOrDefault(s => s.Type == member.TypeName); + if (stringType is not null) + { + if (stringType.EmitRawSpanProperty) + { + writer.WriteLine($"public ReadOnlySpan {propertyName}Bytes => NativeWrapperHelpers.AsByteSpan(_ptr->{member.Name});"); + } + if (stringType.EmitStringProperty) + { + writer.WriteLine($"public string {propertyName} => NativeWrapperHelpers.GetString(_ptr->{member.Name});"); + } + writer.WriteLine(); + return; + } + + // Blob special type → read-only span via pointer dereference + var blobType = config.SpecialTypes.Blobs.FirstOrDefault(b => b.Type == member.TypeName); + if (blobType is not null) + { + writer.WriteLine($"public ReadOnlySpan<{blobType.ElementType}> {propertyName} => NativeWrapperHelpers.AsSpan(_ptr->{member.Name});"); + writer.WriteLine(); + return; + } + + // Pointer field (depth == 1) — expose raw pointer as read/write + if (pointerDepth == 1) + { + writer.WriteLine($"public {member.TypeName} {propertyName} {{ get => _ptr->{member.Name}; set => _ptr->{member.Name} = value; }}"); + writer.WriteLine(); + return; + } + + // Plain value field — direct read/write through pointer + writer.WriteLine($"public {resolver.GetPublicType(member.TypeName)} {propertyName} {{ get => _ptr->{member.Name}; set => _ptr->{member.Name} = value; }}"); + writer.WriteLine(); + } + + // ─── Pointer-based wrapper (read-only view) ─────────────────────────────── + + private static GeneratedFile EmitWrapper(NativeLibrary library, WrapperConfig config, NamingConventions naming, PublicTypeResolver resolver, NativeStruct @struct, OwnedTypeConfig? owned, bool isPartialType, Dictionary manualMethods) + { + var writer = new CodeWriter(); + writer.WriteLine($"namespace {config.WrapperNamespace};"); + writer.WriteLine(); + + var wrapperName = naming.GetWrapperTypeName(@struct.Name); + var wrapperKind = GetWrapperKind(config, @struct.Name, owned); + var implementsIDisposable = wrapperKind == "class" && !string.IsNullOrWhiteSpace(owned?.FreeFunction); + var partialKeyword = isPartialType ? "partial " : string.Empty; + + writer.WriteLine($"public unsafe {partialKeyword}{GetWrapperDeclaration(wrapperName, wrapperKind, implementsIDisposable)}"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine(GetPointerFieldDeclaration(@struct.Name, wrapperKind)); + writer.WriteLine(); + writer.WriteLine($"internal {wrapperName}({@struct.Name}* ptr)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("_ptr = ptr;"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine("public bool IsNull => _ptr == null;"); + writer.WriteLine(); + + if (!string.IsNullOrWhiteSpace(owned?.FreeFunction)) + { + writer.WriteLine("public void Dispose()"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("if (_ptr != null)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine($"Api.{owned.FreeFunction}(_ptr);"); + writer.WriteLine("_ptr = null;"); + } + writer.WriteLine("}"); + } + writer.WriteLine("}"); + writer.WriteLine(); + } + + // Emit instance methods auto-routed to this wrapper type + foreach (var func in library.Functions.Where(f => f.IsDllImport)) + { + var routing = ResolveAutoTarget(library, config, naming, func, manualMethods); + if (routing.TargetType != wrapperName) + { + continue; + } + + if (manualMethods.TryGetValue(func.Name, out var manual)) + { + EmitStaticMethod(writer, library, config, naming, resolver, manual, routing.Kind == RoutingKind.InstanceMethod ? wrapperName : null); + } + else + { + EmitAutoMethod(writer, library, config, naming, resolver, func, routing.Kind == RoutingKind.InstanceMethod ? wrapperName : null); + } + writer.WriteLine(); + } + + foreach (var member in @struct.Members.Where(static m => m.Name != "Anonymous" && !m.Name.StartsWith("_", StringComparison.Ordinal))) + { + EmitMember(writer, library, config, naming, resolver, wrapperName, member); + } + + writer.WriteLine($"internal {@struct.Name}* GetUnsafePtr() => _ptr;"); + } + writer.WriteLine("}"); + + return new GeneratedFile + { + FileName = $"{wrapperName}.nativegen.cs", + Content = writer.ToString(), + }; + } + + // ─── Member emission (pointer-based) ───────────────────────────────────── + + private static void EmitMember(CodeWriter writer, NativeLibrary library, WrapperConfig config, NamingConventions naming, PublicTypeResolver resolver, string wrapperName, NativeMember member) + { + if (member.TypeName.StartsWith("_", StringComparison.Ordinal)) + { + return; + } + + if (member.TypeName.Contains("<", StringComparison.Ordinal) || member.TypeName.Contains("ref ", StringComparison.Ordinal)) + { + return; + } + + var propertyName = GetSafePropertyName(wrapperName, naming.GetPropertyName(member.Name)); + var pointerDepth = BindingParser.GetPointerDepth(member.TypeName); + var baseType = BindingParser.TrimPointers(member.TypeName); + + var stringType = config.SpecialTypes.Strings.FirstOrDefault(s => s.Type == member.TypeName); + if (stringType is not null) + { + if (stringType.EmitRawSpanProperty) + { + writer.WriteLine($"public ReadOnlySpan {propertyName}Bytes => NativeWrapperHelpers.AsByteSpan(_ptr->{member.Name});"); + } + + if (stringType.EmitStringProperty) + { + writer.WriteLine($"public string {propertyName} => NativeWrapperHelpers.GetString(_ptr->{member.Name});"); + } + + writer.WriteLine(); + return; + } + + var blobType = config.SpecialTypes.Blobs.FirstOrDefault(b => b.Type == member.TypeName); + if (blobType is not null) + { + writer.WriteLine($"public ReadOnlySpan<{blobType.ElementType}> {propertyName} => NativeWrapperHelpers.AsSpan(_ptr->{member.Name});"); + writer.WriteLine(); + return; + } + + if (library.StructsByName.TryGetValue(baseType, out var listStruct) && listStruct.IsList) + { + EmitListMember(writer, naming, resolver, member, listStruct, propertyName); + return; + } + + if (pointerDepth == 1 && resolver.HasWrapper(baseType)) + { + var wrapperType = resolver.GetPublicType(member.TypeName); + writer.WriteLine($"public bool Has{propertyName} => _ptr->{member.Name} != null;"); + writer.WriteLine($"public {wrapperType} {propertyName} => _ptr->{member.Name} != null ? new(_ptr->{member.Name}) : throw new InvalidOperationException(\"{propertyName} is null.\");"); + writer.WriteLine(); + return; + } + + if (pointerDepth > 0) + { + writer.WriteLine($"public {member.TypeName} {propertyName} => _ptr->{member.Name};"); + writer.WriteLine(); + return; + } + + if (resolver.HasWrapper(baseType)) + { + var wrapperType = naming.GetWrapperTypeName(baseType); + writer.WriteLine($"public {wrapperType} {propertyName} => new(({baseType}*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref _ptr->{member.Name}));"); + writer.WriteLine(); + return; + } + + writer.WriteLine($"public {resolver.GetPublicType(member.TypeName)} {propertyName} => _ptr->{member.Name};"); + writer.WriteLine(); + } + + private static void EmitListMember(CodeWriter writer, NamingConventions naming, PublicTypeResolver resolver, NativeMember member, NativeStruct listStruct, string propertyName) + { + if (listStruct.ListElementType is null) + { + writer.WriteLine($"public {member.TypeName} {propertyName} => _ptr->{member.Name};"); + writer.WriteLine(); + return; + } + + if (listStruct.IsPointerList && resolver.HasWrapper(listStruct.ListElementType)) + { + var listWrapperName = naming.GetWrapperTypeName(listStruct.Name); + writer.WriteLine($"public {listWrapperName} {propertyName} => new(_ptr->{member.Name}.data, _ptr->{member.Name}.count);"); + writer.WriteLine(); + return; + } + + if (string.Equals(listStruct.ListElementType, "void", StringComparison.Ordinal)) + { + var listWrapperName = naming.GetWrapperTypeName(listStruct.Name); + writer.WriteLine($"public {listWrapperName} {propertyName} => new(_ptr->{member.Name}.data, _ptr->{member.Name}.count);"); + writer.WriteLine(); + return; + } + + var elementType = resolver.GetPublicType(listStruct.ListElementType); + writer.WriteLine($"public ReadOnlySpan<{elementType}> {propertyName} => _ptr->{member.Name}.data == null ? ReadOnlySpan<{elementType}>.Empty : new ReadOnlySpan<{elementType}>(_ptr->{member.Name}.data, checked((int)_ptr->{member.Name}.count));"); + writer.WriteLine(); + } + + // ─── List wrappers ──────────────────────────────────────────────────────── + + private static GeneratedFile EmitPointerList(WrapperConfig config, NamingConventions naming, NativeStruct listStruct) + { + var writer = new CodeWriter(); + var wrapperName = naming.GetWrapperTypeName(listStruct.Name); + var elementType = listStruct.ListElementType!; + var elementWrapperName = naming.GetWrapperTypeName(elementType); + + writer.WriteLine($"namespace {config.WrapperNamespace};"); + writer.WriteLine(); + writer.WriteLine($"public unsafe readonly ref struct {wrapperName}"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine($"private readonly {elementType}** _data;"); + writer.WriteLine("public int Count { get; }"); + writer.WriteLine(); + writer.WriteLine($"internal {wrapperName}({elementType}** data, nuint count)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("_data = data;"); + writer.WriteLine("Count = checked((int)count);"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine($"public {elementWrapperName} this[int index]"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("get"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("NativeWrapperHelpers.ThrowIfOutOfRange(index, Count);"); + writer.WriteLine("return new(_data[index]);"); + } + writer.WriteLine("}"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine("public Enumerator GetEnumerator() => new(_data, Count);"); + writer.WriteLine(); + writer.WriteLine("public unsafe ref struct Enumerator"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine($"private readonly {elementType}** _data;"); + writer.WriteLine("private readonly int _count;"); + writer.WriteLine("private int _index;"); + writer.WriteLine(); + writer.WriteLine($"internal Enumerator({elementType}** data, int count)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("_data = data;"); + writer.WriteLine("_count = count;"); + writer.WriteLine("_index = -1;"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine($"public {elementWrapperName} Current => new(_data[_index]);"); + writer.WriteLine(); + writer.WriteLine("public bool MoveNext()"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("var next = _index + 1;"); + writer.WriteLine("if (next >= _count)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("return false;"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine("_index = next;"); + writer.WriteLine("return true;"); + } + writer.WriteLine("}"); + } + writer.WriteLine("}"); + } + writer.WriteLine("}"); + + return new GeneratedFile + { + FileName = $"{wrapperName}.nativegen.cs", + Content = writer.ToString(), + }; + } + + private static GeneratedFile EmitVoidList(WrapperConfig config, NamingConventions naming, NativeStruct listStruct) + { + var writer = new CodeWriter(); + var wrapperName = naming.GetWrapperTypeName(listStruct.Name); + + writer.WriteLine($"namespace {config.WrapperNamespace};"); + writer.WriteLine(); + writer.WriteLine($"public unsafe readonly ref struct {wrapperName}"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("private readonly void* _data;"); + writer.WriteLine("public int Count { get; }"); + writer.WriteLine(); + writer.WriteLine($"internal {wrapperName}(void* data, nuint count)"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + writer.WriteLine("_data = data;"); + writer.WriteLine("Count = checked((int)count);"); + } + writer.WriteLine("}"); + writer.WriteLine(); + writer.WriteLine("public void* Data => _data;"); + } + writer.WriteLine("}"); + + return new GeneratedFile + { + FileName = $"{wrapperName}.nativegen.cs", + Content = writer.ToString(), + }; + } + + // ─── Auto-dispatch static API ───────────────────────────────────────────── + + private static GeneratedFile EmitAutoStaticApi(NativeLibrary library, WrapperConfig config, NamingConventions naming, PublicTypeResolver resolver, Dictionary manualMethods) + { + var staticTypeName = config.StaticApiClassName ?? (config.LibraryName + "Global"); + var writer = new CodeWriter(); + + writer.WriteLine($"namespace {config.WrapperNamespace};"); + writer.WriteLine(); + writer.WriteLine($"public static unsafe class {staticTypeName}"); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + foreach (var func in library.Functions.Where(static f => f.IsDllImport).OrderBy(static f => f.Name, StringComparer.Ordinal)) + { + var routing = ResolveAutoTarget(library, config, naming, func, manualMethods); + if (routing.TargetType != staticTypeName) + { + continue; + } + + if (manualMethods.TryGetValue(func.Name, out var manual)) + { + EmitStaticMethod(writer, library, config, naming, resolver, manual, null); + } + else + { + EmitAutoMethod(writer, library, config, naming, resolver, func, null); + } + writer.WriteLine(); + } + } + writer.WriteLine("}"); + + return new GeneratedFile + { + FileName = $"{staticTypeName}.nativegen.cs", + Content = writer.ToString(), + }; + } + + // ─── Auto routing ───────────────────────────────────────────────────────── + + private enum RoutingKind { GlobalStatic, InstanceMethod, StaticOnType } + + private sealed record RoutingResult(string TargetType, RoutingKind Kind); + + /// + /// Classifies a native function into one of three routing categories: + /// a) TKnown* func(somethingElse...) → return-type wrapper class (static factory) + /// b) TKnown1 func(TKnown0*, ...) → first-param wrapper type (instance method) + /// c) everything else → global static class + /// Manual configs that set StaticType override the auto-routing. + /// Manual configs with selfPointer adapter force route (b). + /// + private static RoutingResult ResolveAutoTarget(NativeLibrary library, WrapperConfig config, NamingConventions naming, NativeFunction func, Dictionary manualMethods) + { + var staticTypeName = config.StaticApiClassName ?? (config.LibraryName + "Global"); + + // Manual override: StaticType wins + if (manualMethods.TryGetValue(func.Name, out var manual) && !string.IsNullOrWhiteSpace(manual.StaticType)) + { + return new(manual.StaticType, RoutingKind.StaticOnType); + } + + // Manual override: selfPointer wins (route to that type as instance method) + if (manualMethods.TryGetValue(func.Name, out manual)) + { + var selfParam = manual.Parameters.FirstOrDefault(static p => p.Adapter == "selfPointer"); + if (selfParam is not null) + { + var nativeParam = func.Parameters.FirstOrDefault(p => string.Equals(p.Name, selfParam.Native, StringComparison.Ordinal)); + if (nativeParam is not null) + { + var baseType = BindingParser.TrimPointers(nativeParam.TypeName); + if (library.StructsByName.ContainsKey(baseType)) + { + return new(naming.GetWrapperTypeName(baseType), RoutingKind.InstanceMethod); + } + } + } + } + + // Rule (b): first param is T* where T is a known wrapper type → instance on T + if (func.Parameters.Count > 0) + { + var firstParam = func.Parameters[0]; + var firstBase = BindingParser.TrimPointers(firstParam.TypeName); + if (BindingParser.GetPointerDepth(firstParam.TypeName) == 1 && library.StructsByName.ContainsKey(firstBase)) + { + return new(naming.GetWrapperTypeName(firstBase), RoutingKind.InstanceMethod); + } + } + + // Rule (a): return type is T* where T is a known wrapper type → static on T + var returnPointerDepth = BindingParser.GetPointerDepth(func.ReturnType); + if (returnPointerDepth == 1) + { + var returnBase = BindingParser.TrimPointers(func.ReturnType); + if (library.StructsByName.ContainsKey(returnBase)) + { + return new(naming.GetWrapperTypeName(returnBase), RoutingKind.StaticOnType); + } + } + + // Rule (c): global static + return new(staticTypeName, RoutingKind.GlobalStatic); + } + + // ─── Auto method emission ───────────────────────────────────────────────── + + private static void EmitAutoMethod(CodeWriter writer, NativeLibrary library, WrapperConfig config, NamingConventions naming, PublicTypeResolver resolver, NativeFunction func, string? instanceTypeName) + { + var isInstanceMethod = instanceTypeName is not null; + + // Build parameter list, skipping the first param if it's the self pointer + var parameters = new List(); + var argumentExpressions = new List(); + var marshalledTypes = config.MarshalledTypes.ToDictionary(static m => m.NativeType, StringComparer.Ordinal); + var skipFirst = isInstanceMethod; + + foreach (var param in func.Parameters) + { + if (skipFirst) + { + skipFirst = false; + argumentExpressions.Add("_ptr"); + continue; + } + + var publicName = NamingConventions.ToPascalCase(param.Name); + publicName = char.ToLowerInvariant(publicName[0]) + publicName[1..]; + + var pointerDepth = BindingParser.GetPointerDepth(param.TypeName); + var baseType = BindingParser.TrimPointers(param.TypeName); + + if (pointerDepth == 1 && marshalledTypes.TryGetValue(baseType, out _)) + { + // Pass marshalled wrapper by pointer directly — no copy needed + var wrapperType = naming.GetWrapperTypeName(baseType); + parameters.Add($"{wrapperType} {publicName}"); + argumentExpressions.Add($"{publicName}.GetUnsafePtr()"); + } + else if (pointerDepth == 1 && library.StructsByName.ContainsKey(baseType)) + { + var wrapperType = naming.GetWrapperTypeName(baseType); + parameters.Add($"{wrapperType} {publicName}"); + argumentExpressions.Add($"{publicName}.GetUnsafePtr()"); + } + else + { + parameters.Add($"{param.TypeName} {publicName}"); + argumentExpressions.Add(publicName); + } + } + + var (returnType, returnConversion) = ResolveReturnConversion(config, resolver, naming, func.ReturnType); + var methodName = naming.GetWrapperTypeName(func.Name); + var staticKeyword = isInstanceMethod ? string.Empty : "static "; + var signatureLine = $"public {staticKeyword}{returnType} {methodName}({string.Join(", ", parameters)})"; + + writer.WriteLine(signatureLine); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + var callExpression = $"Api.{func.Name}({string.Join(", ", argumentExpressions)})"; + var returnsWrappedType = BindingParser.GetPointerDepth(func.ReturnType) == 1 && resolver.HasWrapper(BindingParser.TrimPointers(func.ReturnType)); + var returnsVoid = string.Equals(func.ReturnType, "void", StringComparison.Ordinal); + + if (returnsWrappedType) + { + writer.WriteLine($"return new({callExpression});"); + } + else if (returnsVoid) + { + writer.WriteLine($"{callExpression};"); + } + else if (returnConversion is not null) + { + writer.WriteLine($"return {string.Format(returnConversion, callExpression)};"); + } + else + { + writer.WriteLine($"return {callExpression};"); + } + } + writer.WriteLine("}"); + } + + // ─── Manual method emission ─────────────────────────────────────────────── + + private static void EmitStaticMethod(CodeWriter writer, NativeLibrary library, WrapperConfig config, NamingConventions naming, PublicTypeResolver resolver, StaticMethodConfig methodConfig, string? wrapperName) + { + if (!library.FunctionsByName.TryGetValue(methodConfig.NativeFunction, out var nativeFunction)) + { + return; + } + + var signature = BuildMethodSignature(library, config, naming, resolver, methodConfig, nativeFunction, wrapperName); + writer.WriteLine(signature.SignatureLine); + writer.WriteLine("{"); + using (writer.IndentScope()) + { + foreach (var line in signature.BodyLines) + { + writer.WriteLine(line); + } + } + writer.WriteLine("}"); + } + + private static GeneratedMethod BuildMethodSignature(NativeLibrary library, WrapperConfig config, NamingConventions naming, PublicTypeResolver resolver, StaticMethodConfig methodConfig, NativeFunction nativeFunction, string? wrapperName) + { + var parameters = new List(); + var preCallLines = new List(); + var argumentExpressions = new List(); + string? pendingSpanSource = null; + string? failureVariable = null; + var isInstanceMethod = false; + + foreach (var parameter in nativeFunction.Parameters) + { + var configParameter = methodConfig.Parameters.FirstOrDefault(p => p.Native == parameter.Name); + if (configParameter is null) + { + // Implicit selfPointer: first unconfigured T* param where T is a known struct + if (!isInstanceMethod && argumentExpressions.Count == 0) + { + var pd = BindingParser.GetPointerDepth(parameter.TypeName); + var bt = BindingParser.TrimPointers(parameter.TypeName); + if (pd == 1 && library.StructsByName.ContainsKey(bt)) + { + isInstanceMethod = true; + argumentExpressions.Add("_ptr"); + continue; + } + } + + argumentExpressions.Add(parameter.Name); + parameters.Add($"{parameter.TypeName} {parameter.Name}"); + continue; + } + + var publicName = configParameter.PublicName ?? NamingConventions.ToPascalCase(parameter.Name); + publicName = char.ToLowerInvariant(publicName[0]) + publicName[1..]; + + switch (configParameter.Adapter) + { + case "selfPointer": + isInstanceMethod = true; + argumentExpressions.Add("_ptr"); + break; + case "utf8Path": + parameters.Add($"ReadOnlySpan {publicName}"); + preCallLines.Add($"fixed (byte* {publicName}Ptr = {publicName})"); + argumentExpressions.Add($"(sbyte*){publicName}Ptr"); + pendingSpanSource = publicName; + break; + case "utf8Length": + argumentExpressions.Add($"(nuint){configParameter.Source ?? pendingSpanSource}.Length"); + break; + case "byteSpan": + parameters.Add($"ReadOnlySpan {publicName}"); + preCallLines.Add($"fixed (byte* {publicName}Ptr = {publicName})"); + argumentExpressions.Add($"{publicName}Ptr"); + pendingSpanSource = publicName; + break; + case "byteSpanLength": + argumentExpressions.Add($"(nuint){configParameter.Source ?? pendingSpanSource}.Length"); + break; + case "inValue": + { + var typeName = configParameter.Type ?? parameter.TypeName.TrimEnd('*').Trim(); + var defaultValue = configParameter.OptionalDefault ? " = default" : string.Empty; + parameters.Add($"in {typeName} {publicName}{defaultValue}"); + preCallLines.Add($"var {publicName}Local = {publicName};"); + argumentExpressions.Add($"&{publicName}Local"); + break; + } + case "errorOut": + { + var typeName = configParameter.Type ?? parameter.TypeName.TrimEnd('*').Trim(); + failureVariable = publicName; + preCallLines.Add($"{typeName} {publicName} = default;"); + argumentExpressions.Add($"&{publicName}"); + break; + } + case "getPtr": + { + var typeName = configParameter.Type ?? parameter.TypeName.TrimEnd('*').Trim(); + parameters.Add($"{typeName} {publicName}"); + argumentExpressions.Add($"{publicName}.GetUnsafePtr()"); + break; + } + default: + parameters.Add($"{configParameter.Type ?? parameter.TypeName} {publicName}"); + argumentExpressions.Add(publicName); + break; + } + } + + var (returnType, returnConversion) = ResolveReturnConversion(config, resolver, naming, nativeFunction.ReturnType); + var methodName = methodConfig.MethodName ?? naming.GetWrapperTypeName(methodConfig.NativeFunction); + var staticKeyword = isInstanceMethod ? string.Empty : "static "; + var signatureLine = $"public {staticKeyword}{returnType} {methodName}({string.Join(", ", parameters)})"; + + var body = new List(); + var fixedLines = preCallLines.Where(static l => l.StartsWith("fixed ", StringComparison.Ordinal)).ToList(); + var normalLines = preCallLines.Where(static l => !l.StartsWith("fixed ", StringComparison.Ordinal)).ToList(); + body.AddRange(normalLines); + + if (fixedLines.Count > 0) + { + foreach (var fixedLine in fixedLines) + { + body.Add(fixedLine); + } + + body.Add("{"); + } + + var callExpression = $"Api.{nativeFunction.Name}({string.Join(", ", argumentExpressions)})"; + var returnsWrappedType = BindingParser.GetPointerDepth(nativeFunction.ReturnType) == 1 && resolver.HasWrapper(BindingParser.TrimPointers(nativeFunction.ReturnType)); + + if (returnsWrappedType) + { + body.Add($"var value = {callExpression};"); + if (methodConfig.ThrowOnNullReturn) + { + body.Add("if (value == null)"); + body.Add("{"); + if (!string.IsNullOrWhiteSpace(failureVariable) && !string.IsNullOrWhiteSpace(methodConfig.FailureMessageMember)) + { + body.Add($" throw new InvalidOperationException(NativeWrapperHelpers.GetString({failureVariable}.{methodConfig.FailureMessageMember}));"); + } + else + { + body.Add(" throw new InvalidOperationException(\"Native call failed.\");"); + } + body.Add("}"); + } + + body.Add("return new(value);"); + } + else if (string.Equals(nativeFunction.ReturnType, "void", StringComparison.Ordinal)) + { + body.Add($"{callExpression};"); + } + else if (returnConversion is not null) + { + body.Add($"return {string.Format(returnConversion, callExpression)};"); + } + else + { + body.Add($"return {callExpression};"); + } + + if (fixedLines.Count > 0) + { + body.Add("}"); + } + + return new GeneratedMethod(signatureLine, body); + } + + // ─── Helpers ────────────────────────────────────────────────────────────── + + /// + /// Returns (publicReturnType, conversionWrapper) where conversionWrapper is + /// a format string like "NativeWrapperHelpers.GetString({0})" if the native + /// return type is a special string/blob that needs conversion, or null otherwise. + /// + private static (string PublicType, string? ConversionFormat) ResolveReturnConversion( + WrapperConfig config, PublicTypeResolver resolver, NamingConventions naming, string nativeReturnType) + { + // Bare void + if (string.Equals(nativeReturnType, "void", StringComparison.Ordinal)) + { + return ("void", null); + } + + // Special string types (e.g. ufbx_string → string via GetString) + var stringType = config.SpecialTypes.Strings.FirstOrDefault(s => + string.Equals(s.Type, nativeReturnType, StringComparison.Ordinal)); + if (stringType is not null) + { + return ("string", "NativeWrapperHelpers.GetString({0})"); + } + + // Special blob types (e.g. ufbx_blob → ReadOnlySpan via AsSpan) + var blobType = config.SpecialTypes.Blobs.FirstOrDefault(b => + string.Equals(b.Type, nativeReturnType, StringComparison.Ordinal)); + if (blobType is not null) + { + return ($"ReadOnlySpan<{blobType.ElementType}>", "NativeWrapperHelpers.AsSpan({0})"); + } + + var publicType = ResolveGeneratedReturnType(resolver, naming, nativeReturnType); + return (publicType, null); + } + + private static string ResolveGeneratedReturnType(PublicTypeResolver resolver, NamingConventions naming, string nativeReturnType) + { + // Bare void — never convert to void* + if (string.Equals(nativeReturnType, "void", StringComparison.Ordinal)) + { + return "void"; + } + + var pointerDepth = BindingParser.GetPointerDepth(nativeReturnType); + if (pointerDepth == 1) + { + var baseType = BindingParser.TrimPointers(nativeReturnType); + if (resolver.HasWrapper(baseType)) + { + return naming.GetWrapperTypeName(baseType); + } + } + + return resolver.GetPublicType(nativeReturnType); + } + + private static string GetWrapperKind(WrapperConfig config, string nativeTypeName, OwnedTypeConfig? owned) + { + if (owned?.WrapperKind is not null) + { + return owned.WrapperKind; + } + + if (config.Wrappers.Kinds.TryGetValue(nativeTypeName, out var kind)) + { + return kind; + } + + return owned is null ? config.Wrappers.DefaultKind : config.Wrappers.DefaultOwnedKind; + } + + private static string GetWrapperDeclaration(string wrapperName, string wrapperKind, bool implementsIDisposable = false) + { + var baseDeclaration = wrapperKind switch + { + "class" => $"class {wrapperName}", + "ref struct" => $"ref struct {wrapperName}", + "readonly ref struct" => $"readonly ref struct {wrapperName}", + _ => $"struct {wrapperName}", + }; + + if (implementsIDisposable && wrapperKind == "class") + { + return $"{baseDeclaration} : IDisposable"; + } + + return baseDeclaration; + } + + private static string GetPointerFieldDeclaration(string nativeTypeName, string wrapperKind) + { + return wrapperKind switch + { + "class" => $"private {nativeTypeName}* _ptr;", + "ref struct" => $"private {nativeTypeName}* _ptr;", + "readonly ref struct" => $"private readonly {nativeTypeName}* _ptr;", + _ => $"private {nativeTypeName}* _ptr;", + }; + } + + private static string GetSafePropertyName(string wrapperName, string propertyName) + { + if (string.Equals(wrapperName, propertyName, StringComparison.Ordinal)) + { + return propertyName + "Value"; + } + + return propertyName; + } + + private sealed record GeneratedMethod(string SignatureLine, IReadOnlyList BodyLines); +} diff --git a/src/Tools/Ghost.NativeWrapperGen/Ghost.NativeWrapperGen.csproj b/src/Tools/Ghost.NativeWrapperGen/Ghost.NativeWrapperGen.csproj new file mode 100644 index 0000000..5da3cf6 --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Ghost.NativeWrapperGen.csproj @@ -0,0 +1,14 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/src/Tools/Ghost.NativeWrapperGen/Model/NativeLibrary.cs b/src/Tools/Ghost.NativeWrapperGen/Model/NativeLibrary.cs new file mode 100644 index 0000000..430b5ea --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Model/NativeLibrary.cs @@ -0,0 +1,55 @@ +namespace Ghost.NativeWrapperGen.Model; + +public sealed class NativeLibrary +{ + public required string NativeNamespace { get; init; } + public required IReadOnlyList Structs { get; init; } + public required IReadOnlyList Enums { get; init; } + public required IReadOnlyList Functions { get; init; } + public required IReadOnlyDictionary StructsByName { get; init; } + public required IReadOnlyDictionary FunctionsByName { get; init; } +} + +public sealed class NativeStruct +{ + public required string Name { get; init; } + public required string Namespace { get; init; } + public required IReadOnlyList Members { get; init; } + public required bool IsList { get; init; } + public required bool IsPointerList { get; init; } + public string? ListElementType { get; init; } + public required bool IsElementLike { get; init; } +} + +public sealed class NativeEnum +{ + public required string Name { get; init; } + public required IReadOnlyList Members { get; init; } +} + +public sealed class NativeFunction +{ + public required string Name { get; init; } + public required string ReturnType { get; init; } + public required IReadOnlyList Parameters { get; init; } + public required bool IsDllImport { get; init; } +} + +public sealed class NativeParameter +{ + public required string Name { get; init; } + public required string TypeName { get; init; } +} + +public sealed class NativeMember +{ + public required string Name { get; init; } + public required string TypeName { get; init; } + public required NativeMemberKind Kind { get; init; } +} + +public enum NativeMemberKind +{ + Field, + Property, +} diff --git a/src/Tools/Ghost.NativeWrapperGen/Parsing/BindingParser.cs b/src/Tools/Ghost.NativeWrapperGen/Parsing/BindingParser.cs new file mode 100644 index 0000000..be5a4c3 --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Parsing/BindingParser.cs @@ -0,0 +1,211 @@ +using Ghost.NativeWrapperGen.Config; +using Ghost.NativeWrapperGen.Model; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Ghost.NativeWrapperGen.Parsing; + +public sealed class BindingParser +{ + public NativeLibrary Parse(string inputDirectory, WrapperConfig config) + { + var structs = new List(); + var enums = new List(); + var functions = new List(); + + foreach (var filePath in Directory.GetFiles(inputDirectory, "*.cs", SearchOption.TopDirectoryOnly).OrderBy(static p => p, StringComparer.Ordinal)) + { + var text = File.ReadAllText(filePath); + var tree = CSharpSyntaxTree.ParseText(text); + var root = tree.GetRoot(); + var namespaceName = GetNamespace(root); + + foreach (var @struct in root.DescendantNodes().OfType()) + { + if (@struct.Parent is not NamespaceDeclarationSyntax && @struct.Parent is not FileScopedNamespaceDeclarationSyntax) + { + continue; + } + + if (config.SkipTypes.Contains(@struct.Identifier.ValueText, StringComparer.Ordinal)) + { + continue; + } + + var members = ParseMembers(@struct); + var listInfo = TryMatchList(members); + + structs.Add(new NativeStruct + { + Name = @struct.Identifier.ValueText, + Namespace = namespaceName, + Members = members, + IsList = listInfo.IsList, + IsPointerList = listInfo.IsPointerList, + ListElementType = listInfo.ListElementType, + IsElementLike = members.Any(static m => m.Name == "element" && m.TypeName == "ufbx_element"), + }); + } + + foreach (var @enum in root.DescendantNodes().OfType()) + { + if (@enum.Parent is not NamespaceDeclarationSyntax && @enum.Parent is not FileScopedNamespaceDeclarationSyntax) + { + continue; + } + + if (config.SkipTypes.Contains(@enum.Identifier.ValueText, StringComparer.Ordinal)) + { + continue; + } + + enums.Add(new NativeEnum + { + Name = @enum.Identifier.ValueText, + Members = @enum.Members.Select(static m => m.Identifier.ValueText).ToArray(), + }); + } + + foreach (var classDeclaration in root.DescendantNodes().OfType()) + { + if (classDeclaration.Identifier.ValueText != "Api") + { + continue; + } + + foreach (var method in classDeclaration.Members.OfType()) + { + functions.Add(new NativeFunction + { + Name = method.Identifier.ValueText, + ReturnType = NormalizeType(method.ReturnType.ToString()), + Parameters = method.ParameterList.Parameters.Select(static p => new NativeParameter + { + Name = p.Identifier.ValueText, + TypeName = NormalizeType(p.Type?.ToString() ?? "void"), + }).ToArray(), + IsDllImport = method.AttributeLists.SelectMany(static a => a.Attributes).Any(static a => a.Name.ToString().Contains("DllImport", StringComparison.Ordinal)), + }); + } + } + } + + var structsByName = structs.ToDictionary(static s => s.Name, StringComparer.Ordinal); + var functionsByName = functions.GroupBy(static f => f.Name, StringComparer.Ordinal).ToDictionary(static g => g.Key, static g => g.First(), StringComparer.Ordinal); + + return new NativeLibrary + { + NativeNamespace = config.NativeNamespace, + Structs = structs, + Enums = enums, + Functions = functions, + StructsByName = structsByName, + FunctionsByName = functionsByName, + }; + } + + private static IReadOnlyList ParseMembers(StructDeclarationSyntax @struct) + { + var members = new List(); + + foreach (var member in @struct.Members) + { + switch (member) + { + case FieldDeclarationSyntax field: + if (field.Declaration.Type is FunctionPointerTypeSyntax) + { + continue; + } + + foreach (var variable in field.Declaration.Variables) + { + members.Add(new NativeMember + { + Name = variable.Identifier.ValueText, + TypeName = NormalizeType(field.Declaration.Type.ToString()), + Kind = NativeMemberKind.Field, + }); + } + break; + case PropertyDeclarationSyntax property: + members.Add(new NativeMember + { + Name = property.Identifier.ValueText, + TypeName = NormalizeType(property.Type.ToString()), + Kind = NativeMemberKind.Property, + }); + break; + } + } + + return members; + } + + private static (bool IsList, bool IsPointerList, string? ListElementType) TryMatchList(IReadOnlyList members) + { + var data = members.FirstOrDefault(static m => m.Kind == NativeMemberKind.Field && m.Name == "data"); + var count = members.FirstOrDefault(static m => m.Kind == NativeMemberKind.Field && m.Name == "count"); + if (data is null || count is null) + { + return default; + } + + if (count.TypeName != "nuint") + { + return default; + } + + var pointerDepth = GetPointerDepth(data.TypeName); + if (pointerDepth == 0) + { + return default; + } + + return (true, pointerDepth > 1, TrimPointers(data.TypeName)); + } + + private static string GetNamespace(SyntaxNode root) + { + var fileScoped = root.DescendantNodes().OfType().FirstOrDefault(); + if (fileScoped is not null) + { + return fileScoped.Name.ToString(); + } + + var block = root.DescendantNodes().OfType().FirstOrDefault(); + if (block is not null) + { + return block.Name.ToString(); + } + + return string.Empty; + } + + public static string NormalizeType(string typeName) + { + return typeName.Replace("ref ", string.Empty, StringComparison.Ordinal) + .Replace("readonly ", string.Empty, StringComparison.Ordinal) + .Trim(); + } + + public static int GetPointerDepth(string typeName) + { + var depth = 0; + foreach (var ch in typeName) + { + if (ch == '*') + { + depth++; + } + } + + return depth; + } + + public static string TrimPointers(string typeName) + { + return typeName.TrimEnd('*').Trim(); + } +} diff --git a/src/Tools/Ghost.NativeWrapperGen/Program.cs b/src/Tools/Ghost.NativeWrapperGen/Program.cs new file mode 100644 index 0000000..186f75c --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Program.cs @@ -0,0 +1,118 @@ +using Ghost.NativeWrapperGen.Config; +using Ghost.NativeWrapperGen.Emit; +using Ghost.NativeWrapperGen.Parsing; +using System.Text.Json; + +namespace Ghost.NativeWrapperGen; + +internal static class Program +{ + public static int Main(string[] args) + { + try + { + var options = CliOptions.Parse(args); + var config = LoadConfig(options.ConfigPath); + + var parser = new BindingParser(); + var library = parser.Parse(options.InputPath, config); + + var outputDirectory = options.OutputPath; + Directory.CreateDirectory(outputDirectory); + CleanupGeneratedFiles(outputDirectory); + + var emitter = new WrapperGeneratorEmitter(); + foreach (var file in emitter.Emit(library, config)) + { + var destination = Path.Combine(outputDirectory, file.FileName); + Directory.CreateDirectory(Path.GetDirectoryName(destination)!); + File.WriteAllText(destination, file.Content); + Console.WriteLine($"Generated {destination}"); + } + + return 0; + } + catch (Exception ex) + { + Console.Error.WriteLine(ex); + return 1; + } + } + + private static WrapperConfig LoadConfig(string configPath) + { + var json = File.ReadAllText(configPath); + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + ReadCommentHandling = JsonCommentHandling.Skip, + AllowTrailingCommas = true, + }; + + var config = JsonSerializer.Deserialize(json, options); + return config ?? throw new InvalidOperationException($"Failed to parse config '{configPath}'."); + } + + private static void CleanupGeneratedFiles(string outputDirectory) + { + foreach (var file in Directory.GetFiles(outputDirectory, "*.nativegen.cs", SearchOption.AllDirectories)) + { + File.Delete(file); + } + } +} + +internal sealed class CliOptions +{ + public required string ConfigPath { get; init; } + public required string InputPath { get; init; } + public required string OutputPath { get; init; } + + public static CliOptions Parse(string[] args) + { + string? configPath = null; + string? inputPath = null; + string? outputPath = null; + + for (var i = 0; i < args.Length; i++) + { + switch (args[i]) + { + case "--config": + configPath = GetValue(args, ref i, "--config"); + break; + case "--input": + inputPath = GetValue(args, ref i, "--input"); + break; + case "--output": + outputPath = GetValue(args, ref i, "--output"); + break; + default: + throw new ArgumentException($"Unknown argument '{args[i]}'. Expected --config, --input, --output."); + } + } + + if (string.IsNullOrWhiteSpace(configPath) || string.IsNullOrWhiteSpace(inputPath) || string.IsNullOrWhiteSpace(outputPath)) + { + throw new ArgumentException("Usage: Ghost.NativeWrapperGen --config --input --output "); + } + + return new CliOptions + { + ConfigPath = Path.GetFullPath(configPath), + InputPath = Path.GetFullPath(inputPath), + OutputPath = Path.GetFullPath(outputPath), + }; + } + + private static string GetValue(string[] args, ref int index, string optionName) + { + index++; + if (index >= args.Length) + { + throw new ArgumentException($"Missing value for '{optionName}'."); + } + + return args[index]; + } +} diff --git a/src/Tools/Ghost.NativeWrapperGen/README.md b/src/Tools/Ghost.NativeWrapperGen/README.md new file mode 100644 index 0000000..40b27f5 --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/README.md @@ -0,0 +1,552 @@ +# Ghost.NativeWrapperGen + +`Ghost.NativeWrapperGen` is a CLI tool that reads low-level generated C# native bindings and emits a configurable wrapper layer. + +It is built for bindings that look like ClangSharp output: + +- many `partial struct` native types +- raw pointers like `foo_node*` +- list structs shaped like `{ T* data; nuint count; }` +- native methods inside a static `Api` class + +The generator is now config-driven in three key areas: + +- wrapper kinds are configurable per type +- string/blob special handling is configurable by type shape +- static methods are generated from discovered native methods plus parameter adapters from config + +## Current capabilities + +Implemented now: + +- parse top-level structs, enums, and `Api` methods +- detect list structs automatically +- generate wrapper types with configurable kinds: `class`, `struct`, `ref struct`, `readonly ref struct` +- generate pointer-list wrappers for `T** + count` +- generate raw void-list wrappers for `void* + count` +- generate string/blob accessors from config instead of hardcoded type names +- generate static wrapper methods from config-driven parameter adapters +- generate owned-resource disposal from config +- regenerate `ufbx` successfully and build `Ghost.Ufbx` + +Validated commands: + +```bash +dotnet run --project src/Tools/Ghost.NativeWrapperGen/Ghost.NativeWrapperGen.csproj -- --config src/Tools/Ghost.NativeWrapperGen/configs/ufbx.json --input src/ThridParty/Ghost.Ufbx/Generated --output src/ThridParty/Ghost.Ufbx/Warper +dotnet build src/ThridParty/Ghost.Ufbx/Ghost.Ufbx.csproj +``` + +## CLI usage + +```bash +dotnet run --project src/Tools/Ghost.NativeWrapperGen/Ghost.NativeWrapperGen.csproj -- --config --input --output +``` + +Arguments: + +- `--config`: JSON config for one library +- `--input`: folder containing generated `.cs` binding files +- `--output`: folder where `*.nativegen.cs` files are written + +The generator deletes all existing `*.nativegen.cs` files inside the output folder before writing new ones. + +## Important files + +- `src/Tools/Ghost.NativeWrapperGen/Program.cs` +- `src/Tools/Ghost.NativeWrapperGen/Config/WrapperConfig.cs` +- `src/Tools/Ghost.NativeWrapperGen/Parsing/BindingParser.cs` +- `src/Tools/Ghost.NativeWrapperGen/Transform/NamingConventions.cs` +- `src/Tools/Ghost.NativeWrapperGen/Transform/PublicTypeResolver.cs` +- `src/Tools/Ghost.NativeWrapperGen/Emit/WrapperGeneratorEmitter.cs` +- `src/Tools/Ghost.NativeWrapperGen/configs/ufbx.json` + +## Config schema + +Example: `src/Tools/Ghost.NativeWrapperGen/configs/ufbx.json` + +```json +{ + "libraryName": "ufbx", + "nativeNamespace": "Ghost.Ufbx", + "wrapperNamespace": "Ghost.Ufbx", + "nativeTypePrefix": "ufbx_", + "staticApiClassName": "Ufbx", + "skipTypes": [ + "NativeAnnotationAttribute", + "NativeTypeNameAttribute" + ], + "wrappers": { + "defaultKind": "struct", + "defaultOwnedKind": "class", + "kinds": { + "ufbx_node": "ref struct", + "ufbx_mesh": "ref struct" + } + }, + "specialTypes": { + "strings": [ + { + "type": "ufbx_string", + "dataField": "data", + "lengthField": "length", + "charSize": 8, + "encoding": "utf8", + "emitRawSpanProperty": true, + "emitStringProperty": true + } + ], + "blobs": [ + { + "type": "ufbx_blob", + "dataField": "data", + "lengthField": "size", + "elementType": "byte" + } + ] + }, + "ownedTypes": [ + { + "nativeType": "ufbx_scene", + "freeFunction": "ufbx_free_scene", + "retainFunction": "ufbx_retain_scene", + "wrapperKind": "class" + } + ], + "staticMethods": [ + { + "nativeFunction": "ufbx_load_file_len", + "methodName": "LoadFile", + "throwOnNullReturn": true, + "failureMessageMember": "description", + "parameters": [ + { "native": "filename", "adapter": "utf8Path", "publicName": "pathUtf8" }, + { "native": "filename_len", "adapter": "utf8Length", "source": "pathUtf8" }, + { "native": "opts", "adapter": "inValue", "type": "ufbx_load_opts", "publicName": "options", "optionalDefault": true }, + { "native": "error", "adapter": "errorOut", "type": "ufbx_error", "publicName": "error" } + ] + } + ] +} +``` + +## Base config fields + +### `libraryName` + +Human-readable library name. + +### `nativeNamespace` + +Namespace containing the low-level generated bindings. + +### `wrapperNamespace` + +Namespace used for emitted wrapper files. + +### `nativeTypePrefix` + +Prefix removed before PascalCase naming. + +Examples: + +- `ufbx_scene` -> `Scene` +- `ufbx_node_list` -> `NodeList` + +### `staticApiClassName` + +Name of the global static wrapper class used for methods that do not target a specific wrapper type. + +Example: + +- `Ufbx` + +### `skipTypes` + +Types ignored by parsing/emission. + +Use this for helper attributes or internal generated artifacts you do not want wrapped. + +### `typeNameOverrides` + +Overrides wrapper type names. + +Example: + +- `ufbx_string` -> `UfbxString` + +### `publicTypeOverrides` + +Overrides member property types. + +This is mainly useful for raw native value types that should expose another public type. + +## Wrapper kind configuration + +The generator no longer assumes everything should be `ref struct`. + +Config section: + +```json +"wrappers": { + "defaultKind": "struct", + "defaultOwnedKind": "class", + "kinds": { + "ufbx_scene": "class", + "ufbx_node": "ref struct", + "ufbx_mesh": "ref struct" + } +} +``` + +Supported values: + +- `class` +- `struct` +- `ref struct` +- `readonly ref struct` + +Resolution order: + +1. `ownedTypes[].wrapperKind` +2. `wrappers.kinds[nativeType]` +3. `wrappers.defaultOwnedKind` for owned types +4. `wrappers.defaultKind` for all other types + +Recommended defaults: + +- owning types: `class` +- lightweight non-owning value wrappers: `struct` +- hot traversal-only wrappers: `ref struct` + +## Special type configuration + +This replaces hardcoded `ufbx_string` and `ufbx_blob` behavior. + +### String special types + +Config shape: + +```json +{ + "type": "ufbx_string", + "dataField": "data", + "lengthField": "length", + "charSize": 8, + "encoding": "utf8", + "emitRawSpanProperty": true, + "emitStringProperty": true +} +``` + +Fields: + +- `type`: native struct type name +- `dataField`: pointer field containing character data +- `lengthField`: element count field +- `charSize`: 8, 16, or 32 +- `encoding`: `utf8`, `utf16`, or `utf32` +- `emitRawSpanProperty`: whether to emit `Bytes` +- `emitStringProperty`: whether to emit `` string property + +Generated helper methods look like: + +```csharp +public static ReadOnlySpan AsByteSpan(ufbx_string value) +public static string GetString(ufbx_string value) +``` + +Generated wrapper members look like: + +```csharp +public ReadOnlySpan NameBytes => NativeWrapperHelpers.AsByteSpan(_ptr->name); +public string Name => NativeWrapperHelpers.GetString(_ptr->name); +``` + +### Blob special types + +Config shape: + +```json +{ + "type": "ufbx_blob", + "dataField": "data", + "lengthField": "size", + "elementType": "byte" +} +``` + +Generated helper methods look like: + +```csharp +public static ReadOnlySpan AsSpan(ufbx_blob value) +``` + +Generated wrapper members look like: + +```csharp +public ReadOnlySpan Data => NativeWrapperHelpers.AsSpan(_ptr->data); +``` + +## Owned type configuration + +Config shape: + +```json +{ + "nativeType": "ufbx_scene", + "freeFunction": "ufbx_free_scene", + "retainFunction": "ufbx_retain_scene", + "wrapperKind": "class" +} +``` + +Fields: + +- `nativeType`: native pointer target type +- `freeFunction`: optional free function in `Api` +- `retainFunction`: reserved for future ownership helpers +- `wrapperKind`: optional per-owned-type wrapper override +- `staticType`: reserved target override for generated static methods + +Current effect: + +- if `freeFunction` is present, generator emits `Dispose()` +- if wrapper kind is not otherwise specified, owning types use `wrappers.defaultOwnedKind` + +## Static method generation + +This replaces the old fixed `EntryPointConfig` model. + +Now you configure native methods by name and provide parameter adapters. + +Config shape: + +```json +{ + "nativeFunction": "ufbx_load_memory", + "methodName": "LoadMemory", + "throwOnNullReturn": true, + "failureMessageMember": "description", + "parameters": [ + { "native": "data", "adapter": "byteSpan", "publicName": "data" }, + { "native": "data_size", "adapter": "byteSpanLength", "source": "data" }, + { "native": "opts", "adapter": "inValue", "type": "ufbx_load_opts", "publicName": "options", "optionalDefault": true }, + { "native": "error", "adapter": "errorOut", "type": "ufbx_error", "publicName": "error" } + ] +} +``` + +### Target selection + +By default: + +- if a native method returns `T*` and `T` has a wrapper, the static method is generated on `T` +- otherwise it is generated on the global static type from `staticApiClassName` + +You can override that later with `staticType`. + +### Current parameter adapters + +Implemented adapters: + +- `utf8Path` + - public parameter: `ReadOnlySpan` + - native argument: `sbyte*` +- `utf8Length` + - emits `(nuint).Length` +- `byteSpan` + - public parameter: `ReadOnlySpan` + - native argument: `byte*` +- `byteSpanLength` + - emits `(nuint).Length` +- `inValue` + - public parameter: `in T` + - native argument: `&localCopy` +- `errorOut` + - hides error buffer from public signature + - emits a local native error value and passes pointer to native call + +### Return handling + +Current behavior: + +- if native return is `T*` and `T` has a wrapper, emitted return type is wrapper type +- if `throwOnNullReturn` is `true`, a null pointer return throws `InvalidOperationException` +- if `failureMessageMember` is set and the method has an `errorOut` parameter, the generator uses that configured member to build the exception message +- primitive and raw returns are forwarded directly + +### Example: `ufbx_load_file_len` + +Native signature: + +```csharp +public static extern ufbx_scene* ufbx_load_file_len(sbyte* filename, nuint filename_len, ufbx_load_opts* opts, ufbx_error* error); +``` + +Generated method: + +```csharp +public static Scene LoadFile(ReadOnlySpan pathUtf8, in ufbx_load_opts options = default) +``` + +### Example: `ufbx_load_memory` + +Native signature: + +```csharp +public static extern ufbx_scene* ufbx_load_memory(void* data, nuint data_size, ufbx_load_opts* opts, ufbx_error* error); +``` + +Generated method: + +```csharp +public static Scene LoadMemory(ReadOnlySpan data, in ufbx_load_opts options = default) +``` + +## List handling + +The parser recognizes list structs by shape: + +- a `data` field +- a `count` field +- `count` type is `nuint` +- `data` is a pointer type + +### Value lists: `T* + count` + +Generated as `ReadOnlySpan` properties. + +### Pointer lists: `T** + count` + +Generated as iterable wrapper list types with: + +- `Count` +- indexer +- `foreach` enumerator + +### Void lists: `void* + count` + +Generated as lightweight wrappers exposing: + +- `Count` +- `Data` + +## Current naming rules + +By default: + +1. remove `nativeTypePrefix` +2. split by `_` +3. convert to PascalCase + +Examples: + +- `ufbx_scene` -> `Scene` +- `ufbx_node` -> `Node` +- `ufbx_node_list` -> `NodeList` + +If a member name would equal the wrapper type name, `Value` is appended. + +Example: + +- wrapper `Props` with field `props` becomes `PropsValue` + +## How to use for another library + +Create a new config, for example `src/Tools/Ghost.NativeWrapperGen/configs/somelib.json`: + +```json +{ + "libraryName": "somelib", + "nativeNamespace": "Ghost.SomeLib", + "wrapperNamespace": "Ghost.SomeLib", + "nativeTypePrefix": "somelib_", + "staticApiClassName": "SomeLib", + "wrappers": { + "defaultKind": "struct", + "defaultOwnedKind": "class", + "kinds": {} + }, + "specialTypes": { + "strings": [ + { + "type": "somelib_string", + "dataField": "data", + "lengthField": "length", + "charSize": 8, + "encoding": "utf8" + } + ], + "blobs": [] + }, + "ownedTypes": [ + { + "nativeType": "somelib_context", + "freeFunction": "somelib_free_context", + "wrapperKind": "class" + } + ], + "staticMethods": [ + { + "nativeFunction": "somelib_load_file_len", + "methodName": "LoadFile", + "throwOnNullReturn": true, + "failureMessageMember": "message", + "parameters": [ + { "native": "path", "adapter": "utf8Path", "publicName": "pathUtf8" }, + { "native": "path_len", "adapter": "utf8Length", "source": "pathUtf8" }, + { "native": "options", "adapter": "inValue", "type": "somelib_load_options", "optionalDefault": true }, + { "native": "error", "adapter": "errorOut", "type": "somelib_error" } + ] + } + ] +} +``` + +Run: + +```bash +dotnet run --project src/Tools/Ghost.NativeWrapperGen/Ghost.NativeWrapperGen.csproj -- --config src/Tools/Ghost.NativeWrapperGen/configs/somelib.json --input src/ThridParty/Ghost.SomeLib/Generated --output src/ThridParty/Ghost.SomeLib/Wrapper +``` + +## Current limitations + +This README documents the current implementation, not a future idealized version. + +Not implemented yet: + +- automatic ownership inference +- automatic retain/release policy generation +- rich enum wrapper generation +- source generator mode +- MSBuild auto-hook integration +- custom adapter plugins outside the built-in adapter set +- direct generation from C headers +- per-member exclusion config +- fixed-buffer string decoding rules + +Also note: + +- `struct` wrappers that own native resources are possible, but not recommended as a default because copy semantics can duplicate ownership +- current string support assumes pointer + length string structs +- pointer-list wrappers are still emitted as `readonly ref struct` views for performance + +## Recommended workflow + +When changing the generator: + +```bash +dotnet build src/Tools/Ghost.NativeWrapperGen/Ghost.NativeWrapperGen.csproj +dotnet run --project src/Tools/Ghost.NativeWrapperGen/Ghost.NativeWrapperGen.csproj -- --config src/Tools/Ghost.NativeWrapperGen/configs/ufbx.json --input src/ThridParty/Ghost.Ufbx/Generated --output src/ThridParty/Ghost.Ufbx/Warper +dotnet build src/ThridParty/Ghost.Ufbx/Ghost.Ufbx.csproj +``` + +## Summary + +Use `Ghost.NativeWrapperGen` when you already have raw generated C# bindings and want a configurable modern wrapper layer without hand-writing hundreds of types. + +The important design idea is now: + +- keep parsing generic +- move policy into config +- keep adapters explicit when native signatures need shaping diff --git a/src/Tools/Ghost.NativeWrapperGen/Transform/NamingConventions.cs b/src/Tools/Ghost.NativeWrapperGen/Transform/NamingConventions.cs new file mode 100644 index 0000000..27b7840 --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Transform/NamingConventions.cs @@ -0,0 +1,49 @@ +using Ghost.NativeWrapperGen.Config; + +namespace Ghost.NativeWrapperGen.Transform; + +public sealed class NamingConventions +{ + private readonly WrapperConfig _config; + + public NamingConventions(WrapperConfig config) + { + _config = config; + } + + public string GetWrapperTypeName(string nativeTypeName) + { + if (_config.TypeNameOverrides.TryGetValue(nativeTypeName, out var overrideName)) + { + return overrideName; + } + + return ToPascalCase(StripKnownPrefix(nativeTypeName)); + } + + public string GetPropertyName(string nativeName) + { + return ToPascalCase(nativeName); + } + + private string StripKnownPrefix(string nativeTypeName) + { + if (nativeTypeName.StartsWith(_config.NativeTypePrefix, StringComparison.Ordinal)) + { + return nativeTypeName[_config.NativeTypePrefix.Length..]; + } + + return nativeTypeName; + } + + public static string ToPascalCase(string value) + { + var parts = value.Split('_', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + if (parts.Length == 0) + { + return value; + } + + return string.Concat(parts.Select(static part => char.ToUpperInvariant(part[0]) + part[1..])); + } +} diff --git a/src/Tools/Ghost.NativeWrapperGen/Transform/PublicTypeResolver.cs b/src/Tools/Ghost.NativeWrapperGen/Transform/PublicTypeResolver.cs new file mode 100644 index 0000000..f48b8b1 --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/Transform/PublicTypeResolver.cs @@ -0,0 +1,56 @@ +using Ghost.NativeWrapperGen.Config; +using Ghost.NativeWrapperGen.Model; +using Ghost.NativeWrapperGen.Parsing; + +namespace Ghost.NativeWrapperGen.Transform; + +public sealed class PublicTypeResolver +{ + private readonly NativeLibrary _library; + private readonly WrapperConfig _config; + private readonly NamingConventions _naming; + + public PublicTypeResolver(NativeLibrary library, WrapperConfig config, NamingConventions naming) + { + _library = library; + _config = config; + _naming = naming; + } + + public string GetPublicType(string nativeTypeName) + { + if (string.Equals(nativeTypeName, "void", StringComparison.Ordinal)) + { + return "void*"; + } + + if (_config.PublicTypeOverrides.TryGetValue(nativeTypeName, out var overrideType)) + { + return overrideType; + } + + var pointerDepth = BindingParser.GetPointerDepth(nativeTypeName); + var baseType = BindingParser.TrimPointers(nativeTypeName); + + if (pointerDepth == 0) + { + return baseType; + } + + if (_library.StructsByName.ContainsKey(baseType)) + { + return pointerDepth switch + { + 1 => _naming.GetWrapperTypeName(baseType), + _ => nativeTypeName, + }; + } + + return nativeTypeName; + } + + public bool HasWrapper(string nativeTypeName) + { + return _library.StructsByName.ContainsKey(nativeTypeName); + } +} diff --git a/src/Tools/Ghost.NativeWrapperGen/configs/ufbx.json b/src/Tools/Ghost.NativeWrapperGen/configs/ufbx.json new file mode 100644 index 0000000..e096d2e --- /dev/null +++ b/src/Tools/Ghost.NativeWrapperGen/configs/ufbx.json @@ -0,0 +1,221 @@ +{ + "libraryName": "ufbx", + "nativeNamespace": "Ghost.Ufbx", + "wrapperNamespace": "Ghost.Ufbx", + "nativeTypePrefix": "ufbx_", + "staticApiClassName": "Ufbx", + "skipTypes": [ + "NativeAnnotationAttribute", + "NativeTypeNameAttribute" + ], + "wrappers": { + "defaultKind": "struct", + "defaultOwnedKind": "class", + "kinds": { + "ufbx_node": "ref struct", + "ufbx_mesh": "ref struct", + "ufbx_element": "ref struct", + "ufbx_anim": "ref struct", + "ufbx_material": "ref struct", + "ufbx_texture": "ref struct", + "ufbx_props": "ref struct", + "ufbx_prop": "ref struct", + "ufbx_load_opts": "class" + } + }, + "specialTypes": { + "strings": [ + { + "type": "ufbx_string", + "dataField": "data", + "lengthField": "length", + "charSize": 8, + "encoding": "utf8", + "emitRawSpanProperty": true, + "emitStringProperty": true + } + ], + "blobs": [ + { + "type": "ufbx_blob", + "dataField": "data", + "lengthField": "size", + "elementType": "byte" + } + ] + }, + "ownedTypes": [ + { + "nativeType": "ufbx_scene", + "freeFunction": "ufbx_free_scene", + "retainFunction": "ufbx_retain_scene", + "wrapperKind": "class" + } + ], + "staticMethods": [ + { + "nativeFunction": "ufbx_load_file_len", + "methodName": "LoadFile", + "throwOnNullReturn": true, + "failureMessageMember": "description", + "parameters": [ + { + "native": "filename", + "adapter": "utf8Path", + "publicName": "pathUtf8" + }, + { + "native": "filename_len", + "adapter": "utf8Length", + "source": "pathUtf8" + }, + { + "native": "opts", + "adapter": "getPtr", + "type": "LoadOpts", + "publicName": "options" + }, + { + "native": "error", + "adapter": "errorOut", + "type": "ufbx_error", + "publicName": "error" + } + ] + }, + { + "nativeFunction": "ufbx_load_memory", + "methodName": "LoadMemory", + "throwOnNullReturn": true, + "failureMessageMember": "description", + "parameters": [ + { + "native": "data", + "adapter": "byteSpan", + "publicName": "data" + }, + { + "native": "data_size", + "adapter": "byteSpanLength", + "source": "data" + }, + { + "native": "opts", + "adapter": "inValue", + "type": "ufbx_load_opts", + "publicName": "options", + "optionalDefault": true + }, + { + "native": "error", + "adapter": "errorOut", + "type": "ufbx_error", + "publicName": "error" + } + ] + }, + { + "nativeFunction": "ufbx_find_node_len", + "methodName": "FindNode", + "parameters": [ + { + "native": "name", + "adapter": "utf8Path", + "publicName": "name" + }, + { + "native": "name_len", + "adapter": "utf8Length", + "source": "name" + } + ] + }, + { + "nativeFunction": "ufbx_find_element_len", + "methodName": "FindElement", + "parameters": [ + { + "native": "name", + "adapter": "utf8Path", + "publicName": "name" + }, + { + "native": "name_len", + "adapter": "utf8Length", + "source": "name" + } + ] + }, + { + "nativeFunction": "ufbx_find_material_len", + "methodName": "FindMaterial", + "parameters": [ + { + "native": "name", + "adapter": "utf8Path", + "publicName": "name" + }, + { + "native": "name_len", + "adapter": "utf8Length", + "source": "name" + } + ] + }, + { + "nativeFunction": "ufbx_find_anim_stack_len", + "methodName": "FindAnimStack", + "parameters": [ + { + "native": "name", + "adapter": "utf8Path", + "publicName": "name" + }, + { + "native": "name_len", + "adapter": "utf8Length", + "source": "name" + } + ] + }, + { + "nativeFunction": "ufbx_find_prop_len", + "methodName": "FindProp", + "parameters": [ + { + "native": "name", + "adapter": "utf8Path", + "publicName": "name" + }, + { + "native": "name_len", + "adapter": "utf8Length", + "source": "name" + } + ] + } + ], + "marshalledTypes": [ + { + "nativeType": "ufbx_load_opts", + "marshalledProperties": [ + { + "native": "obj_mtl_path", + "type": "cstring" + }, + { + "native": "filename", + "type": "cstring" + } + ] + } + ], + "typeNameOverrides": { + "ufbx_string": "UfbxString", + "ufbx_blob": "UfbxBlob" + }, + "publicTypeOverrides": { + "ufbx_string": "string", + "ufbx_blob": "ReadOnlySpan" + } +}