jolt-ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitmodules +3 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +228 -0
  5. data/Rakefile +180 -0
  6. data/examples/character_virtual.rb +35 -0
  7. data/examples/falling_sphere.rb +25 -0
  8. data/examples/stagecraft_binding.rb +29 -0
  9. data/ext/jolt_ruby/CMakeLists.txt +42 -0
  10. data/ext/jolt_ruby/character_helper.cpp +44 -0
  11. data/ext/jolt_ruby/constraint_helper.cpp +154 -0
  12. data/ext/jolt_ruby/extconf.rb +56 -0
  13. data/ext/jolt_ruby/helper.cpp +225 -0
  14. data/ext/jolt_ruby/helper.h +103 -0
  15. data/ext/joltc/.github/FUNDING.yml +1 -0
  16. data/ext/joltc/.github/workflows/build.yml +298 -0
  17. data/ext/joltc/.gitignore +272 -0
  18. data/ext/joltc/CMakeLists.txt +431 -0
  19. data/ext/joltc/LICENSE +21 -0
  20. data/ext/joltc/README.md +10 -0
  21. data/ext/joltc/build/cmake_vs2026_arm64.bat +3 -0
  22. data/ext/joltc/build/cmake_vs2026_clang.bat +10 -0
  23. data/ext/joltc/build/cmake_vs2026_x64.bat +3 -0
  24. data/ext/joltc/build/cmake_vs2026_x64_double.bat +3 -0
  25. data/ext/joltc/include/joltc.h +3166 -0
  26. data/ext/joltc/samples/01_HelloWorld/main.cpp +170 -0
  27. data/ext/joltc/samples/CMakeLists.txt +35 -0
  28. data/ext/joltc/src/joltc.c +4 -0
  29. data/ext/joltc/src/joltc.cpp +11812 -0
  30. data/ext/joltc/src/joltc_assert.cpp +271 -0
  31. data/ext/joltc/tests/CMakeLists.txt +77 -0
  32. data/ext/joltc/tests/test_character.cpp +149 -0
  33. data/ext/joltc/tests/test_collision.cpp +146 -0
  34. data/ext/joltc/tests/test_constraints.cpp +353 -0
  35. data/ext/joltc/tests/test_core.cpp +94 -0
  36. data/ext/joltc/tests/test_math.cpp +585 -0
  37. data/ext/joltc/tests/test_physics_system.cpp +465 -0
  38. data/ext/joltc/tests/test_shapes.cpp +789 -0
  39. data/ext/joltc/tests/test_skeleton.cpp +370 -0
  40. data/ext/joltc/tests/test_vehicle.cpp +319 -0
  41. data/generator/generate.rb +237 -0
  42. data/generator/layout_probe.cpp +489 -0
  43. data/generator/verify_layout.rb +32 -0
  44. data/lib/jolt/body.rb +147 -0
  45. data/lib/jolt/body_collection.rb +115 -0
  46. data/lib/jolt/body_dynamics.rb +93 -0
  47. data/lib/jolt/character_virtual.rb +162 -0
  48. data/lib/jolt/constraint.rb +136 -0
  49. data/lib/jolt/constraint_collection.rb +123 -0
  50. data/lib/jolt/contact_events.rb +19 -0
  51. data/lib/jolt/conversions.rb +76 -0
  52. data/lib/jolt/errors.rb +12 -0
  53. data/lib/jolt/fixed_stepper.rb +37 -0
  54. data/lib/jolt/hit.rb +5 -0
  55. data/lib/jolt/layers.rb +182 -0
  56. data/lib/jolt/native/character_functions.rb +16 -0
  57. data/lib/jolt/native/constraint_functions.rb +27 -0
  58. data/lib/jolt/native/core_functions.rb +17 -0
  59. data/lib/jolt/native/generated.rb +1995 -0
  60. data/lib/jolt/native/platform.rb +51 -0
  61. data/lib/jolt/native/query_functions.rb +43 -0
  62. data/lib/jolt/native/types.rb +28 -0
  63. data/lib/jolt/native.rb +94 -0
  64. data/lib/jolt/shape.rb +90 -0
  65. data/lib/jolt/shape_builders.rb +155 -0
  66. data/lib/jolt/system.rb +238 -0
  67. data/lib/jolt/system_characters.rb +25 -0
  68. data/lib/jolt/system_constraints.rb +36 -0
  69. data/lib/jolt/system_contacts.rb +57 -0
  70. data/lib/jolt/system_queries.rb +111 -0
  71. data/lib/jolt/transform.rb +5 -0
  72. data/lib/jolt/version.rb +5 -0
  73. data/lib/jolt.rb +83 -0
  74. data/script/smoke_gem.rb +29 -0
  75. data/script/verify_release.rb +36 -0
  76. metadata +147 -0
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jolt
4
+ module SystemCharacters
5
+ def __register_character(character, shape)
6
+ @character_registry << character
7
+ @shapes[shape.object_id] = shape
8
+ end
9
+
10
+ def __destroy_character(character)
11
+ return if character.destroyed?
12
+
13
+ __check_alive!
14
+ removed = @character_registry.delete(character)
15
+ raise InvalidArgumentError, "virtual character does not belong to this system" unless removed
16
+
17
+ character.__destroy_native
18
+ nil
19
+ end
20
+
21
+ def __destroy_all_characters
22
+ @character_registry.dup.each(&:destroy)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jolt
4
+ module SystemConstraints
5
+ def __register_constraint(constraint)
6
+ @constraint_registry << constraint
7
+ end
8
+
9
+ def __destroy_constraint(constraint)
10
+ return if constraint.destroyed?
11
+
12
+ __check_alive!
13
+ removed = @constraint_registry.delete(constraint)
14
+ raise InvalidArgumentError, "constraint does not belong to this system" unless removed
15
+
16
+ pointer = constraint.__native_pointer
17
+ Native.JPH_PhysicsSystem_RemoveConstraint(@pointer, pointer)
18
+ Native.JPH_Constraint_Destroy(pointer)
19
+ constraint.__mark_destroyed
20
+ nil
21
+ end
22
+
23
+ def __constraints_snapshot
24
+ __check_alive!
25
+ @constraint_registry.dup
26
+ end
27
+
28
+ def __destroy_constraints_for(body)
29
+ @constraint_registry.select { |constraint| constraint.__involves?(body) }.each(&:destroy)
30
+ end
31
+
32
+ def __destroy_all_constraints
33
+ @constraint_registry.dup.each(&:destroy)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jolt
4
+ module SystemContacts
5
+ CONTACT_EVENT_TYPES = %i[added persisted removed].freeze
6
+ MAX_CONTACT_QUEUE_CAPACITY = 1 << 30
7
+
8
+ def __create_contact_queue(capacity)
9
+ unless capacity.is_a?(Integer) && capacity.between?(2, MAX_CONTACT_QUEUE_CAPACITY)
10
+ raise InvalidArgumentError,
11
+ "contact_queue_capacity must be an integer between 2 and #{MAX_CONTACT_QUEUE_CAPACITY}"
12
+ end
13
+
14
+ @contact_queue = Native.JR_ContactQueue_Create(capacity)
15
+ raise InitializationError, "failed to create contact event queue" if @contact_queue.null?
16
+
17
+ listener = Native.JR_ContactQueue_GetListener(@contact_queue)
18
+ raise InitializationError, "failed to create contact listener" if listener.null?
19
+
20
+ Native.JPH_PhysicsSystem_SetContactListener(@pointer, listener)
21
+ @contact_events = ContactEvents.empty
22
+ end
23
+
24
+ def __drain_contact_events
25
+ grouped = {added: [], persisted: [], removed: []}
26
+ native = Native::ContactEvent.new
27
+ while Native.JR_ContactQueue_Pop(@contact_queue, native.pointer)
28
+ type = CONTACT_EVENT_TYPES.fetch(native[:type])
29
+ removed = type == :removed
30
+ grouped.fetch(type) << Contact.new(
31
+ body_a: @body_registry[native[:body_a]],
32
+ body_b: @body_registry[native[:body_b]],
33
+ sub_shape_a: native[:sub_shape_a],
34
+ sub_shape_b: native[:sub_shape_b],
35
+ point: removed ? nil : Larb::Vec3.new(*native[:point].to_a),
36
+ normal: removed ? nil : Larb::Vec3.new(*native[:normal].to_a),
37
+ penetration: removed ? nil : native[:penetration]
38
+ )
39
+ end
40
+ dropped = Native.JR_ContactQueue_GetDroppedCount(@contact_queue)
41
+ @contact_events = ContactEvents.new(
42
+ added: grouped[:added].freeze,
43
+ persisted: grouped[:persisted].freeze,
44
+ removed: grouped[:removed].freeze,
45
+ dropped_count: dropped
46
+ )
47
+ end
48
+
49
+ def __destroy_contact_queue
50
+ return unless @contact_queue && !@contact_queue.null?
51
+
52
+ Native.JPH_PhysicsSystem_SetContactListener(@pointer, nil) if @pointer && !@pointer.null?
53
+ Native.JR_ContactQueue_Destroy(@contact_queue)
54
+ @contact_queue = nil
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jolt
4
+ module SystemQueries
5
+ def raycast(origin:, direction:, layer_mask: nil)
6
+ __check_alive!
7
+ origin_native = Conversions.native_vec3(origin, name: "origin")
8
+ direction_native = Conversions.native_vec3(direction, name: "direction")
9
+ direction_vector = Conversions.vec3(direction_native)
10
+ if direction_vector.length <= Float::EPSILON
11
+ raise InvalidArgumentError, "direction must not be zero"
12
+ end
13
+
14
+ filter, filter_context = object_layer_filter(layer_mask)
15
+ result = Native::RayCastResult.new
16
+ hit = Native.JPH_NarrowPhaseQuery_CastRay(
17
+ @narrow_phase_query,
18
+ origin_native.pointer,
19
+ direction_native.pointer,
20
+ result.pointer,
21
+ nil,
22
+ filter,
23
+ nil
24
+ )
25
+ return nil unless hit
26
+
27
+ build_hit(origin_native, direction_native, result)
28
+ ensure
29
+ Native.JPH_ObjectLayerFilter_Destroy(filter) if filter && !filter.null?
30
+ filter_context = nil
31
+ end
32
+
33
+ def overlap_sphere(center, radius, layer_mask: nil, &block)
34
+ center_native = Conversions.native_vec3(center, name: "center")
35
+ radius = Conversions.positive_float(radius, "radius")
36
+ collect_overlapping_bodies(
37
+ :JPH_BroadPhaseQuery_CollideSphere,
38
+ center_native.pointer,
39
+ radius,
40
+ layer_mask:,
41
+ &block
42
+ )
43
+ end
44
+
45
+ def overlap_point(point, layer_mask: nil, &block)
46
+ point_native = Conversions.native_vec3(point, name: "point")
47
+ collect_overlapping_bodies(
48
+ :JPH_BroadPhaseQuery_CollidePoint,
49
+ point_native.pointer,
50
+ layer_mask:,
51
+ &block
52
+ )
53
+ end
54
+
55
+ private
56
+
57
+ def collect_overlapping_bodies(function, *query_arguments, layer_mask:)
58
+ __check_alive!
59
+ filter, filter_context = object_layer_filter(layer_mask)
60
+ callback, body_ids = Native::QueryFunctions.body_collector
61
+ Native.public_send(
62
+ function,
63
+ @broad_phase_query,
64
+ *query_arguments,
65
+ callback,
66
+ nil,
67
+ nil,
68
+ filter
69
+ )
70
+ bodies = body_ids.uniq.filter_map { |id| @body_registry[id] }
71
+ bodies.each { |body| yield body } if block_given?
72
+ bodies
73
+ ensure
74
+ Native.JPH_ObjectLayerFilter_Destroy(filter) if filter && !filter.null?
75
+ filter_context = callback = nil
76
+ end
77
+
78
+ def object_layer_filter(layer_mask)
79
+ return [nil, nil] if layer_mask.nil?
80
+
81
+ layer_ids = Array(layer_mask).map { |name| @layers.object_layer_id(name) }.uniq
82
+ Native::QueryFunctions.object_layer_filter(
83
+ Native, layer_ids, @layers.object_layers.length
84
+ )
85
+ end
86
+
87
+ def build_hit(origin, direction, result)
88
+ fraction = result[:fraction]
89
+ point = Native::Vec3.new
90
+ %i[x y z].each do |component|
91
+ point[component] = origin[component] + direction[component] * fraction
92
+ end
93
+
94
+ normal = Native::Vec3.new
95
+ body_pointer = Native.JPH_PhysicsSystem_GetBodyPtr(@pointer, result[:body_id])
96
+ unless body_pointer.null?
97
+ Native.JPH_Body_GetWorldSpaceSurfaceNormal(
98
+ body_pointer, result[:sub_shape_id2], point.pointer, normal.pointer
99
+ )
100
+ end
101
+
102
+ Hit.new(
103
+ body: @body_registry[result[:body_id]],
104
+ fraction:,
105
+ point: Conversions.vec3(point),
106
+ normal: Conversions.vec3(normal),
107
+ sub_shape_id: result[:sub_shape_id2]
108
+ )
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jolt
4
+ Transform = Data.define(:position, :rotation)
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jolt
4
+ VERSION = "1.0.0"
5
+ end
data/lib/jolt.rb ADDED
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "jolt/version"
4
+ require_relative "jolt/errors"
5
+ require_relative "jolt/native"
6
+ require_relative "jolt/conversions"
7
+ require_relative "jolt/layers"
8
+ require_relative "jolt/shape_builders"
9
+ require_relative "jolt/shape"
10
+ require_relative "jolt/fixed_stepper"
11
+ require_relative "jolt/transform"
12
+ require_relative "jolt/body_dynamics"
13
+ require_relative "jolt/body"
14
+ require_relative "jolt/body_collection"
15
+ require_relative "jolt/contact_events"
16
+ require_relative "jolt/hit"
17
+ require_relative "jolt/system_contacts"
18
+ require_relative "jolt/system_queries"
19
+ require_relative "jolt/constraint"
20
+ require_relative "jolt/constraint_collection"
21
+ require_relative "jolt/system_constraints"
22
+ require_relative "jolt/system_characters"
23
+ require_relative "jolt/system"
24
+ require_relative "jolt/character_virtual"
25
+
26
+ module Jolt
27
+ @lifecycle_mutex = Mutex.new
28
+ @initialized = false
29
+ @systems = []
30
+ @at_exit_registered = false
31
+
32
+ class << self
33
+ def init
34
+ @lifecycle_mutex.synchronize do
35
+ return self if @initialized
36
+
37
+ Native.load!
38
+ raise InitializationError, "Jolt Physics initialization failed" unless Native.JPH_Init
39
+
40
+ @initialized = true
41
+ unless @at_exit_registered
42
+ at_exit { shutdown }
43
+ @at_exit_registered = true
44
+ end
45
+ end
46
+
47
+ self
48
+ end
49
+
50
+ def initialized?
51
+ @lifecycle_mutex.synchronize { @initialized }
52
+ end
53
+
54
+ def shutdown
55
+ systems = @lifecycle_mutex.synchronize do
56
+ return unless @initialized
57
+
58
+ @systems.dup
59
+ end
60
+ systems.each(&:destroy)
61
+
62
+ @lifecycle_mutex.synchronize do
63
+ return unless @initialized
64
+
65
+ @systems.clear
66
+ Native.JPH_Shutdown
67
+ @initialized = false
68
+ end
69
+ end
70
+
71
+ def __register_system(system)
72
+ @lifecycle_mutex.synchronize do
73
+ raise InitializationError, "Jolt Physics is not initialized" unless @initialized
74
+
75
+ @systems << system
76
+ end
77
+ end
78
+
79
+ def __unregister_system(system)
80
+ @lifecycle_mutex.synchronize { @systems.delete(system) }
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubygems"
4
+
5
+ gem "jolt-ruby"
6
+ require "jolt"
7
+
8
+ smoke_home = File.realpath(ENV.fetch("JOLT_RUBY_SMOKE_HOME"))
9
+ loaded_gem = File.realpath(Gem.loaded_specs.fetch("jolt-ruby").full_gem_path)
10
+ unless loaded_gem.start_with?("#{smoke_home}#{File::SEPARATOR}")
11
+ raise "loaded jolt-ruby from #{loaded_gem}, expected an installation under #{smoke_home}"
12
+ end
13
+
14
+ begin
15
+ system = Jolt::System.new
16
+ missing_functions = Jolt::Native::Generated.missing_functions
17
+ unless missing_functions.empty?
18
+ raise "packaged native libraries are missing: #{missing_functions.join(", ")}"
19
+ end
20
+
21
+ body = system.bodies.create(shape: Jolt::Shape.sphere(0.5), position: [0, 2, 0])
22
+ system.update(1.0 / 60.0)
23
+ raise "packaged simulation did not advance" unless body.position.y < 2
24
+
25
+ puts "loaded and simulated with #{File.basename(loaded_gem)}"
26
+ ensure
27
+ system&.destroy
28
+ Jolt.shutdown
29
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubygems/package"
4
+
5
+ directory, tag = ARGV
6
+ abort "usage: #{$PROGRAM_NAME} GEM_DIRECTORY vVERSION" unless directory && tag
7
+ abort "release tag must have the form v1.2.3" unless tag.match?(/\Av\d+\.\d+\.\d+\z/)
8
+
9
+ version = tag.delete_prefix("v")
10
+ expected_platforms = %w[
11
+ ruby
12
+ x86_64-linux
13
+ aarch64-linux
14
+ arm64-darwin
15
+ x86_64-darwin
16
+ x64-mingw-ucrt
17
+ ].sort
18
+ gem_paths = Dir[File.join(directory, "*.gem")].sort
19
+ specifications = gem_paths.map { |path| Gem::Package.new(path).spec }
20
+
21
+ unless specifications.length == expected_platforms.length
22
+ abort "expected #{expected_platforms.length} gems, found #{specifications.length}"
23
+ end
24
+ unless specifications.all? { |specification| specification.name == "jolt-ruby" }
25
+ abort "release directory contains a gem other than jolt-ruby"
26
+ end
27
+ unless specifications.all? { |specification| specification.version.to_s == version }
28
+ abort "release gem version does not match tag #{tag}"
29
+ end
30
+
31
+ actual_platforms = specifications.map { |specification| specification.platform.to_s }.sort
32
+ unless actual_platforms == expected_platforms
33
+ abort "expected platforms #{expected_platforms.join(", ")}, found #{actual_platforms.join(", ")}"
34
+ end
35
+
36
+ puts "verified jolt-ruby #{version} for #{actual_platforms.join(", ")}"
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jolt-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Yudai Takada
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ffi
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.17'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.17'
26
+ - !ruby/object:Gem::Dependency
27
+ name: larb
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ description: A Ruby-friendly 3D physics API backed by Jolt Physics through joltc and
41
+ FFI.
42
+ email:
43
+ - t.yudai92@gmail.com
44
+ executables: []
45
+ extensions:
46
+ - ext/jolt_ruby/extconf.rb
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitmodules"
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - examples/character_virtual.rb
54
+ - examples/falling_sphere.rb
55
+ - examples/stagecraft_binding.rb
56
+ - ext/jolt_ruby/CMakeLists.txt
57
+ - ext/jolt_ruby/character_helper.cpp
58
+ - ext/jolt_ruby/constraint_helper.cpp
59
+ - ext/jolt_ruby/extconf.rb
60
+ - ext/jolt_ruby/helper.cpp
61
+ - ext/jolt_ruby/helper.h
62
+ - ext/joltc/.github/FUNDING.yml
63
+ - ext/joltc/.github/workflows/build.yml
64
+ - ext/joltc/.gitignore
65
+ - ext/joltc/CMakeLists.txt
66
+ - ext/joltc/LICENSE
67
+ - ext/joltc/README.md
68
+ - ext/joltc/build/cmake_vs2026_arm64.bat
69
+ - ext/joltc/build/cmake_vs2026_clang.bat
70
+ - ext/joltc/build/cmake_vs2026_x64.bat
71
+ - ext/joltc/build/cmake_vs2026_x64_double.bat
72
+ - ext/joltc/include/joltc.h
73
+ - ext/joltc/samples/01_HelloWorld/main.cpp
74
+ - ext/joltc/samples/CMakeLists.txt
75
+ - ext/joltc/src/joltc.c
76
+ - ext/joltc/src/joltc.cpp
77
+ - ext/joltc/src/joltc_assert.cpp
78
+ - ext/joltc/tests/CMakeLists.txt
79
+ - ext/joltc/tests/test_character.cpp
80
+ - ext/joltc/tests/test_collision.cpp
81
+ - ext/joltc/tests/test_constraints.cpp
82
+ - ext/joltc/tests/test_core.cpp
83
+ - ext/joltc/tests/test_math.cpp
84
+ - ext/joltc/tests/test_physics_system.cpp
85
+ - ext/joltc/tests/test_shapes.cpp
86
+ - ext/joltc/tests/test_skeleton.cpp
87
+ - ext/joltc/tests/test_vehicle.cpp
88
+ - generator/generate.rb
89
+ - generator/layout_probe.cpp
90
+ - generator/verify_layout.rb
91
+ - lib/jolt.rb
92
+ - lib/jolt/body.rb
93
+ - lib/jolt/body_collection.rb
94
+ - lib/jolt/body_dynamics.rb
95
+ - lib/jolt/character_virtual.rb
96
+ - lib/jolt/constraint.rb
97
+ - lib/jolt/constraint_collection.rb
98
+ - lib/jolt/contact_events.rb
99
+ - lib/jolt/conversions.rb
100
+ - lib/jolt/errors.rb
101
+ - lib/jolt/fixed_stepper.rb
102
+ - lib/jolt/hit.rb
103
+ - lib/jolt/layers.rb
104
+ - lib/jolt/native.rb
105
+ - lib/jolt/native/character_functions.rb
106
+ - lib/jolt/native/constraint_functions.rb
107
+ - lib/jolt/native/core_functions.rb
108
+ - lib/jolt/native/generated.rb
109
+ - lib/jolt/native/platform.rb
110
+ - lib/jolt/native/query_functions.rb
111
+ - lib/jolt/native/types.rb
112
+ - lib/jolt/shape.rb
113
+ - lib/jolt/shape_builders.rb
114
+ - lib/jolt/system.rb
115
+ - lib/jolt/system_characters.rb
116
+ - lib/jolt/system_constraints.rb
117
+ - lib/jolt/system_contacts.rb
118
+ - lib/jolt/system_queries.rb
119
+ - lib/jolt/transform.rb
120
+ - lib/jolt/version.rb
121
+ - script/smoke_gem.rb
122
+ - script/verify_release.rb
123
+ homepage: https://github.com/ydah/jolt-ruby
124
+ licenses:
125
+ - MIT
126
+ metadata:
127
+ homepage_uri: https://github.com/ydah/jolt-ruby
128
+ source_code_uri: https://github.com/ydah/jolt-ruby/tree/main
129
+ rubygems_mfa_required: 'true'
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 3.2.0
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubygems_version: 4.0.6
145
+ specification_version: 4
146
+ summary: Ruby bindings for the Jolt Physics engine
147
+ test_files: []