public CachedProperty(PropertyDefinition property, string cacheFieldName = null) { Property = property; if (cacheFieldName != null) { CacheFieldName = cacheFieldName; } else { string name = property.Name; CacheFieldName = "_" + char.ToLower(name[0]) + name.Substring(1); } Access = RefAccessSpecifier.Private; }
void WriteProperty(PropertyDefinition prop, int level) { EnsureWhiteSpace(WriteTo.CS); WriteTabs(level + 1, WriteTo.CS); Write("public ", WriteTo.CS); WriteTypeCS(prop.Type); Write(' ', WriteTo.CS); WriteLine(prop.Name, WriteTo.CS); WriteTabs(level + 1, WriteTo.CS); WriteLine('{', WriteTo.CS); Write(BulletParser.GetTypeGetterCSMarshal(prop, level), WriteTo.CS); if (prop.Setter != null) { WriteTabs(level + 2, WriteTo.CS); Write("set { ", WriteTo.CS); Write(prop.Parent.FullNameCS, WriteTo.CS); Write('_', WriteTo.CS); Write(prop.Setter.Name, WriteTo.CS); Write("(_native, ", WriteTo.CS); Write(BulletParser.GetTypeSetterCSMarshal(prop.Type), WriteTo.CS); WriteLine("); }", WriteTo.CS); } WriteTabs(level + 1, WriteTo.CS); WriteLine('}', WriteTo.CS); hasCSWhiteSpace = false; }
void WriteProperty(PropertyDefinition prop, int level) { EnsureWhiteSpace(WriteTo.CS); WriteTabs(level + 1, WriteTo.CS); Write("public ", WriteTo.CS); WriteTypeCS(prop.Type); WriteLine($" {prop.Name}", WriteTo.CS); WriteTabs(level + 1, WriteTo.CS); WriteLine('{', WriteTo.CS); if (prop.Parent.CachedProperties.Keys.Contains(prop.Name)) { var cachedProperty = prop.Parent.CachedProperties[prop.Name]; WriteTabs(level + 2, WriteTo.CS); WriteLine($"get {{ return {cachedProperty.CacheFieldName}; }}", WriteTo.CS); if (prop.Setter != null) { WriteTabs(level + 2, WriteTo.CS); WriteLine("set", WriteTo.CS); WriteTabs(level + 2, WriteTo.CS); WriteLine("{", WriteTo.CS); WriteTabs(level + 3, WriteTo.CS); WriteLine(string.Format("{0}_{1}(_native, {2});", prop.Parent.FullNameC, prop.Setter.Name, BulletParser.GetTypeSetterCSMarshal(prop.Type)), WriteTo.CS); WriteTabs(level + 3, WriteTo.CS); WriteLine($"{cachedProperty.CacheFieldName} = value;", WriteTo.CS); WriteTabs(level + 2, WriteTo.CS); WriteLine("}", WriteTo.CS); } } else { Write(BulletParser.GetTypeGetterCSMarshal(prop, level), WriteTo.CS); if (prop.Setter != null) { WriteTabs(level + 2, WriteTo.CS); WriteLine(string.Format("set {{ {0}_{1}(_native, {2}); }}", prop.Parent.FullNameC, prop.Setter.Name, BulletParser.GetTypeSetterCSMarshal(prop.Type)), WriteTo.CS); } } WriteTabs(level + 1, WriteTo.CS); WriteLine('}', WriteTo.CS); hasCSWhiteSpace = false; }
public static string GetTypeGetterCSMarshal(PropertyDefinition prop, int level) { StringBuilder output = new StringBuilder(); TypeRefDefinition type = prop.Type; if (!type.IsBasic) { switch (type.ManagedNameCS) { case "Matrix3x3": case "Quaternion": case "Transform": case "Vector3": case "Vector4": output.AppendLine(GetTabs(level + 2) + "get"); output.AppendLine(GetTabs(level + 2) + "{"); output.AppendLine(GetTabs(level + 3) + GetTypeNameCS(type) + " value;"); output.AppendLine(GetTabs(level + 3) + prop.Parent.FullNameCS + '_' + prop.Getter.Name + "(_native, out value);"); output.AppendLine(GetTabs(level + 3) + "return value;"); output.AppendLine(GetTabs(level + 2) + '}'); return output.ToString(); } } output.AppendLine(GetTabs(level + 2) + "get { return " + BulletParser.GetTypeMarshalConstructorStartCS(prop.Getter) + prop.Parent.FullNameCS + '_' + prop.Getter.Name + "(_native)" + BulletParser.GetTypeMarshalConstructorEndCS(prop.Getter) + "; }"); return output.ToString(); }
public BulletParser(Dictionary<string, ClassDefinition> classDefinitions, Dictionary<string, HeaderDefinition> headerDefinitions) { this.classDefinitions = classDefinitions; ExternalHeaders = headerDefinitions; // Excluded classes string[] excludedClassArray = new string[] { "ActionInterface", "AlignedAllocator", "bChunk", "bCommon", "bFile", "Box", "BulletFile", "cl_MiniCL_Defs", "cl_platform", "ContactProcessing", "ConvexHull", "ConvexHullComputer", "DantzigLCP", "GenericPoolAllocator", "gim_array", "gim_bitset", "gim_box_collision", "gim_box_set", "gim_clip_polygon", "gim_contact", "gim_geom_types", "gim_hash_table", "gim_memory", "gim_radixsort", "gim_tri_collision", "GjkEpa2", "Gpu3DGridBroadphase", "Gpu3DGridBroadphaseSharedTypes", "GpuDefines", "GrahamScan2dConvexHull", "HashedSimplePairCache", "HashMap", "HeapManager", "IDebugDraw", "JacobianEntry", "List", "Material", "Matrix3x3", "MatrixX", "MiniCLTask", "MiniCLTaskScheduler", "MultiSapBroadphase", "PlatformDefinitions", "PolarDecomposition", "PolyhedralContactClipping", "PosixThreadSupport", "PpuAddressSpace", "QuadWord", "RaycastCallback", "SequentialThreadSupport", "SimpleDynamicsWorld", "SoftBodyData", "SoftBodyInternals", "SoftBodySolvers", "SoftRigidCollisionAlgorithm", "SoftSoftCollisionAlgorithm", "SolveProjectedGaussSeidel", "SolverBody", "SolverConstraint", "SpuCollisionObjectWrapper", "SpuCollisionShapes", "SpuCollisionTaskProcess", "SpuContactManifoldCollisionAlgorithm", "SpuContactResult", "SpuConvexPenetrationDepthSolver", "SpuDoubleBuffer", "SpuGatheringCollisionTask", "SpuMinkowskiPenetrationDepthSolver", "SpuSampleTask", "SpuSampleTaskProcess", "SpuSync", "StackAlloc", "SubSimplexConvexCast", "Transform", "TrbDynBody", "TrbStateVec", "vectormath_aos", "vmInclude", "HacdCircularList", "HacdGraph", "HacdICHull", "HacdManifoldMesh", "HacdVector", "Quaternion", "Vector3", "LemkeAlgorithm", "CharacterControllerInterface", "TypedObject" }; // Managed method names methodNameMapping.Add("gimpact_vs_compoundshape", "GImpactVsCompoundShape"); methodNameMapping.Add("gimpact_vs_concave", "GImpactVsConcave"); methodNameMapping.Add("gimpact_vs_gimpact", "GImpactVsGImpact"); methodNameMapping.Add("gimpact_vs_shape", "GImpactVsShape"); methodNameMapping.Add("collideKDOP", "CollideKdop"); methodNameMapping.Add("collideOCL", "CollideOcl"); methodNameMapping.Add("collideTTpersistentStack", "CollideTTPersistentStack"); methodNameMapping.Add("maxdepth", "MaxDepth"); methodNameMapping.Add("updateRHS", "UpdateRhs"); // Managed method parameter names parameterNameMapping.Add("bcheckexist", "checkExist"); parameterNameMapping.Add("childShapeindex", "childShapeIndex"); parameterNameMapping.Add("dt", "deltaTime"); parameterNameMapping.Add("fromfaces", "fromFaces"); parameterNameMapping.Add("i_dataBufferSize", "dataBufferSize"); parameterNameMapping.Add("i_swapEndian", "swapEndian"); parameterNameMapping.Add("i_alignedDataBuffer", "alignedDataBuffer"); parameterNameMapping.Add("o_alignedDataBuffer", "alignedDataBuffer"); parameterNameMapping.Add("drawflags", "drawFlags"); parameterNameMapping.Add("idraw", "iDraw"); parameterNameMapping.Add("indexstride", "indexStride"); parameterNameMapping.Add("indicestype", "indicesType"); parameterNameMapping.Add("limot", "limitMotor"); parameterNameMapping.Add("maxiterations", "maxIterations"); parameterNameMapping.Add("maxdepth", "maxDepth"); parameterNameMapping.Add("mindepth", "minDepth"); parameterNameMapping.Add("nodeindex", "nodeIndex"); parameterNameMapping.Add("numfaces", "numFaces"); parameterNameMapping.Add("numindices", "numIndices"); parameterNameMapping.Add("numverts", "numVerts"); parameterNameMapping.Add("paircache", "pairCache"); parameterNameMapping.Add("rbA", "rigidBodyA"); parameterNameMapping.Add("rbB", "rigidBodyB"); parameterNameMapping.Add("rbAFrame", "rigidBodyAFrame"); parameterNameMapping.Add("rbBFrame", "rigidBodyBFrame"); parameterNameMapping.Add("use32bitIndices", "use32BitIndices"); parameterNameMapping.Add("use4componentVertices", "use4ComponentVertices"); parameterNameMapping.Add("vertexbase", "vertexBase"); // Managed header names var headerNameMapping = new Dictionary<string, string>(); headerNameMapping.Add("btActionInterface", "IAction"); headerNameMapping.Add("btBox2dBox2dCollisionAlgorithm", "Box2DBox2DCollisionAlgorithm"); headerNameMapping.Add("btBox2dShape", "Box2DShape"); headerNameMapping.Add("btCompoundFromGimpact", "CompoundFromGImpact"); headerNameMapping.Add("btConvex2dConvex2dAlgorithm", "Convex2DConvex2DAlgorithm"); headerNameMapping.Add("btConvex2dShape", "Convex2DShape"); headerNameMapping.Add("btMLCPSolver", "MlcpSolver"); headerNameMapping.Add("btMLCPSolverInterface", "MlcpSolverInterface"); headerNameMapping.Add("btNNCGConstraintSolver", "NncgConstraintSolver"); headerNameMapping.Add("btSparseSDF", "SparseSdf"); headerNameMapping.Add("hacdHACD", "Hacd"); // Managed class names var classNameMapping = new Dictionary<string, string>(); classNameMapping.Add("btAABB", "Aabb"); classNameMapping.Add("bt32BitAxisSweep3", "AxisSweep3_32Bit"); classNameMapping.Add("btActionInterface", "IAction"); classNameMapping.Add("btBox2dBox2dCollisionAlgorithm", "Box2DBox2DCollisionAlgorithm"); classNameMapping.Add("btBox2dShape", "Box2DShape"); classNameMapping.Add("btConvex2dConvex2dAlgorithm", "Convex2DConvex2DAlgorithm"); classNameMapping.Add("btConvex2dShape", "Convex2DShape"); classNameMapping.Add("btMLCPSolver", "MlcpSolver"); classNameMapping.Add("btMLCPSolverInterface", "MlcpSolverInterface"); classNameMapping.Add("btMultibodyLink", "MultiBodyLink"); classNameMapping.Add("btNNCGConstraintSolver", "NncgConstraintSolver"); classNameMapping.Add("HACD", "Hacd"); classNameMapping.Add("GIM_BVH_DATA", "GimBvhData"); classNameMapping.Add("GIM_BVH_DATA_ARRAY", "GimBvhDataArray"); classNameMapping.Add("GIM_BVH_TREE_NODE", "GimBvhTreeNode"); classNameMapping.Add("GIM_BVH_TREE_NODE_ARRAY", "GimBvhTreeNodeArray"); classNameMapping.Add("GIM_PAIR", "GimPair"); classNameMapping.Add("GIM_TRIANGLE_CONTACT", "GimTriangleContact"); classNameMapping.Add("BT_QUANTIZED_BVH_NODE", "GImpactQuantizedBvhNode"); classNameMapping.Add("GIM_QUANTIZED_BVH_NODE_ARRAY", "GimGImpactQuantizedBvhNodeArray"); classNameMapping.Add("btCPUVertexBufferDescriptor", "CpuVertexBufferDescriptor"); classNameMapping.Add("btBU_Simplex1to4", "BuSimplex1To4"); classNameMapping.Add("sStkCLN", "StkCln"); classNameMapping.Add("sStkNN", "StkNN"); classNameMapping.Add("sStkNP", "StkNP"); classNameMapping.Add("sStkNPS", "StkNps"); classNameMapping.Add("sRayCast", "SRayCast"); classNameMapping.Add("RContact", "RigidContact"); classNameMapping.Add("SContact", "SoftContact"); // Classes that shouldn't be instantiated by users List<string> hidePublicConstructors = new List<string>() { "btActivatingCollisionAlgorithm", "btContactConstraint", "btConvexInternalShape", "btConvexInternalAabbCachingShape", "btPolyhedralConvexAabbCachingShape", "btTypedObject", "btDbvtProxy", "btSimpleBroadphaseProxy", "btDispatcherInfo", "btTriangleMeshShape", "btUsageBitfield", "btSoftBody::Anchor", "btSoftBody::Config", "btSoftBody::Cluster", "btSoftBody::Face", "btSoftBody::Tetra", "btSoftBody::Element", "btSoftBody::Feature", "btSoftBody::Link", "btSoftBody::Material", "btSoftBody::Node", "btSoftBody::Note", "btSoftBody::Pose", "btSoftBody::SolverState", "btSoftBody::Joint::Specs", "btSoftBody::AJoint", "btSoftBody::CJoint", "btSoftBody::LJoint", "btSparseSdf", "btCompoundShapeChild", "btMultibodyLink" }; // Classes for which no internal constructor is needed List<string> hideInternalConstructor = new List<string>() { "btBox2dBox2dCollisionAlgorithm", "btBoxBoxCollisionAlgorithm", "btBoxBoxDetector", "btBroadphaseRayCallback", "btCollisionAlgorithmConstructionInfo", "btDefaultCollisionConstructionInfo", "btCompoundCompoundCollisionAlgorithm", "btContinuousConvexCollision", "btConvex2dConvex2dAlgorithm", "btConvexConcaveCollisionAlgorithm", "btConvexConvexAlgorithm", "btDefaultMotionState", "btRigidBody", "btDiscreteCollisionDetectorInterface::ClosestPointInput", "btEmptyAlgorithm", "btGjkConvexCast", "btGjkEpaPenetrationDepthSolver", "btMinkowskiPenetrationDepthSolver", "btPointCollector", "btMultiBodyDynamicsWorld", "btDefaultVehicleRaycaster", "btRaycastVehicle", "btDefaultSerializer", "btSoftBodyRigidBodyCollisionConfiguration", "btCPUVertexBufferDescriptor", "btSoftRigidDynamicsWorld", "btSphereBoxCollisionAlgorithm", "btSphereTriangleCollisionAlgorithm", "SpuGatheringCollisionDispatcher", "btConvexSeparatingDistanceUtil", "btVehicleRaycaster::btVehicleRaycasterResult", "btOverlapCallback", "btRaycastVehicle::btVehicleTuning", "btBox2dShape", "btBoxShape", "btCapsuleShapeX", "btCapsuleShapeZ", "btCylinderShapeX", "btCylinderShapeZ", "btConeShapeX", "btConeShapeZ", "btConvex2dShape", "btConvexHullShape", "btConvexPointCloudShape", "btEmptyShape", "btHeightfieldTerrainShape", "btMinkowskiSumShape", "btMultiSphereShape", "btMultimaterialTriangleMeshShape", "btScaledBvhTriangleMeshShape", "btSphereShape", "btStaticPlaneShape", "btUniformScalingShape", "btCollisionWorld::ConvexResultCallback", "btCollisionWorld::ClosestConvexResultCallback", "HACD", "btRigidBody::btRigidBodyConstructionInfo", "btSoftBody::ImplicitFn", "btTriangleBuffer", "btMaterialProperties", "btCollisionWorld::AllHitsRayResultCallback", "btCollisionWorld::ContactResultCallback", "btCollisionWorld::ClosestRayResultCallback", "btCollisionWorld::RayResultCallback", "btJointFeedback", "btTypedConstraint::btConstraintInfo1", "btTypedConstraint::btConstraintInfo2", "btConeTwistConstraint", "btFixedConstraint", "btGearConstraint", "btGeneric6DofSpringConstraint", "btHinge2Constraint", "btHingeAccumulatedAngleConstraint", "btPoint2PointConstraint", "btSliderConstraint", "btUniversalConstraint", "btMLCPSolver", "btMultiBodyConstraintSolver", "btNNCGConstraintSolver", "btPairCachingGhostObject", "btSortedOverlappingPairCache", "btNullPairCache", "btDbvtBroadphase", "btSimpleBroadphase", "btShapeHull", "btSoftBody::sRayCast", "btSoftBody::AJoint::Specs", "btSoftBody::LJoint::Specs", "btCompoundShape" // constructor needed for CompoundFromGImpact in C++/CLI, but not C# }; // Classes that might be cleaned up by Bullet and not us (use preventDelete to indicate this) List<string> preventDelete = new List<string>() { "btAABB", "btCollisionAlgorithmCreateFunc", "btCollisionObject", "btCollisionObjectWrapper", "btCollisionShape", "btCollisionWorld::LocalConvexResult", "btCollisionWorld::LocalRayResult", "btConstraintSolver", "btContactSolverInfoData", "btDbvt", "btOverlappingPairCache", "btPoolAllocator", "btRotationalLimitMotor", "btTranslationalLimitMotor", "btRotationalLimitMotor2", "btTranslationalLimitMotor2", "btConstraintSetting", "btSimulationIslandManager", "btSolve2LinearConstraint", "btIndexedMesh", "btTriangleInfoMap", "btAngularLimit", "btContactSolverInfo", "btWheelInfo", "btManifoldPoint", "btCollisionWorld::LocalShapeInfo", "btSequentialImpulseConstraintSolver"}; // Classes that have OnDisposing/OnDisposed events List<string> trackingDisposable = new List<string>() { "btCollisionObject", "btCollisionShape", "btCollisionWorld", "btDbvt", "btRaycastVehicle", "btTypedConstraint"}; excludedClassNames = new Dictionary<string, string>(); foreach (string c in excludedClassArray) { excludedClassNames.Add(c, c); } // Resolve references (match TypeRefDefinitions to ClassDefinitions) foreach (ClassDefinition c in classDefinitions.Values) { // Resolve base class type if (c.BaseClass != null) { ResolveTypeRef(c.BaseClass); if (c.BaseClass.Target == null) { Console.WriteLine("Base class " + c.BaseClass.Name + " not found!"); } else { var targetHeader = c.BaseClass.Target.Header; if (c.Header != targetHeader && !c.Header.Includes.Contains(targetHeader)) { c.Header.Includes.Add(targetHeader); } } } // Resolve typedef if (c.TypedefUnderlyingType != null) { ResolveTypeRef(c.TypedefUnderlyingType); } // Resolve method return type and parameter types foreach (MethodDefinition method in c.Methods) { ResolveTypeRef(method.ReturnType); foreach (ParameterDefinition param in method.Parameters) { ResolveTypeRef(param.Type); } } // Resolve field types foreach (FieldDefinition field in c.Fields) { ResolveTypeRef(field.Type); } } // Exclude all overridden methods foreach (ClassDefinition c in classDefinitions.Values) { int i; for (i = 0; i < c.Methods.Count; ) { var method = c.Methods[i]; // Check if the method already exists in base classes var baseClass = c.BaseClass; while (baseClass != null && baseClass.Target != null) { foreach (MethodDefinition m in baseClass.Target.Methods) { if (method.Equals(m)) { c.Methods.Remove(method); method = null; break; } } if (method == null) { break; } baseClass = baseClass.Target.BaseClass; } if (method != null) { i++; } } } // Exclude constructors of abstract classes foreach (ClassDefinition c in classDefinitions.Values) { if (!c.IsAbstract) { continue; } int i; for (i = 0; i < c.Methods.Count; ) { var method = c.Methods[i]; if (method.IsConstructor) { c.Methods.Remove(method); continue; } i++; } } // Exclude duplicate methods foreach (ClassDefinition c in classDefinitions.Values) { for (int i = 0; i < c.Methods.Count; i++) { for (int j = i + 1; j < c.Methods.Count; j++) { if (!c.Methods[i].Equals(c.Methods[j])) { continue; } var iType = c.Methods[i].ReturnType; var jType = c.Methods[j].ReturnType; bool iConst = iType.IsConst || (iType.Referenced != null && iType.Referenced.IsConst); bool jConst = jType.IsConst || (jType.Referenced != null && jType.Referenced.IsConst); // Prefer non-const return value if (iConst) { if (!jConst) { c.Methods.RemoveAt(i); i--; } } else { if (jConst) { c.Methods.RemoveAt(j); i--; } } break; } } } // Set managed method/parameter names foreach (ClassDefinition c in classDefinitions.Values) { foreach (var method in c.Methods) { method.ManagedName = GetManagedMethodName(method); foreach (var param in method.Parameters) { param.ManagedName = GetManagedParameterName(param); } } } // Turn fields into get/set methods foreach (ClassDefinition c in classDefinitions.Values) { foreach (FieldDefinition field in c.Fields) { ResolveTypeRef(field.Type); string name = field.Name; if (name.StartsWith("m_")) { name = name.Substring(2); } name = name.Substring(0, 1).ToUpper() + name.Substring(1); // capitalize // one_two_three -> oneTwoThree string managedName = name; while (managedName.Contains("_")) { int pos = managedName.IndexOf('_'); managedName = managedName.Substring(0, pos) + managedName.Substring(pos + 1, 1).ToUpper() + managedName.Substring(pos + 2); } // Generate getter/setter methods string getterName, setterName; string managedGetterName, managedSetterName; if (name.StartsWith("has")) { getterName = name; setterName = "set" + name.Substring(3); managedGetterName = managedName; managedSetterName = "Set" + managedName.Substring(3); } else if (name.StartsWith("is")) { getterName = name; setterName = "set" + name.Substring(2); managedGetterName = managedName; managedSetterName = "Set" + managedName.Substring(2); } else { getterName = "get" + name; setterName = "set" + name; managedGetterName = "Get" + managedName; managedSetterName = "Set" + managedName; } // See if there are already accessor methods for this field MethodDefinition getter = null, setter = null; foreach (var m in c.Methods) { if (m.ManagedName.Equals(managedGetterName) && m.Parameters.Length == 0) { getter = m; continue; } if (m.ManagedName.Equals(managedSetterName) && m.Parameters.Length == 1) { setter = m; } } if (getter == null) { getter = new MethodDefinition(getterName, c, 0); getter.ManagedName = managedGetterName; getter.ReturnType = field.Type; getter.Field = field; } var prop = new PropertyDefinition(getter); // Can't assign value to reference or constant array if (setter == null && !field.Type.IsReference && !field.Type.IsConstantArray) { setter = new MethodDefinition(setterName, c, 1); setter.ManagedName = managedSetterName; setter.ReturnType = new TypeRefDefinition(); setter.Field = field; TypeRefDefinition constType; if (!field.Type.IsBasic && !field.Type.IsPointer) { constType = field.Type.Copy(); constType.IsConst = true; } else { constType = field.Type; } setter.Parameters[0] = new ParameterDefinition("value", constType); setter.Parameters[0].ManagedName = "value"; prop.Setter = setter; prop.Setter.Property = prop; } } } // Turn getters/setters into properties foreach (ClassDefinition c in classDefinitions.Values) { // Getters with return type and 0 arguments foreach (var method in c.Methods) { if (method.Parameters.Length == 0 && !method.IsVoid && (method.Name.StartsWith("get", StringComparison.InvariantCultureIgnoreCase) || method.Name.StartsWith("has", StringComparison.InvariantCultureIgnoreCase) || method.Name.StartsWith("is", StringComparison.InvariantCultureIgnoreCase))) { if (method.Property == null) { new PropertyDefinition(method); } } } // Getters with void type and 1 pointer argument for the return value // TODO: in general, it is not possible to automatically determine // whether such methods can be wrapped by properties or not, // so read this info from the project configuration. foreach (var method in c.Methods) { if (method.Parameters.Length == 1 && method.IsVoid && method.Name.StartsWith("get", StringComparison.InvariantCultureIgnoreCase)) { if (method.Property != null) { continue; } var paramType = method.Parameters[0].Type; if (paramType.IsPointer || paramType.IsReference) { // TODO: check project configuration //if (true) { new PropertyDefinition(method); } } } } // Setters foreach (var method in c.Methods) { if (method.Parameters.Length == 1 && method.Name.StartsWith("set", StringComparison.InvariantCultureIgnoreCase)) { string name = method.ManagedName.Substring(3); // Find the property with the matching getter foreach (PropertyDefinition prop in c.Properties) { if (prop.Setter != null) { continue; } if (prop.Name.Equals(name)) { prop.Setter = method; method.Property = prop; break; } } } } } // Get managed header names foreach (HeaderDefinition header in ExternalHeaders.Values) { string name = header.Name; string mapping; if (headerNameMapping.TryGetValue(name, out mapping)) { header.ManagedName = mapping; } else if (name.StartsWith("bt")) { header.ManagedName = name.Substring(2); } else if (name.StartsWith("hacd")) { header.ManagedName = "Hacd" + name.Substring(4); } } // Apply class properties foreach (ClassDefinition c in classDefinitions.Values) { string name = c.Name; string mapping; if (classNameMapping.TryGetValue(name, out mapping)) { c.ManagedName = mapping; } else if (name.StartsWith("bt") && !name.Equals("btScalar")) { c.ManagedName = name.Substring(2); } else { c.ManagedName = name; } if (hidePublicConstructors.Contains(c.FullName)) { c.HidePublicConstructors = true; } if (hideInternalConstructor.Contains(c.FullName)) { c.NoInternalConstructor = true; } if (preventDelete.Contains(c.FullName)) { c.HasPreventDelete = true; } if (trackingDisposable.Contains(c.FullName)) { c.IsTrackingDisposable = true; } } // Sort methods and properties alphabetically foreach (ClassDefinition c in classDefinitions.Values) { // Order by name, then fix inheritance, parent classes must appear first c.Classes.Sort((c1, c2) => c1.Name.CompareTo(c2.Name)); var classesOrdered = c.Classes; for (int i = 0; i < classesOrdered.Count; i++) { var thisClass = classesOrdered[i]; var baseClass = thisClass.BaseClass; if (baseClass != null && classesOrdered.Contains(baseClass.Target)) { int thisIndex = classesOrdered.IndexOf(thisClass); if (thisIndex < classesOrdered.IndexOf(baseClass.Target)) { classesOrdered.Remove(baseClass.Target); classesOrdered.Insert(thisIndex, baseClass.Target); } } } c.Methods.Sort((m1, m2) => m1.Name.CompareTo(m2.Name)); c.Properties.Sort((p1, p2) => p1.Name.CompareTo(p2.Name)); } // Mark excluded classes foreach (ClassDefinition c in classDefinitions.Values) { if (IsExcludedClass(c)) { c.IsExcluded = true; } } Console.WriteLine("Parsing complete"); }
void CreateFieldSetter(PropertyDefinition prop, string setterName, string managedSetterName) { // Can't assign value to reference or constant array if (prop.Type.IsReference || prop.Type.IsConstantArray) return; if (prop.Type.Name != null && prop.Type.Name.StartsWith("btAlignedObjectArray")) return; var type = prop.Getter.ReturnType; MethodDefinition setter = new MethodDefinition(setterName, prop.Parent, 1); setter.ManagedName = managedSetterName; setter.ReturnType = new TypeRefDefinition(); setter.Field = prop.Getter.Field; if (!type.IsBasic && !type.IsPointer) { type = type.Copy(); type.IsConst = true; } setter.Parameters[0] = new ParameterDefinition("value", type); setter.Parameters[0].ManagedName = "value"; prop.Setter = setter; prop.Setter.Property = prop; }
// Create getters and setters for fields void CreateFieldAccessors() { foreach (var @class in Project.ClassDefinitions.Values) { foreach (var field in @class.Fields) { string name = field.Name; if (name.StartsWith("m_")) { name = name.Substring(2); } name = char.ToUpper(name[0]) + name.Substring(1); // capitalize string managedName = ToCamelCase(name, true); // Generate getter/setter methods string getterName, setterName; string managedGetterName, managedSetterName; string verb = _booleanVerbs.FirstOrDefault(v => name.StartsWith(v)); if (verb != null && "bool".Equals(field.Type.Name)) { getterName = name; setterName = "set" + name.Substring(verb.Length); managedGetterName = managedName; managedSetterName = "Set" + managedName.Substring(verb.Length); } else { getterName = "get" + name; setterName = "set" + name; managedGetterName = "Get" + managedName; managedSetterName = "Set" + managedName; } // See if there are already accessor methods for this field MethodDefinition getter = null, setter = null; foreach (var method in @class.Methods) { if (managedGetterName.Equals(method.ManagedName) && method.Parameters.Length == 0) { getter = method; continue; } if (managedSetterName.Equals(method.ManagedName) && method.Parameters.Length == 1) { setter = method; } } if (getter == null) { getter = new MethodDefinition(getterName, @class, 0); getter.ManagedName = managedGetterName; getter.ReturnType = field.Type; getter.Field = field; } var prop = new PropertyDefinition(getter, GetPropertyName(getter)); if (setter == null) { CreateFieldSetter(prop, setterName, managedSetterName); } } } }
public static string GetTypeGetterCSMarshal(PropertyDefinition prop, int level) { StringBuilder output = new StringBuilder(); TypeRefDefinition type = prop.Type; // If cached property can only be set in constructor, // the getter can simply return the cached value // TODO: check if cached value is initialized in all constructors CachedProperty cachedProperty; if (prop.Parent.CachedProperties.TryGetValue(prop.Name, out cachedProperty)) { if (cachedProperty.Property.Setter == null) { output.AppendLine(GetTabs(level + 2) + string.Format("get {{ return {0}; }}", cachedProperty.CacheFieldName)); return output.ToString(); } } if (!type.IsBasic) { switch (type.ManagedNameCS) { case "Matrix3x3": case "Quaternion": case "Transform": case "Vector3": case "Vector4": output.AppendLine(GetTabs(level + 2) + "get"); output.AppendLine(GetTabs(level + 2) + "{"); output.AppendLine(GetTabs(level + 3) + GetTypeNameCS(type) + " value;"); output.AppendLine(GetTabs(level + 3) + string.Format("{0}_{1}(_native, out value);", prop.Parent.FullNameC, prop.Getter.Name)); output.AppendLine(GetTabs(level + 3) + "return value;"); output.AppendLine(GetTabs(level + 2) + '}'); return output.ToString(); } } output.AppendLine(GetTabs(level + 2) + string.Format("get {{ return {0}{1}_{2}(_native){3}; }}", GetTypeMarshalConstructorStartCS(prop.Getter), prop.Parent.FullNameC, prop.Getter.Name, GetTypeMarshalConstructorEndCS(prop.Getter))); return output.ToString(); }