Bläddra i källkod

Possible to generate a bunch of structs automatically

Lucien Greathouse 6 månader sedan
förälder
incheckning
1ba2c30f83
13 ändrade filer med 585 tillägg och 159 borttagningar
  1. 5 1
      .gitignore
  2. 2 0
      CMakeLists.txt
  3. 375 0
      Cargo.lock
  4. 3 0
      Cargo.toml
  5. 16 15
      JoltC/Functions.h
  6. 14 0
      JoltC/Generated.h
  7. 25 0
      JoltCImpl/Generated.h
  8. 2 32
      JoltCImpl/JoltC.cpp
  9. 1 0
      generate/Cargo.toml
  10. 81 0
      generate/src/emit.rs
  11. 29 0
      generate/src/macros.rs
  12. 21 111
      generate/src/main.rs
  13. 11 0
      input/MirroredStructs.h

+ 5 - 1
.gitignore

@@ -1 +1,5 @@
-/build*
+# CMake output
+/build*
+
+# Cargo output
+/target

+ 2 - 0
CMakeLists.txt

@@ -33,10 +33,12 @@ add_library(joltc STATIC
     JoltC/JoltC.h
     JoltC/Enums.h
     JoltC/Functions.h
+    JoltC/Generated.h
 
     # C++ Implementation
     JoltCImpl/Test.cpp
     JoltCImpl/JoltC.cpp
+    JoltCImpl/Generated.h
 )
 
 target_compile_features(joltc PUBLIC cxx_std_17)

+ 375 - 0
Cargo.lock

@@ -0,0 +1,375 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
+dependencies = [
+ "anstyle",
+ "once_cell",
+ "windows-sys",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.97"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
+
+[[package]]
+name = "autocfg"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
+name = "clap"
+version = "4.5.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+
+[[package]]
+name = "cps"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "570e736c5c84982a931d819c7be0ad000f3aad769eb4e78b234dc9fa64b10415"
+dependencies = [
+ "litrs",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "fs-err"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "generate"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "clap",
+ "cps",
+ "fs-err",
+ "heck",
+ "regex",
+ "walkdir",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "litrs"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9275e0933cf8bb20f008924c0cb07a0692fe54d8064996520bf998de9eb79aa"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "once_cell"
+version = "1.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "winapi-util"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

+ 3 - 0
Cargo.toml

@@ -0,0 +1,3 @@
+[workspace]
+resolver = "2"
+members = ["generate"]

+ 16 - 15
JoltC/Functions.h

@@ -180,6 +180,8 @@ typedef struct JPC_ShapeCastResult {
 
 typedef struct JPC_Body JPC_Body;
 
+#include <JoltC/Generated.h>
+
 ////////////////////////////////////////////////////////////////////////////////
 // VertexList == Array<Float3> == std::vector<Float3>
 
@@ -561,20 +563,6 @@ typedef struct JPC_Constraint JPC_Constraint;
 
 JPC_API void JPC_Constraint_delete(JPC_Constraint* self);
 
-////////////////////////////////////////////////////////////////////////////////
-// ConstraintSettings
-
-typedef struct JPC_ConstraintSettings {
-	bool Enabled;
-	uint32_t ConstraintPriority;
-	uint NumVelocityStepsOverride;
-	uint NumPositionStepsOverride;
-	float DrawConstraintSize;
-	uint64_t UserData;
-} JPC_ConstraintSettings;
-
-JPC_API void JPC_ConstraintSettings_default(JPC_ConstraintSettings* settings);
-
 ////////////////////////////////////////////////////////////////////////////////
 // FixedConstraintSettings
 
@@ -603,7 +591,20 @@ JPC_API JPC_Constraint* JPC_FixedConstraintSettings_Create(
 	JPC_Body* inBody2);
 
 ////////////////////////////////////////////////////////////////////////////////
-// TriangleShapeSettings
+// ShapeSettings
+
+typedef struct JPC_ShapeSettings {
+	uint64_t UserData;
+} JPC_ShapeSettings;
+
+////////////////////////////////////////////////////////////////////////////////
+// ConvexShapeSettings -> ShapeSettings
+
+typedef struct JPC_ConvexShapeSettings {
+} JPC_ConvexShapeSettings;
+
+////////////////////////////////////////////////////////////////////////////////
+// TriangleShapeSettings -> ConvexShapeSettings -> ShapeSettings
 
 typedef struct JPC_TriangleShapeSettings {
 	// ShapeSettings

+ 14 - 0
JoltC/Generated.h

@@ -0,0 +1,14 @@
+#pragma once
+// Generated by JoltC-generate
+
+typedef struct JPC_ConstraintSettings {
+	bool Enabled;
+	uint32_t ConstraintPriority;
+	uint NumVelocityStepsOverride;
+	uint NumPositionStepsOverride;
+	float DrawConstraintSize;
+	uint64_t UserData;
+} JPC_ConstraintSettings;
+
+JPC_API void JPC_ConstraintSettings_default(JPC_ConstraintSettings* value);
+

+ 25 - 0
JoltCImpl/Generated.h

@@ -0,0 +1,25 @@
+// Generated by JoltC-generate
+
+JPC_IMPL void JPC_ConstraintSettings_to_jpc(JPC_ConstraintSettings* outJpc, const JPH::ConstraintSettings* inJph) {
+	outJpc->Enabled = inJph->mEnabled;
+	outJpc->ConstraintPriority = inJph->mConstraintPriority;
+	outJpc->NumVelocityStepsOverride = inJph->mNumVelocityStepsOverride;
+	outJpc->NumPositionStepsOverride = inJph->mNumPositionStepsOverride;
+	outJpc->DrawConstraintSize = inJph->mDrawConstraintSize;
+	outJpc->UserData = inJph->mUserData;
+}
+
+JPC_IMPL void JPC_ConstraintSettings_to_jph(const JPC_ConstraintSettings* inJpc, JPH::ConstraintSettings* outJph) {
+	outJph->mEnabled = inJpc->Enabled;
+	outJph->mConstraintPriority = inJpc->ConstraintPriority;
+	outJph->mNumVelocityStepsOverride = inJpc->NumVelocityStepsOverride;
+	outJph->mNumPositionStepsOverride = inJpc->NumPositionStepsOverride;
+	outJph->mDrawConstraintSize = inJpc->DrawConstraintSize;
+	outJph->mUserData = inJpc->UserData;
+}
+
+JPC_API void JPC_ConstraintSettings_default(JPC_ConstraintSettings* value) {
+	JPH::ConstraintSettings defaultValue{};
+	JPC_ConstraintSettings_to_jpc(value, &defaultValue);
+}
+

+ 2 - 32
JoltCImpl/JoltC.cpp

@@ -33,6 +33,8 @@
 
 #define JPC_IMPL static
 
+#include <JoltCImpl/Generated.h>
+
 #define OPAQUE_WRAPPER(c_type, cpp_type) \
 	static c_type* to_jpc(cpp_type *in) { return reinterpret_cast<c_type*>(in); } \
 	static const c_type* to_jpc(const cpp_type *in) { return reinterpret_cast<const c_type*>(in); } \
@@ -747,38 +749,6 @@ JPC_API void JPC_Constraint_delete(JPC_Constraint* self) {
 	delete to_jph(self);
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// ConstraintSettings
-
-JPC_IMPL void JPC_ConstraintSettings_to_jpc(
-	JPC_ConstraintSettings* outJpc,
-	const JPH::ConstraintSettings* inJph)
-{
-	outJpc->Enabled = inJph->mEnabled;
-	outJpc->ConstraintPriority = inJph->mConstraintPriority;
-	outJpc->NumVelocityStepsOverride = inJph->mNumVelocityStepsOverride;
-	outJpc->NumPositionStepsOverride = inJph->mNumPositionStepsOverride;
-	outJpc->DrawConstraintSize = inJph->mDrawConstraintSize;
-	outJpc->UserData = inJph->mUserData;
-}
-
-JPC_IMPL void JPC_ConstraintSettings_to_jph(
-	const JPC_ConstraintSettings* inJpc,
-	JPH::ConstraintSettings* outJph)
-{
-	outJph->mEnabled = inJpc->Enabled;
-	outJph->mConstraintPriority = inJpc->ConstraintPriority;
-	outJph->mNumVelocityStepsOverride = inJpc->NumVelocityStepsOverride;
-	outJph->mNumPositionStepsOverride = inJpc->NumPositionStepsOverride;
-	outJph->mDrawConstraintSize = inJpc->DrawConstraintSize;
-	outJph->mUserData = inJpc->UserData;
-}
-
-JPC_API void JPC_ConstraintSettings_default(JPC_ConstraintSettings* settings) {
-	JPH::ConstraintSettings defaultSettings{};
-	JPC_ConstraintSettings_to_jpc(settings, &defaultSettings);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // FixedConstraintSettings
 

+ 1 - 0
generate/Cargo.toml

@@ -8,6 +8,7 @@ edition = "2021"
 [dependencies]
 anyhow = "1.0.82"
 clap = { version = "4.5.4", features = ["derive"] }
+cps = "0.2.3"
 fs-err = "2.11.0"
 heck = "0.5.0"
 regex = "1.10.4"

+ 81 - 0
generate/src/emit.rs

@@ -0,0 +1,81 @@
+use std::fmt::Write;
+
+pub struct MirrorStruct {
+    pub jph_name: &'static str,
+    pub jpc_name: &'static str,
+    pub fields: &'static [StructField],
+}
+
+impl MirrorStruct {
+    pub fn emit_header(&self, out: &mut impl Write) -> anyhow::Result<()> {
+        self.header_definition(out)?;
+        self.header_methods(out)?;
+        Ok(())
+    }
+
+    fn header_methods(&self, out: &mut impl Write) -> anyhow::Result<()> {
+        let jpc_name = self.jpc_name;
+
+        writeln!(out, "JPC_API void {jpc_name}_default({jpc_name}* value);")?;
+        writeln!(out)?;
+
+        Ok(())
+    }
+
+    fn header_definition(&self, out: &mut impl Write) -> anyhow::Result<()> {
+        let jpc_name = self.jpc_name;
+
+        writeln!(out, "typedef struct {jpc_name} {{")?;
+        for StructField { ty, name } in self.fields {
+            writeln!(out, "\t{ty} {name};")?;
+        }
+        writeln!(out, "}} {jpc_name};")?;
+        writeln!(out)?;
+
+        Ok(())
+    }
+
+    pub fn emit_impl(&self, out: &mut impl Write) -> anyhow::Result<()> {
+        self.impl_methods(out)?;
+        Ok(())
+    }
+
+    fn impl_methods(&self, out: &mut impl Write) -> anyhow::Result<()> {
+        let Self {
+            jpc_name, jph_name, ..
+        } = self;
+
+        writeln!(
+            out,
+            "JPC_IMPL void {jpc_name}_to_jpc({jpc_name}* outJpc, const {jph_name}* inJph) {{"
+        )?;
+        for StructField { ty, name } in self.fields {
+            writeln!(out, "\toutJpc->{name} = inJph->m{name};")?;
+        }
+        writeln!(out, "}}")?;
+        writeln!(out)?;
+
+        writeln!(
+            out,
+            "JPC_IMPL void {jpc_name}_to_jph(const {jpc_name}* inJpc, {jph_name}* outJph) {{"
+        )?;
+        for StructField { ty, name } in self.fields {
+            writeln!(out, "\toutJph->m{name} = inJpc->{name};")?;
+        }
+        writeln!(out, "}}")?;
+        writeln!(out)?;
+
+        writeln!(out, "JPC_API void {jpc_name}_default({jpc_name}* value) {{")?;
+        writeln!(out, "\t{jph_name} defaultValue{{}};")?;
+        writeln!(out, "\t{jpc_name}_to_jpc(value, &defaultValue);")?;
+        writeln!(out, "}}")?;
+        writeln!(out)?;
+
+        Ok(())
+    }
+}
+
+pub struct StructField {
+    pub ty: &'static str,
+    pub name: &'static str,
+}

+ 29 - 0
generate/src/macros.rs

@@ -0,0 +1,29 @@
+macro_rules! mirrored_structs {
+    (
+        $(struct $struct_name:ident {
+            $($field_ty:ident $field_name:ident;)*
+        };)*
+    ) => {
+        [$(
+            MirrorStruct {
+                jph_name: concat!("JPH::", stringify!($struct_name)),
+                jpc_name: concat!("JPC_", stringify!($struct_name)),
+                fields: &[$(
+                    StructField {
+                        ty: stringify!($field_ty),
+                        name: stringify!($field_name),
+                    },
+                )*]
+            }
+        )*]
+    }
+}
+
+#[cps::cps]
+macro_rules! include_mirrored_structs {
+    ($source:literal) =>
+    let $($body:tt)* = cps::include!($source) in
+    {
+        mirrored_structs!($($body)*)
+    }
+}

+ 21 - 111
generate/src/main.rs

@@ -1,13 +1,13 @@
-use std::collections::HashMap;
+mod emit;
+
+#[macro_use]
+mod macros;
+
 use std::fmt::Write;
 
-use anyhow::Context;
-use fs_err as fs;
-use heck::AsShoutySnakeCase;
-use regex::Regex;
-use walkdir::WalkDir;
+use self::emit::{MirrorStruct, StructField};
 
-static PREFIX: &str = "JPC";
+static STRUCTS: &[MirrorStruct] = &include_mirrored_structs!("input/ReflectedStructs.h");
 
 fn main() {
     if let Err(err) = generate() {
@@ -16,117 +16,27 @@ fn main() {
 }
 
 fn generate() -> anyhow::Result<()> {
-    let mut output = String::new();
-
-    writeln!(output, "// Generated by JoltC-generate").unwrap();
-
-    for entry in WalkDir::new("JoltPhysics/Jolt") {
-        let entry = entry?;
-        let file_name = entry
-            .file_name()
-            .to_str()
-            .context("invalid UTF-8 in file name")?;
+    let mut header = String::new();
 
-        if file_name.ends_with(".h") {
-            eprintln!("Processing {file_name}...");
+    writeln!(header, "#pragma once")?;
+    writeln!(header, "// Generated by JoltC-generate")?;
+    writeln!(header)?;
 
-            let header = fs::read_to_string(entry.path())?;
-
-            convert_enums(&header, &mut output);
-        }
+    for struc in STRUCTS {
+        struc.emit_header(&mut header)?;
     }
 
-    println!("{output}");
+    let mut cpp = String::new();
 
-    Ok(())
-}
+    writeln!(cpp, "// Generated by JoltC-generate")?;
+    writeln!(cpp)?;
 
-fn convert_enums(header: &str, output: &mut String) {
-    struct WipEnum {
-        cpp_name: String,
-        c_name: String,
-        shouty_c_name: String,
-        next_value: u32,
-        num_variants: u32,
+    for struc in STRUCTS {
+        struc.emit_impl(&mut cpp)?;
     }
 
-    let enum_types: HashMap<&str, &str> = HashMap::from_iter([
-        ("int", "int"),
-        ("uint", "unsigned int"),
-        ("uint8", "uint8_t"),
-        ("uint16", "uint16_t"),
-        ("uint32", "uint32_t"),
-    ]);
-
-    let enum_class = Regex::new(r"^\s*enum\s+class\s+(\w+)(?:\s*:\s*(\w+))?").unwrap();
-    let enum_member = Regex::new(r"^\s*(\w+)(?:\s*=\s*(.+?)(?:,|/|$))?").unwrap();
-    let end_block = Regex::new(r"^\s*}").unwrap();
-
-    let mut current_enum = None;
-
-    for line in header.lines() {
-        if current_enum.is_none() {
-            if let Some(captures) = enum_class.captures(line) {
-                let mut name = &captures[1];
-                let given_repr = captures.get(2).map(|m| m.as_str()).unwrap_or("int");
-
-                let repr = enum_types
-                    .get(given_repr)
-                    .unwrap_or_else(|| panic!("unknown enum type {given_repr}"));
-
-                // EShapeSubType => ShapeSubType
-                if name.starts_with('E') && name.as_bytes()[1].is_ascii_uppercase() {
-                    name = &name[1..];
-                }
-
-                let c_name = format!("{PREFIX}_{}", name);
+    fs_err::write("JoltC/Generated.h", header)?;
+    fs_err::write("JoltCImpl/Generated.h", cpp)?;
 
-                let shouty_c_name =
-                    format!("{}", AsShoutySnakeCase(&c_name)).replace("DO_FS", "DOFS");
-
-                writeln!(output, "typedef {repr} {c_name};").unwrap();
-
-                current_enum = Some(WipEnum {
-                    cpp_name: name.to_owned(),
-                    c_name,
-                    shouty_c_name,
-                    next_value: 0,
-                    num_variants: 0,
-                });
-
-                continue;
-            }
-
-            continue;
-        }
-
-        if let Some(current) = &mut current_enum {
-            if end_block.is_match(line) {
-                writeln!(output).unwrap();
-
-                current_enum = None;
-                continue;
-            }
-
-            if let Some(captures) = enum_member.captures(line) {
-                current.num_variants += 1;
-
-                let name = &captures[1];
-                let given_value = captures.get(2).map(|m| m.as_str().trim().to_string());
-
-                if given_value.is_none() && current.num_variants > 1 && current.next_value == 0 {
-                    panic!("Enum {} variant {name} did not have a value, but is set to use auto values", current.cpp_name);
-                }
-
-                let value = given_value.unwrap_or_else(|| {
-                    let v = current.next_value;
-                    current.next_value += 1;
-                    v.to_string()
-                });
-
-                let c_name = format!("{}_{}", current.shouty_c_name, AsShoutySnakeCase(name));
-                writeln!(output, "static {} {c_name} = {value};", current.c_name).unwrap();
-            }
-        }
-    }
+    Ok(())
 }

+ 11 - 0
input/MirroredStructs.h

@@ -0,0 +1,11 @@
+// The structs in this file are C structs that are mirrored 1:1 with Jolt's C++
+// types.
+
+struct ConstraintSettings {
+	bool Enabled;
+	uint32_t ConstraintPriority;
+	uint NumVelocityStepsOverride;
+	uint NumPositionStepsOverride;
+	float DrawConstraintSize;
+	uint64_t UserData;
+};