raylib-bindings 0.5.8pre1-arm64-darwin

Sign up to get free protection for your applications and to get access to all the features.
data/lib/raylib.rb ADDED
@@ -0,0 +1,62 @@
1
+ # Yet another raylib wrapper for Ruby
2
+ #
3
+ # * https://github.com/vaiorabbit/raylib-bindings
4
+
5
+ require 'ffi'
6
+ require 'fileutils'
7
+ require_relative 'raylib_main'
8
+ require_relative 'config'
9
+ require_relative 'raymath'
10
+ require_relative 'rcamera'
11
+ require_relative 'rlgl'
12
+ require_relative 'raygui_main'
13
+ require_relative 'physac'
14
+ require_relative 'raylib_helper'
15
+ require_relative 'raygui_helper'
16
+
17
+ module Raylib
18
+ extend FFI::Library
19
+
20
+ def self.load_lib(libpath, raygui_libpath: nil, physac_libpath: nil)
21
+ lib_paths = [libpath, raygui_libpath, physac_libpath].compact
22
+
23
+ ffi_lib_flags :now, :global
24
+ ffi_lib(*lib_paths)
25
+ setup_symbols
26
+
27
+ setup_raygui_symbols unless raygui_libpath.nil?
28
+ setup_physac_symbols unless physac_libpath.nil?
29
+ rescue LoadError => e
30
+ warn e
31
+ end
32
+
33
+ def self.setup_symbols
34
+ setup_raylib_symbols
35
+ setup_raymath_symbols
36
+ setup_rcamera_symbols
37
+ setup_rlgl_symbols
38
+ end
39
+
40
+ #
41
+ # Generate sample code
42
+ #
43
+ def self.template
44
+ # Copy template code to user's current directory
45
+ example_path = "#{Gem::Specification.find_by_name('raylib-bindings').full_gem_path}/examples"
46
+ template_code_src = "#{example_path}/template.rb"
47
+ unless File.exist? template_code_src
48
+ warn "[Error] Raylib.template : Template source #{template_code_src} not found"
49
+ return false
50
+ end
51
+
52
+ template_code_dst = "#{Dir.getwd}/template.rb"
53
+ if File.exist? template_code_dst
54
+ warn "[Error] Raylib.template : Template destination #{template_code_dst} already exists"
55
+ return false
56
+ end
57
+
58
+ warn "[Info] Raylib.template : #{template_code_src} => #{template_code_dst}"
59
+ FileUtils.copy template_code_src, template_code_dst
60
+ warn '[Info] Raylib.template : Done'
61
+ end
62
+ end
@@ -0,0 +1,400 @@
1
+ # Yet another raylib wrapper for Ruby
2
+ #
3
+ # * https://github.com/vaiorabbit/raylib-bindings
4
+
5
+ module Raylib
6
+ #
7
+ # Color helper
8
+ #
9
+
10
+ class Color
11
+ def self.from_u8(r = 0, g = 0, b = 0, a = 255)
12
+ Color.new.set(r, g, b, a)
13
+ end
14
+
15
+ def set(r, g, b, a)
16
+ self[:r] = r
17
+ self[:g] = g
18
+ self[:b] = b
19
+ self[:a] = a
20
+ self
21
+ end
22
+
23
+ def copy(other)
24
+ self[:r] = other.r
25
+ self[:g] = other.g
26
+ self[:b] = other.b
27
+ self[:a] = other.a
28
+ self
29
+ end
30
+ end
31
+
32
+ LIGHTGRAY = Color.from_u8(200, 200, 200, 255)
33
+ GRAY = Color.from_u8(130, 130, 130, 255)
34
+ DARKGRAY = Color.from_u8(80, 80, 80, 255)
35
+ YELLOW = Color.from_u8(253, 249, 0, 255)
36
+ GOLD = Color.from_u8(255, 203, 0, 255)
37
+ ORANGE = Color.from_u8(255, 161, 0, 255)
38
+ PINK = Color.from_u8(255, 109, 194, 255)
39
+ RED = Color.from_u8(230, 41, 55, 255)
40
+ MAROON = Color.from_u8(190, 33, 55, 255)
41
+ GREEN = Color.from_u8(0, 228, 48, 255)
42
+ LIME = Color.from_u8(0, 158, 47, 255)
43
+ DARKGREEN = Color.from_u8(0, 117, 44, 255)
44
+ SKYBLUE = Color.from_u8(102, 191, 255, 255)
45
+ BLUE = Color.from_u8(0, 121, 241, 255)
46
+ DARKBLUE = Color.from_u8(0, 82, 172, 255)
47
+ PURPLE = Color.from_u8(200, 122, 255, 255)
48
+ VIOLET = Color.from_u8(135, 60, 190, 255)
49
+ DARKPURPLE = Color.from_u8(112, 31, 126, 255)
50
+ BEIGE = Color.from_u8(211, 176, 131, 255)
51
+ BROWN = Color.from_u8(127, 106, 79, 255)
52
+ DARKBROWN = Color.from_u8(76, 63, 47, 255)
53
+
54
+ WHITE = Color.from_u8(255, 255, 255, 255)
55
+ BLACK = Color.from_u8(0, 0, 0, 255)
56
+ BLANK = Color.from_u8(0, 0, 0, 0)
57
+ MAGENTA = Color.from_u8(255, 0, 255, 255)
58
+ RAYWHITE = Color.from_u8(245, 245, 245, 255)
59
+
60
+ #
61
+ # Math helper
62
+ #
63
+
64
+ class Vector2
65
+ def self.create(x = 0, y = 0)
66
+ Vector2.new.set(x, y)
67
+ end
68
+
69
+ def self.copy_from(vec)
70
+ Vector2.create(vec[:x], vec[:y])
71
+ end
72
+
73
+ def set(x, y)
74
+ self[:x] = x
75
+ self[:y] = y
76
+ self
77
+ end
78
+
79
+ def to_a
80
+ [x, y]
81
+ end
82
+ end
83
+
84
+ class Vector3
85
+ def self.create(x = 0, y = 0, z = 0)
86
+ Vector3.new.set(x, y, z)
87
+ end
88
+
89
+ def self.copy_from(vec)
90
+ Vector3.create(vec[:x], vec[:y], vec[:z])
91
+ end
92
+
93
+ def set(x, y, z)
94
+ self[:x] = x
95
+ self[:y] = y
96
+ self[:z] = z
97
+ self
98
+ end
99
+
100
+ def to_a
101
+ [x, y, z]
102
+ end
103
+ end
104
+
105
+ class Vector4
106
+ def self.create(x = 0, y = 0, z = 0, w = 0)
107
+ Vector4.new.set(x, y, z, w)
108
+ end
109
+
110
+ def self.copy_from(vec)
111
+ Vector4.create(vec[:x], vec[:y], vec[:z], vec[:w])
112
+ end
113
+
114
+ def set(x, y, z, w)
115
+ self[:x] = x
116
+ self[:y] = y
117
+ self[:z] = z
118
+ self[:w] = w
119
+ self
120
+ end
121
+
122
+ def to_a
123
+ [x, y, z, w]
124
+ end
125
+ end
126
+
127
+ class Quaternion
128
+ def self.create(x = 0, y = 0, z = 0, w = 0)
129
+ Quaternion.new.set(x, y, z, w)
130
+ end
131
+
132
+ def self.copy_from(quat)
133
+ Quaternion.create(quat[:x], quat[:y], quat[:z], quat[:w])
134
+ end
135
+
136
+ def set(x, y, z, w)
137
+ self[:x] = x
138
+ self[:y] = y
139
+ self[:z] = z
140
+ self[:w] = w
141
+ self
142
+ end
143
+
144
+ def to_a
145
+ [x, y, z, w]
146
+ end
147
+ end
148
+
149
+ class Rectangle
150
+ def self.create(x = 0, y = 0, width = 0, height = 0)
151
+ Rectangle.new.set(x, y, width, height)
152
+ end
153
+
154
+ def set(x, y, width, height)
155
+ self[:x] = x
156
+ self[:y] = y
157
+ self[:width] = width
158
+ self[:height] = height
159
+ self
160
+ end
161
+ end
162
+
163
+ class BoundingBox
164
+ def self.create(*args)
165
+ case args.size
166
+ when 2
167
+ instance = BoundingBox.new
168
+ instance[:min] = args[0] # min
169
+ instance[:max] = args[1] # max
170
+ instance
171
+ when 6
172
+ instance = BoundingBox.new
173
+ instance[:min] = Vector3.create(args[0], args[1], args[2]) # min_x, min_y, min_z
174
+ instance[:max] = Vector3.create(args[3], args[4], args[5]) # max_x, max_y, max_z
175
+ instance
176
+ else
177
+ raise ArgumentError.new 'BoundingBox.create : Number of arguments must be 2 or 6'
178
+ end
179
+ end
180
+
181
+ def with_min(x, y, z)
182
+ self[:min].set(x, y, z)
183
+ self
184
+ end
185
+
186
+ def with_max(x, y, z)
187
+ self[:max].set(x, y, z)
188
+ self
189
+ end
190
+ end
191
+
192
+ def Vector3ToFloat(vec)
193
+ Vector3ToFloatV(vec)[:v].to_a
194
+ end
195
+
196
+ def MatrixToFloat(mat)
197
+ MatrixToFloatV(mat)[:v].to_a
198
+ end
199
+
200
+ #
201
+ # Camera helper
202
+ #
203
+
204
+ class Camera3D
205
+ def with_position(x, y, z)
206
+ self[:position].set(x, y, z)
207
+ self
208
+ end
209
+
210
+ def with_target(x, y, z)
211
+ self[:target].set(x, y, z)
212
+ self
213
+ end
214
+
215
+ def with_up(x, y, z)
216
+ self[:up].set(x, y, z)
217
+ self
218
+ end
219
+
220
+ def with_fovy(fovy)
221
+ self[:fovy] = fovy
222
+ self
223
+ end
224
+
225
+ def with_projection(projection)
226
+ self[:projection] = projection
227
+ self
228
+ end
229
+ end
230
+
231
+ class Camera2D
232
+ def with_offset(x, y)
233
+ self[:offset].set(x, y)
234
+ self
235
+ end
236
+
237
+ def with_target(x, y)
238
+ self[:target].set(x, y)
239
+ self
240
+ end
241
+
242
+ def with_rotation(rotation)
243
+ self[:rotation] = rotation
244
+ self
245
+ end
246
+
247
+ def with_zoom(zoom)
248
+ self[:zoom] = zoom
249
+ self
250
+ end
251
+ end
252
+
253
+ #
254
+ # Transform helper
255
+ #
256
+
257
+ class Transform
258
+ def t = self[:translation]
259
+ def r = self[:rotation]
260
+ def s = self[:scale]
261
+ end
262
+
263
+ #
264
+ # Model helper
265
+ #
266
+
267
+ # DrawModelEx : Draw a model with extended parameters
268
+ # @param model [Model]
269
+ # @param position [Vector3]
270
+ # @param rotationAxis [Vector3]
271
+ # @param rotationAngle [float]
272
+ # @param scale [Vector3]
273
+ # @param tint [Color]
274
+ # @return [void]
275
+ def DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint)
276
+ # [NOTE] Fixing unintended matrix modification
277
+ # - In C, DrawModelEx uses the whole copy of `model` on stack, which will never affect the content of original `model`.
278
+ # But Ruby FFI seems to pass the reference of `model` to DrawModelEx, which results in transform accumulation (e.g.:`model` get rotated by `rotationAngle` around `rotationAxis` every frame).
279
+ # So here I copy the transform into `mtx_clone` and copy back this to the original after finished calling DrawModelEx.
280
+ # - Other DrawXXX members (DrawModel, DrawModelWires, DrawModelWiresEx) are free from this problem.
281
+ # - They call DrawModelEx in C layer, which will use the copy of `model` on stack.
282
+ mtx_clone = model[:transform].clone
283
+ internalDrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint)
284
+ model[:transform] = mtx_clone
285
+ end
286
+
287
+ class Model
288
+ # GetModelMaterial (ruby raylib original)
289
+ # @param index [int] 0 ~ materialCount
290
+ # @return [Material]
291
+ def material(index = 0)
292
+ Material.new(self[:materials] + index * Material.size)
293
+ end
294
+
295
+ # GetModelMaterialCount (ruby raylib original)
296
+ # @return [int]
297
+ def material_count
298
+ self[:materialCount]
299
+ end
300
+
301
+ # GetModelBoneCount (ruby raylib original)
302
+ # @return [int]
303
+ def bone_count
304
+ self[:boneCount]
305
+ end
306
+
307
+ # @return BoneInfo
308
+ def bone_info(index)
309
+ BoneInfo.new(self[:bones] + index * BoneInfo.size)
310
+ end
311
+
312
+ # @return Transform
313
+ def bind_pose_transform(index)
314
+ Transform.new(self[:bindPose] + index * Transform.size)
315
+ end
316
+ end
317
+
318
+ class BoneInfo
319
+ def parent_bone_index
320
+ self[:parent]
321
+ end
322
+ end
323
+
324
+ #
325
+ # ModelAnimation helper
326
+ #
327
+
328
+ # Manages a set of ModelAnimation (ruby raylib original)
329
+ class ModelAnimations
330
+ attr_reader :anims, :anim_ptrs
331
+
332
+ def initialize
333
+ @anims = nil
334
+ @anim_ptrs = nil
335
+ @framePoses = nil # array of Transform**
336
+ end
337
+
338
+ def anim(index) = @anims[index]
339
+ def anims_count = @anims.length
340
+ def frame_count(index) = @anims[index][:frameCount]
341
+
342
+ # @return BoneInfo
343
+ def bone_info(anim_index, bone_index)
344
+ BoneInfo.new(@anims[anim_index][:bones] + bone_index * BoneInfo.size)
345
+ end
346
+
347
+ # @return Transform*
348
+ def frame_pose(index, frame)
349
+ @framePoses[index] + frame * FFI::NativeType::POINTER.size # Transform*
350
+ end
351
+
352
+ # @return Transform
353
+ def bone_transform(frame_pose, bone_index)
354
+ Transform.new(frame_pose.read_pointer + bone_index * Transform.size)
355
+ end
356
+
357
+ # @return Transform
358
+ def bone_transform_of_frame_pose(anim_index, frame, bone_index)
359
+ bone_transform(frame_pose(anim_index, frame), bone_index)
360
+ end
361
+
362
+ # @return self
363
+ def setup(fileName)
364
+ @anims, @anim_ptrs = LoadAndAllocateModelAnimations(fileName)
365
+ @framePoses = []
366
+ @anims.each do |anim|
367
+ @framePoses << anim[:framePoses]
368
+ end
369
+ self
370
+ end
371
+
372
+ def cleanup
373
+ UnloadAndFreeModelAnimations(@anims, @anim_ptrs)
374
+ end
375
+ end
376
+
377
+ # LoadAndAllocateModelAnimations : (ruby raylib original)
378
+ # @param fileName [const char *]
379
+ # @return array of ModelAnimation and pointer to loaded memory
380
+ def LoadAndAllocateModelAnimations(fileName)
381
+ animsCount_buf = FFI::MemoryPointer.new(:uint, 1)
382
+ anim_ptrs = LoadModelAnimations(fileName, animsCount_buf)
383
+ animsCount = animsCount_buf.read_uint
384
+ anims = animsCount.times.map do |i|
385
+ ModelAnimation.new(anim_ptrs + i * ModelAnimation.size)
386
+ end
387
+ return anims, anim_ptrs
388
+ end
389
+
390
+ # UnloadAndFreeModelAnimations : (ruby raylib original)
391
+ # @param anims [array of ModelAnimation]
392
+ # @param anim_ptrs [pointer to loaded memory]
393
+ def UnloadAndFreeModelAnimations(anims, anim_ptrs)
394
+ anims.each do |anim|
395
+ UnloadModelAnimation(anim)
396
+ end
397
+ MemFree(anim_ptrs)
398
+ end
399
+
400
+ end