processing 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +4 -4
- data/.github/workflows/test.yml +3 -3
- data/ChangeLog.md +7 -0
- data/LICENSE +1 -1
- data/VERSION +1 -1
- data/examples/breakout.rb +2 -1
- data/examples/camera.rb +2 -1
- data/examples/clock.rb +3 -1
- data/examples/delay_camera.rb +2 -1
- data/examples/hello.rb +2 -1
- data/examples/image.rb +2 -1
- data/examples/shapes.rb +2 -1
- data/lib/processing/all.rb +20 -0
- data/lib/processing/capture.rb +119 -0
- data/lib/processing/context.rb +471 -0
- data/lib/processing/font.rb +62 -0
- data/lib/processing/graphics.rb +40 -0
- data/lib/processing/graphics_context.rb +1676 -0
- data/lib/processing/image.rb +128 -0
- data/lib/processing/shader.rb +157 -0
- data/lib/processing/touch.rb +28 -0
- data/lib/processing/vector.rb +559 -0
- data/lib/processing.rb +30 -11
- data/lib/rubysketch-processing.rb +1 -1
- data/lib/rubysketch.rb +1 -1
- data/processing.gemspec +2 -2
- data/src/RubyProcessing.mm +1 -1
- data/test/helper.rb +8 -2
- data/test/{processing/test_graphics.rb → test_graphics.rb} +3 -3
- data/test/{processing/test_shader.rb → test_shader.rb} +3 -3
- data/test/{processing/test_utility.rb → test_utility.rb} +3 -3
- data/test/{processing/test_vector.rb → test_vector.rb} +8 -4
- metadata +24 -18
- data/lib/processing/include.rb +0 -25
- data/lib/processing/processing.rb +0 -3211
- data/test/processing/helper.rb +0 -11
@@ -1,3211 +0,0 @@
|
|
1
|
-
module Processing
|
2
|
-
|
3
|
-
|
4
|
-
# Processing compatible API
|
5
|
-
#
|
6
|
-
module Processing
|
7
|
-
|
8
|
-
|
9
|
-
# @private
|
10
|
-
DEG2RAD__ = Math::PI / 180.0
|
11
|
-
|
12
|
-
# @private
|
13
|
-
RAD2DEG__ = 180.0 / Math::PI
|
14
|
-
|
15
|
-
|
16
|
-
# Vector class.
|
17
|
-
#
|
18
|
-
class Vector
|
19
|
-
|
20
|
-
include Comparable
|
21
|
-
|
22
|
-
# Initialize vector object.
|
23
|
-
#
|
24
|
-
# @overload new()
|
25
|
-
# @overload new(x)
|
26
|
-
# @overload new(x, y)
|
27
|
-
# @overload new(x, y, z)
|
28
|
-
# @overload new(v)
|
29
|
-
# @overload new(a)
|
30
|
-
#
|
31
|
-
# @param x [Numeric] x of vector
|
32
|
-
# @param y [Numeric] y of vector
|
33
|
-
# @param z [Numeric] z of vector
|
34
|
-
# @param v [Vector] vector object to copy
|
35
|
-
# @param a [Array] array like [x, y, z]
|
36
|
-
#
|
37
|
-
def initialize(x = 0, y = 0, z = 0, context: nil)
|
38
|
-
@point = case x
|
39
|
-
when Rays::Point then x.dup
|
40
|
-
when Vector then x.getInternal__.dup
|
41
|
-
when Array then Rays::Point.new x[0] || 0, x[1] || 0, x[2] || 0
|
42
|
-
else Rays::Point.new x || 0, y || 0, z || 0
|
43
|
-
end
|
44
|
-
@context = context || Context.context__
|
45
|
-
end
|
46
|
-
|
47
|
-
# Initializer for dup or clone
|
48
|
-
#
|
49
|
-
def initialize_copy(o)
|
50
|
-
@point = o.getInternal__.dup
|
51
|
-
end
|
52
|
-
|
53
|
-
# Copy vector object
|
54
|
-
#
|
55
|
-
# @return [Vector] duplicated vector object
|
56
|
-
#
|
57
|
-
alias copy dup
|
58
|
-
|
59
|
-
# Sets x, y and z.
|
60
|
-
#
|
61
|
-
# @overload set(x)
|
62
|
-
# @overload set(x, y)
|
63
|
-
# @overload set(x, y, z)
|
64
|
-
# @overload set(v)
|
65
|
-
# @overload set(a)
|
66
|
-
#
|
67
|
-
# @param x [Numeric] x of vector
|
68
|
-
# @param y [Numeric] y of vector
|
69
|
-
# @param z [Numeric] z of vector
|
70
|
-
# @param v [Vector] vector object to copy
|
71
|
-
# @param a [Array] array with x, y, z
|
72
|
-
#
|
73
|
-
# @return [nil] nil
|
74
|
-
#
|
75
|
-
def set(*args)
|
76
|
-
initialize(*args)
|
77
|
-
self
|
78
|
-
end
|
79
|
-
|
80
|
-
# Gets x value.
|
81
|
-
#
|
82
|
-
# @return [Numeric] x value of vector
|
83
|
-
#
|
84
|
-
def x()
|
85
|
-
@point.x
|
86
|
-
end
|
87
|
-
|
88
|
-
# Gets y value.
|
89
|
-
#
|
90
|
-
# @return [Numeric] y value of vector
|
91
|
-
#
|
92
|
-
def y()
|
93
|
-
@point.y
|
94
|
-
end
|
95
|
-
|
96
|
-
# Gets z value.
|
97
|
-
#
|
98
|
-
# @return [Numeric] z value of vector
|
99
|
-
#
|
100
|
-
def z()
|
101
|
-
@point.z
|
102
|
-
end
|
103
|
-
|
104
|
-
# Sets x value.
|
105
|
-
#
|
106
|
-
# @return [Numeric] x value of vector
|
107
|
-
#
|
108
|
-
def x=(x)
|
109
|
-
@point.x = x
|
110
|
-
end
|
111
|
-
|
112
|
-
# Sets y value.
|
113
|
-
#
|
114
|
-
# @return [Numeric] y value of vector
|
115
|
-
#
|
116
|
-
def y=(y)
|
117
|
-
@point.y = y
|
118
|
-
end
|
119
|
-
|
120
|
-
# Sets z value.
|
121
|
-
#
|
122
|
-
# @return [Numeric] z value of vector
|
123
|
-
#
|
124
|
-
def z=(z)
|
125
|
-
@point.z = z
|
126
|
-
end
|
127
|
-
|
128
|
-
# Returns the interpolated vector between 2 vectors.
|
129
|
-
#
|
130
|
-
# @overload lerp(v, amount)
|
131
|
-
# @overload lerp(x, y, amount)
|
132
|
-
# @overload lerp(x, y, z, amount)
|
133
|
-
#
|
134
|
-
# @param v [Vector] vector to interpolate
|
135
|
-
# @param x [Numeric] x of vector to interpolate
|
136
|
-
# @param y [Numeric] y of vector to interpolate
|
137
|
-
# @param z [Numeric] z of vector to interpolate
|
138
|
-
# @param amount [Numeric] amount to interpolate
|
139
|
-
#
|
140
|
-
# @return [Vector] interporated vector
|
141
|
-
#
|
142
|
-
def lerp(*args, amount)
|
143
|
-
v = toVector__(*args)
|
144
|
-
self.x = x + (v.x - x) * amount
|
145
|
-
self.y = y + (v.y - y) * amount
|
146
|
-
self.z = z + (v.z - z) * amount
|
147
|
-
self
|
148
|
-
end
|
149
|
-
|
150
|
-
# Returns the interpolated vector between 2 vectors.
|
151
|
-
#
|
152
|
-
# @param v1 [Vector] vector to interpolate
|
153
|
-
# @param v2 [Vector] vector to interpolate
|
154
|
-
# @param amount [Numeric] amount to interpolate
|
155
|
-
#
|
156
|
-
# @return [Vector] interporated vector
|
157
|
-
#
|
158
|
-
def self.lerp(v1, v2, amount)
|
159
|
-
v1.dup.lerp v2, amount
|
160
|
-
end
|
161
|
-
|
162
|
-
# Returns x, y, z as an array
|
163
|
-
#
|
164
|
-
# @return [Array] array of x, y, z
|
165
|
-
#
|
166
|
-
def array()
|
167
|
-
@point.to_a 3
|
168
|
-
end
|
169
|
-
|
170
|
-
# Adds a vector.
|
171
|
-
#
|
172
|
-
# @overload add(v)
|
173
|
-
# @overload add(x, y)
|
174
|
-
# @overload add(x, y, z)
|
175
|
-
#
|
176
|
-
# @param v [Vector] vector to add
|
177
|
-
# @param x [Vector] x of vector to add
|
178
|
-
# @param y [Vector] y of vector to add
|
179
|
-
# @param z [Vector] z of vector to add
|
180
|
-
#
|
181
|
-
# @return [Vector] added vector
|
182
|
-
#
|
183
|
-
def add(*args)
|
184
|
-
@point += toVector__(*args).getInternal__
|
185
|
-
self
|
186
|
-
end
|
187
|
-
|
188
|
-
# Subtracts a vector.
|
189
|
-
#
|
190
|
-
# @overload sub(v)
|
191
|
-
# @overload sub(x, y)
|
192
|
-
# @overload sub(x, y, z)
|
193
|
-
#
|
194
|
-
# @param v [Vector] vector to subtract
|
195
|
-
# @param x [Vector] x of vector to subtract
|
196
|
-
# @param y [Vector] y of vector to subtract
|
197
|
-
# @param z [Vector] z of vector to subtract
|
198
|
-
#
|
199
|
-
# @return [Vector] subtracted vector
|
200
|
-
#
|
201
|
-
def sub(*args)
|
202
|
-
@point -= toVector__(*args).getInternal__
|
203
|
-
self
|
204
|
-
end
|
205
|
-
|
206
|
-
# Multiplies a vector by scalar.
|
207
|
-
#
|
208
|
-
# @param num [Numeric] number to multiply the vector
|
209
|
-
#
|
210
|
-
# @return [Vector] multiplied vector
|
211
|
-
#
|
212
|
-
def mult(num)
|
213
|
-
@point *= num
|
214
|
-
self
|
215
|
-
end
|
216
|
-
|
217
|
-
# Divides a vector by scalar.
|
218
|
-
#
|
219
|
-
# @param num [Numeric] number to divide the vector
|
220
|
-
#
|
221
|
-
# @return [Vector] divided vector
|
222
|
-
#
|
223
|
-
def div(num)
|
224
|
-
@point /= num
|
225
|
-
self
|
226
|
-
end
|
227
|
-
|
228
|
-
# Adds a vector.
|
229
|
-
#
|
230
|
-
# @param v [Vector] vector to add
|
231
|
-
#
|
232
|
-
# @return [Vector] added vector
|
233
|
-
#
|
234
|
-
def +(v)
|
235
|
-
dup.add v
|
236
|
-
end
|
237
|
-
|
238
|
-
# Subtracts a vector.
|
239
|
-
#
|
240
|
-
# @param v [Vector] vector to subtract
|
241
|
-
#
|
242
|
-
# @return [Vector] subtracted vector
|
243
|
-
#
|
244
|
-
def -(v)
|
245
|
-
dup.sub v
|
246
|
-
end
|
247
|
-
|
248
|
-
# Multiplies a vector by scalar.
|
249
|
-
#
|
250
|
-
# @param num [Numeric] number to multiply the vector
|
251
|
-
#
|
252
|
-
# @return [Vector] multiplied vector
|
253
|
-
#
|
254
|
-
def *(num)
|
255
|
-
dup.mult num
|
256
|
-
end
|
257
|
-
|
258
|
-
# Divides a vector by scalar.
|
259
|
-
#
|
260
|
-
# @param num [Numeric] number to divide the vector
|
261
|
-
#
|
262
|
-
# @return [Vector] divided vector
|
263
|
-
#
|
264
|
-
def /(num)
|
265
|
-
dup.div num
|
266
|
-
end
|
267
|
-
|
268
|
-
# Adds 2 vectors.
|
269
|
-
#
|
270
|
-
# @overload add(v1, v2)
|
271
|
-
# @overload add(v1, v2, target)
|
272
|
-
#
|
273
|
-
# @param v1 [Vector] a vector
|
274
|
-
# @param v2 [Vector] another vector
|
275
|
-
# @param target [Vector] vector to store added vector
|
276
|
-
#
|
277
|
-
# @return [Vector] added vector
|
278
|
-
#
|
279
|
-
def self.add(v1, v2, target = nil)
|
280
|
-
v = v1 + v2
|
281
|
-
target.set v if self === target
|
282
|
-
v
|
283
|
-
end
|
284
|
-
|
285
|
-
# Subtracts 2 vectors.
|
286
|
-
#
|
287
|
-
# @overload sub(v1, v2)
|
288
|
-
# @overload sub(v1, v2, target)
|
289
|
-
#
|
290
|
-
# @param v1 [Vector] a vector
|
291
|
-
# @param v2 [Vector] another vector
|
292
|
-
# @param target [Vector] vector to store subtracted vector
|
293
|
-
#
|
294
|
-
# @return [Vector] subtracted vector
|
295
|
-
#
|
296
|
-
def self.sub(v1, v2, target = nil)
|
297
|
-
v = v1 - v2
|
298
|
-
target.set v if self === target
|
299
|
-
v
|
300
|
-
end
|
301
|
-
|
302
|
-
# Multiplies a vector by scalar.
|
303
|
-
#
|
304
|
-
# @overload mult(v, num)
|
305
|
-
# @overload mult(v, num, target)
|
306
|
-
#
|
307
|
-
# @param v [Vector] a vector
|
308
|
-
# @param num [Numeric] number to multiply the vector
|
309
|
-
# @param target [Vector] vector to store multiplied vector
|
310
|
-
#
|
311
|
-
# @return [Vector] multiplied vector
|
312
|
-
#
|
313
|
-
def self.mult(v1, num, target = nil)
|
314
|
-
v = v1 * num
|
315
|
-
target.set v if self === target
|
316
|
-
v
|
317
|
-
end
|
318
|
-
|
319
|
-
# Divides a vector by scalar.
|
320
|
-
#
|
321
|
-
# @overload div(v, num)
|
322
|
-
# @overload div(v, num, target)
|
323
|
-
#
|
324
|
-
# @param v [Vector] a vector
|
325
|
-
# @param num [Numeric] number to divide the vector
|
326
|
-
# @param target [Vector] vector to store divided vector
|
327
|
-
#
|
328
|
-
# @return [Vector] divided vector
|
329
|
-
#
|
330
|
-
def self.div(v1, num, target = nil)
|
331
|
-
v = v1 / num
|
332
|
-
target.set v if self === target
|
333
|
-
v
|
334
|
-
end
|
335
|
-
|
336
|
-
# Returns the length of the vector.
|
337
|
-
#
|
338
|
-
# @return [Numeric] length
|
339
|
-
#
|
340
|
-
def mag()
|
341
|
-
@point.length
|
342
|
-
end
|
343
|
-
|
344
|
-
# Returns squared length of the vector.
|
345
|
-
#
|
346
|
-
# @return [Numeric] squared length
|
347
|
-
#
|
348
|
-
def magSq()
|
349
|
-
Rays::Point::dot(@point, @point)
|
350
|
-
end
|
351
|
-
|
352
|
-
# Changes the length of the vector.
|
353
|
-
#
|
354
|
-
# @overload setMag(len)
|
355
|
-
# @overload setMag(target, len)
|
356
|
-
#
|
357
|
-
# @param len [Numeric] length of new vector
|
358
|
-
# @param target [Vector] vector to store new vector
|
359
|
-
#
|
360
|
-
# @return [Vector] vector with new length
|
361
|
-
#
|
362
|
-
def setMag(target = nil, len)
|
363
|
-
(target || self).set @point.normal * len
|
364
|
-
end
|
365
|
-
|
366
|
-
# Changes the length of the vector to 1.0.
|
367
|
-
#
|
368
|
-
# @param target [Vector] vector to store the normalized vector
|
369
|
-
#
|
370
|
-
# @return [Vector] normalized vector
|
371
|
-
#
|
372
|
-
def normalize(target = nil)
|
373
|
-
(target || self).set @point.normal
|
374
|
-
end
|
375
|
-
|
376
|
-
# Changes the length of the vector if it's length is greater than the max value.
|
377
|
-
#
|
378
|
-
# @param max [Numeric] max length
|
379
|
-
#
|
380
|
-
# @return [Vector] new vector
|
381
|
-
#
|
382
|
-
def limit(max)
|
383
|
-
setMag max if magSq > max ** 2
|
384
|
-
self
|
385
|
-
end
|
386
|
-
|
387
|
-
# Returns the distance of 2 vectors.
|
388
|
-
#
|
389
|
-
# @param v [Vector] a vector
|
390
|
-
#
|
391
|
-
# @return [Numeric] the distance
|
392
|
-
#
|
393
|
-
def dist(v)
|
394
|
-
(self - v).mag
|
395
|
-
end
|
396
|
-
|
397
|
-
# Returns the distance of 2 vectors.
|
398
|
-
#
|
399
|
-
# @param v1 [Vector] a vector
|
400
|
-
# @param v2 [Vector] another vector
|
401
|
-
#
|
402
|
-
# @return [Numeric] the distance
|
403
|
-
#
|
404
|
-
def self.dist(v1, v2)
|
405
|
-
v1.dist v2
|
406
|
-
end
|
407
|
-
|
408
|
-
# Calculates the dot product of 2 vectors.
|
409
|
-
#
|
410
|
-
# @overload dot(v)
|
411
|
-
# @overload dot(x, y)
|
412
|
-
# @overload dot(x, y, z)
|
413
|
-
#
|
414
|
-
# @param v [Vector] a vector
|
415
|
-
# @param x [Numeric] x of vector
|
416
|
-
# @param y [Numeric] y of vector
|
417
|
-
# @param z [Numeric] z of vector
|
418
|
-
#
|
419
|
-
# @return [Numeric] result of dot product
|
420
|
-
#
|
421
|
-
def dot(*args)
|
422
|
-
Rays::Point::dot getInternal__, toVector__(*args).getInternal__
|
423
|
-
end
|
424
|
-
|
425
|
-
# Calculates the dot product of 2 vectors.
|
426
|
-
#
|
427
|
-
# @param v1 [Vector] a vector
|
428
|
-
# @param v2 [Vector] another vector
|
429
|
-
#
|
430
|
-
# @return [Numeric] result of dot product
|
431
|
-
#
|
432
|
-
def self.dot(v1, v2)
|
433
|
-
v1.dot v2
|
434
|
-
end
|
435
|
-
|
436
|
-
# Calculates the cross product of 2 vectors.
|
437
|
-
#
|
438
|
-
# @overload cross(v)
|
439
|
-
# @overload cross(x, y)
|
440
|
-
# @overload cross(x, y, z)
|
441
|
-
#
|
442
|
-
# @param v [Vector] a vector
|
443
|
-
# @param x [Numeric] x of vector
|
444
|
-
# @param y [Numeric] y of vector
|
445
|
-
# @param z [Numeric] z of vector
|
446
|
-
#
|
447
|
-
# @return [Numeric] result of cross product
|
448
|
-
#
|
449
|
-
def cross(a, *rest)
|
450
|
-
target = self.class === rest.last ? rest.pop : nil
|
451
|
-
v = self.class.new Rays::Point::cross getInternal__, toVector__(a, *rest).getInternal__
|
452
|
-
target.set v if self.class === target
|
453
|
-
v
|
454
|
-
end
|
455
|
-
|
456
|
-
# Calculates the cross product of 2 vectors.
|
457
|
-
#
|
458
|
-
# @param v1 [Vector] a vector
|
459
|
-
# @param v2 [Vector] another vector
|
460
|
-
#
|
461
|
-
# @return [Numeric] result of cross product
|
462
|
-
#
|
463
|
-
def self.cross(v1, v2, target = nil)
|
464
|
-
v1.cross v2, target
|
465
|
-
end
|
466
|
-
|
467
|
-
# Rotate the vector.
|
468
|
-
#
|
469
|
-
# @param angle [Numeric] the angle of rotation
|
470
|
-
#
|
471
|
-
# @return [Vector] rotated this object
|
472
|
-
#
|
473
|
-
def rotate(angle)
|
474
|
-
angle = @context ? @context.toAngle__(angle) : angle * RAD2DEG__
|
475
|
-
@point.rotate! angle
|
476
|
-
self
|
477
|
-
end
|
478
|
-
|
479
|
-
# Returns the angle of rotation for this vector.
|
480
|
-
#
|
481
|
-
# @return [Numeric] the angle in radians
|
482
|
-
#
|
483
|
-
def heading()
|
484
|
-
Math.atan2 y, x
|
485
|
-
end
|
486
|
-
|
487
|
-
# Returns rotated new vector.
|
488
|
-
#
|
489
|
-
# @param angle [Numeric] the angle of rotation
|
490
|
-
# @param target [Vector] vector to store new vector
|
491
|
-
#
|
492
|
-
# @return [Vector] rotated vector
|
493
|
-
#
|
494
|
-
def self.fromAngle(angle, target = nil)
|
495
|
-
v = self.new(1, 0, 0).rotate(angle)
|
496
|
-
target.set v if target
|
497
|
-
v
|
498
|
-
end
|
499
|
-
|
500
|
-
# Returns angle between 2 vectors.
|
501
|
-
#
|
502
|
-
# @param v1 [Vector] a vector
|
503
|
-
# @param v2 [Vector] another vector
|
504
|
-
#
|
505
|
-
# @return [Numeric] angle in radians
|
506
|
-
#
|
507
|
-
def self.angleBetween(v1, v2)
|
508
|
-
x1, y1, z1 = v1.array
|
509
|
-
x2, y2, z2 = v2.array
|
510
|
-
return 0 if (x1 == 0 && y1 == 0 && z1 == 0) || (x2 == 0 && y2 == 0 && z2 == 0)
|
511
|
-
|
512
|
-
x = dot(v1, v2) / (v1.mag * v2.mag)
|
513
|
-
return Math::PI if x <= -1
|
514
|
-
return 0 if x >= 1
|
515
|
-
return Math.acos x
|
516
|
-
end
|
517
|
-
|
518
|
-
# Returns a new 2D unit vector with a random direction.
|
519
|
-
#
|
520
|
-
# @param target [Vector] a vector to store the new vector
|
521
|
-
#
|
522
|
-
# @return [Vector] a random vector
|
523
|
-
#
|
524
|
-
def self.random2D(target = nil)
|
525
|
-
v = self.fromAngle rand 0.0...(Math::PI * 2)
|
526
|
-
target.set v if target
|
527
|
-
v
|
528
|
-
end
|
529
|
-
|
530
|
-
# Returns a new 3D unit vector with a random direction.
|
531
|
-
#
|
532
|
-
# @param target [Vector] a vector to store the new vector
|
533
|
-
#
|
534
|
-
# @return [Vector] a random vector
|
535
|
-
#
|
536
|
-
def self.random3D(target = nil)
|
537
|
-
angle = rand 0.0...(Math::PI * 2)
|
538
|
-
z = rand(-1.0..1.0)
|
539
|
-
z2 = z ** 2
|
540
|
-
x = Math.sqrt(1.0 - z2) * Math.cos(angle)
|
541
|
-
y = Math.sqrt(1.0 - z2) * Math.sin(angle)
|
542
|
-
v = self.new x, y, z
|
543
|
-
target.set v if target
|
544
|
-
v
|
545
|
-
end
|
546
|
-
|
547
|
-
# @private
|
548
|
-
def inspect()
|
549
|
-
"<##{self.class.name} #{x}, #{y}, #{z}>"
|
550
|
-
end
|
551
|
-
|
552
|
-
# @private
|
553
|
-
def <=>(o)
|
554
|
-
@point <=> o.getInternal__
|
555
|
-
end
|
556
|
-
|
557
|
-
# @private
|
558
|
-
def getInternal__()
|
559
|
-
@point
|
560
|
-
end
|
561
|
-
|
562
|
-
# @private
|
563
|
-
private def toVector__(*args)
|
564
|
-
self.class === args.first ? args.first : self.class.new(*args)
|
565
|
-
end
|
566
|
-
|
567
|
-
end# Vector
|
568
|
-
|
569
|
-
|
570
|
-
# Image object.
|
571
|
-
#
|
572
|
-
class Image
|
573
|
-
|
574
|
-
# @private
|
575
|
-
def initialize(image)
|
576
|
-
@image = image
|
577
|
-
end
|
578
|
-
|
579
|
-
# Gets width of image.
|
580
|
-
#
|
581
|
-
# @return [Numeric] width of image
|
582
|
-
#
|
583
|
-
def width()
|
584
|
-
@image.width
|
585
|
-
end
|
586
|
-
|
587
|
-
# Gets height of image.
|
588
|
-
#
|
589
|
-
# @return [Numeric] height of image
|
590
|
-
#
|
591
|
-
def height()
|
592
|
-
@image.height
|
593
|
-
end
|
594
|
-
|
595
|
-
# Applies an image filter.
|
596
|
-
#
|
597
|
-
# overload filter(shader)
|
598
|
-
# overload filter(type)
|
599
|
-
# overload filter(type, param)
|
600
|
-
#
|
601
|
-
# @param shader [Shader] a fragment shader to apply
|
602
|
-
# @param type [THRESHOLD, GRAY, INVERT, BLUR] filter type
|
603
|
-
# @param param [Numeric] a parameter for each filter
|
604
|
-
#
|
605
|
-
def filter(*args)
|
606
|
-
@filter = Shader.createFilter__(*args)
|
607
|
-
end
|
608
|
-
|
609
|
-
# Resizes image.
|
610
|
-
#
|
611
|
-
# @param width [Numeric] width for resized image
|
612
|
-
# @param height [Numeric] height for resized image
|
613
|
-
#
|
614
|
-
# @return [nil] nil
|
615
|
-
#
|
616
|
-
def resize(width, height)
|
617
|
-
@image = Rays::Image.new(width, height).paint do |painter|
|
618
|
-
painter.image @image, 0, 0, width, height
|
619
|
-
end
|
620
|
-
nil
|
621
|
-
end
|
622
|
-
|
623
|
-
# Copies image.
|
624
|
-
#
|
625
|
-
# @overload copy(sx, sy, sw, sh, dx, dy, dw, dh)
|
626
|
-
# @overload copy(img, sx, sy, sw, sh, dx, dy, dw, dh)
|
627
|
-
#
|
628
|
-
# @param img [Image] image for copy source
|
629
|
-
# @param sx [Numrtic] x position of source region
|
630
|
-
# @param sy [Numrtic] y position of source region
|
631
|
-
# @param sw [Numrtic] width of source region
|
632
|
-
# @param sh [Numrtic] height of source region
|
633
|
-
# @param dx [Numrtic] x position of destination region
|
634
|
-
# @param dy [Numrtic] y position of destination region
|
635
|
-
# @param dw [Numrtic] width of destination region
|
636
|
-
# @param dh [Numrtic] height of destination region
|
637
|
-
#
|
638
|
-
# @return [nil] nil
|
639
|
-
#
|
640
|
-
def copy(img = nil, sx, sy, sw, sh, dx, dy, dw, dh)
|
641
|
-
blend img, sx, sy, sw, sh, dx, dy, dw, dh, :normal
|
642
|
-
end
|
643
|
-
|
644
|
-
# Blends image.
|
645
|
-
#
|
646
|
-
# @overload blend(sx, sy, sw, sh, dx, dy, dw, dh, mode)
|
647
|
-
# @overload blend(img, sx, sy, sw, sh, dx, dy, dw, dh, mode)
|
648
|
-
#
|
649
|
-
# @param img [Image] image for blend source
|
650
|
-
# @param sx [Numeric] x position of source region
|
651
|
-
# @param sy [Numeric] y position of source region
|
652
|
-
# @param sw [Numeric] width of source region
|
653
|
-
# @param sh [Numeric] height of source region
|
654
|
-
# @param dx [Numeric] x position of destination region
|
655
|
-
# @param dy [Numeric] y position of destination region
|
656
|
-
# @param dw [Numeric] width of destination region
|
657
|
-
# @param dh [Numeric] height of destination region
|
658
|
-
# @param mode [BLEND, ADD, SUBTRACT, LIGHTEST, DARKEST, EXCLUSION, MULTIPLY, SCREEN, REPLACE] blend mode
|
659
|
-
#
|
660
|
-
# @return [nil] nil
|
661
|
-
#
|
662
|
-
def blend(img = nil, sx, sy, sw, sh, dx, dy, dw, dh, mode)
|
663
|
-
img ||= self
|
664
|
-
@image.paint do |painter|
|
665
|
-
img.drawImage__ painter, sx, sy, sw, sh, dx, dy, dw, dh, blend_mode: mode
|
666
|
-
end
|
667
|
-
nil
|
668
|
-
end
|
669
|
-
|
670
|
-
# Saves image to file.
|
671
|
-
#
|
672
|
-
# @param filename [String] file name to save image
|
673
|
-
#
|
674
|
-
def save(filename)
|
675
|
-
@image.save filename
|
676
|
-
end
|
677
|
-
|
678
|
-
# @private
|
679
|
-
def getInternal__()
|
680
|
-
@image
|
681
|
-
end
|
682
|
-
|
683
|
-
# @private
|
684
|
-
def drawImage__(painter, *args, **states)
|
685
|
-
shader = painter.shader || @filter&.getInternal__
|
686
|
-
painter.push shader: shader, **states do |_|
|
687
|
-
painter.image getInternal__, *args
|
688
|
-
end
|
689
|
-
end
|
690
|
-
|
691
|
-
end# Image
|
692
|
-
|
693
|
-
|
694
|
-
# Font object.
|
695
|
-
#
|
696
|
-
class Font
|
697
|
-
|
698
|
-
# @private
|
699
|
-
def initialize(font)
|
700
|
-
@font = font
|
701
|
-
end
|
702
|
-
|
703
|
-
# Returns bounding box.
|
704
|
-
#
|
705
|
-
# @overload textBounds(str)
|
706
|
-
# @overload textBounds(str, x, y)
|
707
|
-
# @overload textBounds(str, x, y, fontSize)
|
708
|
-
#
|
709
|
-
# @param str [String] text to calculate bounding box
|
710
|
-
# @param x [Numeric] horizontal position of bounding box
|
711
|
-
# @param y [Numeric] vertical position of bounding box
|
712
|
-
# @param fontSize [Numeric] font size
|
713
|
-
#
|
714
|
-
# @return [TextBounds] bounding box for text
|
715
|
-
#
|
716
|
-
def textBounds(str, x = 0, y = 0, fontSize = nil)
|
717
|
-
f = fontSize ? Rays::Font.new(@font.name, fontSize) : @font
|
718
|
-
TextBounds.new x, y, x + f.width(str), y + f.height
|
719
|
-
end
|
720
|
-
|
721
|
-
end# Font
|
722
|
-
|
723
|
-
|
724
|
-
# Bounding box for text.
|
725
|
-
#
|
726
|
-
class TextBounds
|
727
|
-
|
728
|
-
# Horizontal position
|
729
|
-
#
|
730
|
-
attr_reader :x
|
731
|
-
|
732
|
-
# Vertical position
|
733
|
-
#
|
734
|
-
attr_reader :y
|
735
|
-
|
736
|
-
# Width of bounding box
|
737
|
-
#
|
738
|
-
attr_reader :w
|
739
|
-
|
740
|
-
# Height of bounding box
|
741
|
-
#
|
742
|
-
attr_reader :h
|
743
|
-
|
744
|
-
# @private
|
745
|
-
def initialize(x, y, w, h)
|
746
|
-
@x, @y, @w, @h = x, y, w, h
|
747
|
-
end
|
748
|
-
|
749
|
-
end# TextBounds
|
750
|
-
|
751
|
-
|
752
|
-
# Touch object.
|
753
|
-
#
|
754
|
-
class Touch
|
755
|
-
|
756
|
-
# Identifier of each touch
|
757
|
-
#
|
758
|
-
attr_reader :id
|
759
|
-
|
760
|
-
# Horizontal position of touch
|
761
|
-
#
|
762
|
-
attr_reader :x
|
763
|
-
|
764
|
-
# Vertical position of touch
|
765
|
-
#
|
766
|
-
attr_reader :y
|
767
|
-
|
768
|
-
# @private
|
769
|
-
def initialize(id, x, y)
|
770
|
-
@id, @x, @y = id, x, y
|
771
|
-
end
|
772
|
-
|
773
|
-
end# Touch
|
774
|
-
|
775
|
-
|
776
|
-
# Shader object.
|
777
|
-
#
|
778
|
-
class Shader
|
779
|
-
|
780
|
-
# Initialize shader object.
|
781
|
-
#
|
782
|
-
# @param vertSrc [String] vertex shader source
|
783
|
-
# @param fragSrc [String] fragment shader source
|
784
|
-
#
|
785
|
-
def initialize(vertSrc, fragSrc)
|
786
|
-
@shader = Rays::Shader.new fragSrc, vertSrc, ENV__
|
787
|
-
end
|
788
|
-
|
789
|
-
# Sets uniform variables.
|
790
|
-
#
|
791
|
-
# @overload set(name, a)
|
792
|
-
# @overload set(name, a, b)
|
793
|
-
# @overload set(name, a, b, c)
|
794
|
-
# @overload set(name, a, b, c, d)
|
795
|
-
# @overload set(name, nums)
|
796
|
-
# @overload set(name, vec)
|
797
|
-
# @overload set(name, vec, ncoords)
|
798
|
-
# @overload set(name, tex)
|
799
|
-
#
|
800
|
-
# @param name [String] uniform variable name
|
801
|
-
# @param a [Numeric] int or float value
|
802
|
-
# @param b [Numeric] int or float value
|
803
|
-
# @param c [Numeric] int or float value
|
804
|
-
# @param d [Numeric] int or float value
|
805
|
-
# @param nums [Array] int or float array
|
806
|
-
# @param vec [Vector] vector
|
807
|
-
# @param ncoords [Integer] number of coordinates, max 4
|
808
|
-
# @param tex [Image] texture image
|
809
|
-
#
|
810
|
-
def setUniform(name, *args)
|
811
|
-
arg = args.first
|
812
|
-
case
|
813
|
-
when Array === arg
|
814
|
-
@shader.uniform name, *arg
|
815
|
-
when Numeric === arg
|
816
|
-
@shader.uniform name, *args
|
817
|
-
when Vector === arg
|
818
|
-
vec, ncoords = args
|
819
|
-
@shader.uniform name, vec.getInternal__.to_a(ncoords || 3)
|
820
|
-
when arg.respond_to?(:getInternal__)
|
821
|
-
@shader.uniform name, arg.getInternal__
|
822
|
-
else
|
823
|
-
raise ArgumentError
|
824
|
-
end
|
825
|
-
end
|
826
|
-
|
827
|
-
alias set setUniform
|
828
|
-
|
829
|
-
# @private
|
830
|
-
def getInternal__()
|
831
|
-
@shader
|
832
|
-
end
|
833
|
-
|
834
|
-
# @private
|
835
|
-
ENV__ = {
|
836
|
-
attribute_position: [:vertex, :position],
|
837
|
-
attribute_texcoord: :texCoord,
|
838
|
-
attribute_color: :color,
|
839
|
-
varying_position: :vertPosition,
|
840
|
-
varying_texcoord: :vertTexCoord,
|
841
|
-
varying_color: :vertColor,
|
842
|
-
uniform_position_matrix: [:transform, :transformMatrix],
|
843
|
-
uniform_texcoord_matrix: :texMatrix,
|
844
|
-
uniform_texcoord_min: :texMin,
|
845
|
-
uniform_texcoord_max: :texMax,
|
846
|
-
uniform_texcoord_offset: :texOffset,
|
847
|
-
uniform_texture: [:texMap, :texture]
|
848
|
-
}.freeze
|
849
|
-
|
850
|
-
# @private
|
851
|
-
def self.createFilter__(*args)
|
852
|
-
case arg = args.shift
|
853
|
-
when Shader
|
854
|
-
arg
|
855
|
-
when :threshold
|
856
|
-
self.new(nil, <<~END).tap {|sh| sh.set :threshold, (args.shift || 0.5)}
|
857
|
-
uniform float threshold;
|
858
|
-
uniform sampler2D texMap;
|
859
|
-
varying vec4 vertTexCoord;
|
860
|
-
varying vec4 vertColor;
|
861
|
-
void main() {
|
862
|
-
vec4 col = texture2D(texMap, vertTexCoord.xy) * vertColor;
|
863
|
-
float gray = col.r * 0.3 + col.g * 0.59 + col.b * 0.11;
|
864
|
-
gl_FragColor = vec4(vec3(gray > threshold ? 1.0 : 0.0), 1.0);
|
865
|
-
}
|
866
|
-
END
|
867
|
-
when :gray
|
868
|
-
self.new nil, <<~END
|
869
|
-
uniform sampler2D texMap;
|
870
|
-
varying vec4 vertTexCoord;
|
871
|
-
varying vec4 vertColor;
|
872
|
-
void main() {
|
873
|
-
vec4 col = texture2D(texMap, vertTexCoord.xy);
|
874
|
-
float gray = col.r * 0.3 + col.g * 0.59 + col.b * 0.11;
|
875
|
-
gl_FragColor = vec4(vec3(gray), 1.0) * vertColor;
|
876
|
-
}
|
877
|
-
END
|
878
|
-
when :invert
|
879
|
-
self.new nil, <<~END
|
880
|
-
uniform sampler2D texMap;
|
881
|
-
varying vec4 vertTexCoord;
|
882
|
-
varying vec4 vertColor;
|
883
|
-
void main() {
|
884
|
-
vec4 col = texture2D(texMap, vertTexCoord.xy);
|
885
|
-
gl_FragColor = vec4(vec3(1.0 - col.rgb), 1.0) * vertColor;
|
886
|
-
}
|
887
|
-
END
|
888
|
-
when :blur
|
889
|
-
self.new(nil, <<~END).tap {|sh| sh.set :radius, (args.shift || 1).to_f}
|
890
|
-
#define PI 3.1415926538
|
891
|
-
uniform float radius;
|
892
|
-
uniform sampler2D texMap;
|
893
|
-
uniform vec3 texMin;
|
894
|
-
uniform vec3 texMax;
|
895
|
-
uniform vec3 texOffset;
|
896
|
-
varying vec4 vertTexCoord;
|
897
|
-
varying vec4 vertColor;
|
898
|
-
float gaussian(vec2 pos, float sigma) {
|
899
|
-
float s2 = sigma * sigma;
|
900
|
-
return 1.0 / (2.0 * PI * s2) * exp(-(dot(pos, pos) / (2.0 * s2)));
|
901
|
-
}
|
902
|
-
void main() {
|
903
|
-
float sigma = radius * 0.5;
|
904
|
-
vec3 color = vec3(0.0);
|
905
|
-
float total_weight = 0.0;
|
906
|
-
for (float y = -radius; y < radius; y += 1.0)
|
907
|
-
for (float x = -radius; x < radius; x += 1.0) {
|
908
|
-
vec2 offset = vec2(x, y);
|
909
|
-
float weight = gaussian(offset, sigma);
|
910
|
-
vec2 texcoord = vertTexCoord.xy + offset * texOffset.xy;
|
911
|
-
if (
|
912
|
-
texcoord.x < texMin.x || texMax.x < texcoord.x ||
|
913
|
-
texcoord.y < texMin.y || texMax.y < texcoord.y
|
914
|
-
) continue;
|
915
|
-
color += texture2D(texMap, texcoord).rgb * weight;
|
916
|
-
total_weight += weight;
|
917
|
-
}
|
918
|
-
gl_FragColor = vec4(color / total_weight, 1.0) * vertColor;
|
919
|
-
}
|
920
|
-
END
|
921
|
-
else
|
922
|
-
nil
|
923
|
-
end
|
924
|
-
end
|
925
|
-
|
926
|
-
end# Shader
|
927
|
-
|
928
|
-
|
929
|
-
# Camera object.
|
930
|
-
#
|
931
|
-
class Capture
|
932
|
-
|
933
|
-
# Returns a list of available camera device names
|
934
|
-
#
|
935
|
-
# @return [Array] device name list
|
936
|
-
#
|
937
|
-
def self.list()
|
938
|
-
Rays::Camera.device_names
|
939
|
-
end
|
940
|
-
|
941
|
-
# Initialize camera object.
|
942
|
-
#
|
943
|
-
# @overload Capture.new()
|
944
|
-
# @overload Capture.new(cameraName)
|
945
|
-
# @overload Capture.new(requestWidth, requestHeight)
|
946
|
-
# @overload Capture.new(requestWidth, requestHeight, cameraName)
|
947
|
-
#
|
948
|
-
# @param requestWidth [Integer] captured image width
|
949
|
-
# @param requestHeight [Integer] captured image height
|
950
|
-
# @param cameraName [String] camera device name
|
951
|
-
#
|
952
|
-
def initialize(*args)
|
953
|
-
width, height, name =
|
954
|
-
if args.empty?
|
955
|
-
[-1, -1, nil]
|
956
|
-
elsif args[0].kind_of?(String)
|
957
|
-
[-1, -1, args[0]]
|
958
|
-
elsif args[0].kind_of?(Numeric) && args[1].kind_of?(Numeric)
|
959
|
-
[args[0], args[1], args[2]]
|
960
|
-
else
|
961
|
-
raise ArgumentError
|
962
|
-
end
|
963
|
-
@camera = Rays::Camera.new width, height, device_name: name
|
964
|
-
end
|
965
|
-
|
966
|
-
# Start capturing.
|
967
|
-
#
|
968
|
-
# @return [nil] nil
|
969
|
-
#
|
970
|
-
def start()
|
971
|
-
raise "Failed to start capture" unless @camera.start
|
972
|
-
nil
|
973
|
-
end
|
974
|
-
|
975
|
-
# Stop capturing.
|
976
|
-
#
|
977
|
-
# @return [nil] nil
|
978
|
-
#
|
979
|
-
def stop()
|
980
|
-
@camera.stop
|
981
|
-
nil
|
982
|
-
end
|
983
|
-
|
984
|
-
# Returns is the next captured image available?
|
985
|
-
#
|
986
|
-
# @return [Boolean] true means object has next frame
|
987
|
-
#
|
988
|
-
def available()
|
989
|
-
@camera.active?
|
990
|
-
end
|
991
|
-
|
992
|
-
# Reads next frame image
|
993
|
-
#
|
994
|
-
def read()
|
995
|
-
@camera.image
|
996
|
-
end
|
997
|
-
|
998
|
-
# Returns the width of captured image
|
999
|
-
#
|
1000
|
-
# @return [Numeric] the width of captured image
|
1001
|
-
#
|
1002
|
-
def width()
|
1003
|
-
@camera.image&.width || 0
|
1004
|
-
end
|
1005
|
-
|
1006
|
-
# Returns the height of captured image
|
1007
|
-
#
|
1008
|
-
# @return [Numeric] the height of captured image
|
1009
|
-
#
|
1010
|
-
def height()
|
1011
|
-
@camera.image&.height || 0
|
1012
|
-
end
|
1013
|
-
|
1014
|
-
# Applies an image filter.
|
1015
|
-
#
|
1016
|
-
# overload filter(shader)
|
1017
|
-
# overload filter(type)
|
1018
|
-
# overload filter(type, param)
|
1019
|
-
#
|
1020
|
-
# @param shader [Shader] a fragment shader to apply
|
1021
|
-
# @param type [THRESHOLD, GRAY, INVERT, BLUR] filter type
|
1022
|
-
# @param param [Numeric] a parameter for each filter
|
1023
|
-
#
|
1024
|
-
def filter(*args)
|
1025
|
-
@filter = Shader.createFilter__(*args)
|
1026
|
-
end
|
1027
|
-
|
1028
|
-
# @private
|
1029
|
-
def getInternal__()
|
1030
|
-
@camera.image || (@dummyImage ||= Rays::Image.new 1, 1)
|
1031
|
-
end
|
1032
|
-
|
1033
|
-
# @private
|
1034
|
-
def drawImage__(painter, *args, **states)
|
1035
|
-
shader = painter.shader || @filter&.getInternal__
|
1036
|
-
painter.push shader: shader, **states do |_|
|
1037
|
-
painter.image getInternal__, *args
|
1038
|
-
end
|
1039
|
-
end
|
1040
|
-
|
1041
|
-
end# Capture
|
1042
|
-
|
1043
|
-
|
1044
|
-
# Drawing context
|
1045
|
-
#
|
1046
|
-
module GraphicsContext
|
1047
|
-
|
1048
|
-
# PI
|
1049
|
-
#
|
1050
|
-
PI = Math::PI
|
1051
|
-
|
1052
|
-
# PI / 2
|
1053
|
-
#
|
1054
|
-
HALF_PI = PI / 2
|
1055
|
-
|
1056
|
-
# PI / 4
|
1057
|
-
#
|
1058
|
-
QUARTER_PI = PI / 4
|
1059
|
-
|
1060
|
-
# PI * 2
|
1061
|
-
#
|
1062
|
-
TWO_PI = PI * 2
|
1063
|
-
|
1064
|
-
# PI * 2
|
1065
|
-
#
|
1066
|
-
TAU = PI * 2
|
1067
|
-
|
1068
|
-
# RGBA format for createImage().
|
1069
|
-
#
|
1070
|
-
RGBA = :rgba
|
1071
|
-
|
1072
|
-
# RGB format for createImage, or RGB mode for colorMode().
|
1073
|
-
#
|
1074
|
-
RGB = :rgb
|
1075
|
-
|
1076
|
-
# HSB mode for colorMode().
|
1077
|
-
#
|
1078
|
-
HSB = :hsb
|
1079
|
-
|
1080
|
-
# Radian mode for angleMode().
|
1081
|
-
#
|
1082
|
-
RADIANS = :radians
|
1083
|
-
|
1084
|
-
# Degree mode for angleMode().
|
1085
|
-
#
|
1086
|
-
DEGREES = :degrees
|
1087
|
-
|
1088
|
-
# Mode for rectMode(), ellipseMode() and imageMode().
|
1089
|
-
#
|
1090
|
-
CORNER = :corner
|
1091
|
-
|
1092
|
-
# Mode for rectMode(), ellipseMode() and imageMode().
|
1093
|
-
#
|
1094
|
-
CORNERS = :corners
|
1095
|
-
|
1096
|
-
# Mode for rectMode(), ellipseMode(), imageMode() and textAlign().
|
1097
|
-
#
|
1098
|
-
CENTER = :center
|
1099
|
-
|
1100
|
-
# Mode for rectMode() and ellipseMode().
|
1101
|
-
#
|
1102
|
-
RADIUS = :radius
|
1103
|
-
|
1104
|
-
# Mode for strokeCap().
|
1105
|
-
#
|
1106
|
-
PROJECT = :square
|
1107
|
-
|
1108
|
-
# Mode for strokeJoin().
|
1109
|
-
#
|
1110
|
-
MITER = :miter
|
1111
|
-
|
1112
|
-
# Mode for strokeCap() and strokeJoin().
|
1113
|
-
#
|
1114
|
-
ROUND = :round
|
1115
|
-
|
1116
|
-
# Mode for strokeCap() and strokeJoin().
|
1117
|
-
#
|
1118
|
-
SQUARE = :butt
|
1119
|
-
|
1120
|
-
# Mode for blendMode().
|
1121
|
-
#
|
1122
|
-
BLEND = :normal
|
1123
|
-
|
1124
|
-
# Mode for blendMode().
|
1125
|
-
#
|
1126
|
-
ADD = :add
|
1127
|
-
|
1128
|
-
# Mode for blendMode().
|
1129
|
-
#
|
1130
|
-
SUBTRACT = :subtract
|
1131
|
-
|
1132
|
-
# Mode for blendMode().
|
1133
|
-
#
|
1134
|
-
LIGHTEST = :lightest
|
1135
|
-
|
1136
|
-
# Mode for blendMode().
|
1137
|
-
#
|
1138
|
-
DARKEST = :darkest
|
1139
|
-
|
1140
|
-
# Mode for blendMode().
|
1141
|
-
#
|
1142
|
-
EXCLUSION = :exclusion
|
1143
|
-
|
1144
|
-
# Mode for blendMode().
|
1145
|
-
#
|
1146
|
-
MULTIPLY = :multiply
|
1147
|
-
|
1148
|
-
# Mode for blendMode().
|
1149
|
-
#
|
1150
|
-
SCREEN = :screen
|
1151
|
-
|
1152
|
-
# Mode for blendMode().
|
1153
|
-
#
|
1154
|
-
REPLACE = :replace
|
1155
|
-
|
1156
|
-
# Key code or Mode for textAlign().
|
1157
|
-
LEFT = :left
|
1158
|
-
|
1159
|
-
# Key code or Mode for textAlign().
|
1160
|
-
RIGHT = :right
|
1161
|
-
|
1162
|
-
# Mode for textAlign().
|
1163
|
-
TOP = :top
|
1164
|
-
|
1165
|
-
# Mode for textAlign().
|
1166
|
-
BOTTOM = :bottom
|
1167
|
-
|
1168
|
-
# Mode for textAlign().
|
1169
|
-
BASELINE = :baseline
|
1170
|
-
|
1171
|
-
# Filter type for filter()
|
1172
|
-
THRESHOLD = :threshold
|
1173
|
-
|
1174
|
-
# Filter type for filter()
|
1175
|
-
GRAY = :gray
|
1176
|
-
|
1177
|
-
# Filter type for filter()
|
1178
|
-
INVERT = :invert
|
1179
|
-
|
1180
|
-
# Filter type for filter()
|
1181
|
-
BLUR = :blur
|
1182
|
-
|
1183
|
-
# Key codes.
|
1184
|
-
ENTER = :enter
|
1185
|
-
SPACE = :space
|
1186
|
-
TAB = :tab
|
1187
|
-
DELETE = :delete
|
1188
|
-
BACKSPACE = :backspace
|
1189
|
-
ESC = :escape
|
1190
|
-
HOME = :home
|
1191
|
-
#END = :end
|
1192
|
-
PAGEUP = :pageup
|
1193
|
-
PAGEDOWN = :pagedown
|
1194
|
-
CLEAR = :clear
|
1195
|
-
SHIFT = :shift
|
1196
|
-
CONTROL = :control
|
1197
|
-
ALT = :alt
|
1198
|
-
WIN = :win
|
1199
|
-
COMMAND = :command
|
1200
|
-
OPTION = :option
|
1201
|
-
FUNCTION = :function
|
1202
|
-
CAPSLOCK = :capslock
|
1203
|
-
SECTION = :section
|
1204
|
-
HELP = :help
|
1205
|
-
F1 = :f1
|
1206
|
-
F2 = :f2
|
1207
|
-
F3 = :f3
|
1208
|
-
F4 = :f4
|
1209
|
-
F5 = :f5
|
1210
|
-
F6 = :f6
|
1211
|
-
F7 = :f7
|
1212
|
-
F8 = :f8
|
1213
|
-
F9 = :f9
|
1214
|
-
F10 = :f10
|
1215
|
-
F11 = :f11
|
1216
|
-
F12 = :f12
|
1217
|
-
F13 = :f13
|
1218
|
-
F14 = :f14
|
1219
|
-
F15 = :f15
|
1220
|
-
F16 = :f16
|
1221
|
-
F17 = :f17
|
1222
|
-
F18 = :f18
|
1223
|
-
F19 = :f19
|
1224
|
-
F20 = :f20
|
1225
|
-
F21 = :f21
|
1226
|
-
F22 = :f22
|
1227
|
-
F23 = :f23
|
1228
|
-
F24 = :f24
|
1229
|
-
UP = :up
|
1230
|
-
DOWN = :down
|
1231
|
-
|
1232
|
-
# @private
|
1233
|
-
def init__(image, painter)
|
1234
|
-
@drawing__ = false
|
1235
|
-
@hsbColor__ = false
|
1236
|
-
@colorMaxes__ = [1.0] * 4
|
1237
|
-
@angleScale__ = 1.0
|
1238
|
-
@rectMode__ = nil
|
1239
|
-
@ellipseMode__ = nil
|
1240
|
-
@imageMode__ = nil
|
1241
|
-
@textAlignH__ = nil
|
1242
|
-
@textAlignV__ = nil
|
1243
|
-
@tint__ = nil
|
1244
|
-
@filter__ = nil
|
1245
|
-
@matrixStack__ = []
|
1246
|
-
@styleStack__ = []
|
1247
|
-
@fontCache__ = {}
|
1248
|
-
|
1249
|
-
updateCanvas__ image, painter
|
1250
|
-
|
1251
|
-
colorMode RGB, 255
|
1252
|
-
angleMode RADIANS
|
1253
|
-
rectMode CORNER
|
1254
|
-
ellipseMode CENTER
|
1255
|
-
imageMode CORNER
|
1256
|
-
blendMode BLEND
|
1257
|
-
strokeCap ROUND
|
1258
|
-
strokeJoin MITER
|
1259
|
-
textAlign LEFT
|
1260
|
-
|
1261
|
-
fill 255
|
1262
|
-
stroke 0
|
1263
|
-
strokeWeight 1
|
1264
|
-
noTint
|
1265
|
-
end
|
1266
|
-
|
1267
|
-
# @private
|
1268
|
-
def updateCanvas__(image, painter)
|
1269
|
-
@image__, @painter__ = image, painter
|
1270
|
-
end
|
1271
|
-
|
1272
|
-
# @private
|
1273
|
-
def beginDraw__()
|
1274
|
-
raise "call beginDraw() before drawing" if @drawing__
|
1275
|
-
@matrixStack__.clear
|
1276
|
-
@styleStack__.clear
|
1277
|
-
@drawing__ = true
|
1278
|
-
end
|
1279
|
-
|
1280
|
-
# @private
|
1281
|
-
def endDraw__()
|
1282
|
-
raise unless @drawing__
|
1283
|
-
@drawing__ = false
|
1284
|
-
end
|
1285
|
-
|
1286
|
-
def width()
|
1287
|
-
@image__.width
|
1288
|
-
end
|
1289
|
-
|
1290
|
-
def height()
|
1291
|
-
@image__.height
|
1292
|
-
end
|
1293
|
-
|
1294
|
-
# Sets color mode and max color values.
|
1295
|
-
#
|
1296
|
-
# @overload colorMode(mode)
|
1297
|
-
# @overload colorMode(mode, max)
|
1298
|
-
# @overload colorMode(mode, max1, max2, max3)
|
1299
|
-
# @overload colorMode(mode, max1, max2, max3, maxA)
|
1300
|
-
#
|
1301
|
-
# @param mode [RGB, HSB] RGB or HSB
|
1302
|
-
# @param max [Numeric] max values for all color values
|
1303
|
-
# @param max1 [Numeric] max value for red or hue
|
1304
|
-
# @param max2 [Numeric] max value for green or saturation
|
1305
|
-
# @param max3 [Numeric] max value for blue or brightness
|
1306
|
-
# @param maxA [Numeric] max value for alpha
|
1307
|
-
#
|
1308
|
-
# @return [nil] nil
|
1309
|
-
#
|
1310
|
-
def colorMode(mode, *maxes)
|
1311
|
-
mode = mode.downcase.to_sym
|
1312
|
-
raise ArgumentError, "invalid color mode: #{mode}" unless [RGB, HSB].include?(mode)
|
1313
|
-
raise ArgumentError unless [0, 1, 3, 4].include?(maxes.size)
|
1314
|
-
|
1315
|
-
@hsbColor__ = mode == HSB
|
1316
|
-
case maxes.size
|
1317
|
-
when 1 then @colorMaxes__ = [maxes.first.to_f] * 4
|
1318
|
-
when 3, 4 then @colorMaxes__[0...maxes.size] = maxes.map &:to_f
|
1319
|
-
end
|
1320
|
-
nil
|
1321
|
-
end
|
1322
|
-
|
1323
|
-
# @private
|
1324
|
-
private def toRGBA__(*args)
|
1325
|
-
a, b, c, d = args
|
1326
|
-
return parseColor__(a, b || alphaMax__) if a.kind_of?(String)
|
1327
|
-
|
1328
|
-
rgba = case args.size
|
1329
|
-
when 1, 2 then [a, a, a, b || alphaMax__]
|
1330
|
-
when 3, 4 then [a, b, c, d || alphaMax__]
|
1331
|
-
else raise ArgumentError
|
1332
|
-
end
|
1333
|
-
rgba = rgba.map.with_index {|value, i| value / @colorMaxes__[i]}
|
1334
|
-
color = @hsbColor__ ? Rays::Color.hsv(*rgba) : Rays::Color.new(*rgba)
|
1335
|
-
color.to_a
|
1336
|
-
end
|
1337
|
-
|
1338
|
-
# @private
|
1339
|
-
private def parseColor__(str, alpha)
|
1340
|
-
result = str.match(/^\s*##{'([0-9a-f]{2})' * 3}\s*$/i)
|
1341
|
-
raise ArgumentError, "invalid color code: '#{str}'" unless result
|
1342
|
-
|
1343
|
-
rgb = result[1..3].map.with_index {|hex, i| hex.to_i(16) / 255.0}
|
1344
|
-
return *rgb, (alpha / alphaMax__)
|
1345
|
-
end
|
1346
|
-
|
1347
|
-
# @private
|
1348
|
-
private def alphaMax__()
|
1349
|
-
@colorMaxes__[3]
|
1350
|
-
end
|
1351
|
-
|
1352
|
-
# Sets angle mode.
|
1353
|
-
#
|
1354
|
-
# @param mode [RADIANS, DEGREES] RADIANS or DEGREES
|
1355
|
-
#
|
1356
|
-
# @return [nil] nil
|
1357
|
-
#
|
1358
|
-
def angleMode(mode)
|
1359
|
-
@angleScale__ = case mode.downcase.to_sym
|
1360
|
-
when RADIANS then RAD2DEG__
|
1361
|
-
when DEGREES then 1.0
|
1362
|
-
else raise ArgumentError, "invalid angle mode: #{mode}"
|
1363
|
-
end
|
1364
|
-
nil
|
1365
|
-
end
|
1366
|
-
|
1367
|
-
# @private
|
1368
|
-
def toAngle__(angle)
|
1369
|
-
angle * @angleScale__
|
1370
|
-
end
|
1371
|
-
|
1372
|
-
# Sets rect mode. Default is CORNER.
|
1373
|
-
#
|
1374
|
-
# CORNER -> rect(left, top, width, height)
|
1375
|
-
# CORNERS -> rect(left, top, right, bottom)
|
1376
|
-
# CENTER -> rect(center_x, center_y, width, height)
|
1377
|
-
# RADIUS -> rect(center_x, center_y, radius_h, radius_v)
|
1378
|
-
#
|
1379
|
-
# @param mode [CORNER, CORNERS, CENTER, RADIUS]
|
1380
|
-
#
|
1381
|
-
# @return [nil] nil
|
1382
|
-
#
|
1383
|
-
def rectMode(mode)
|
1384
|
-
@rectMode__ = mode
|
1385
|
-
end
|
1386
|
-
|
1387
|
-
# Sets ellipse mode. Default is CENTER.
|
1388
|
-
#
|
1389
|
-
# CORNER -> ellipse(left, top, width, height)
|
1390
|
-
# CORNERS -> ellipse(left, top, right, bottom)
|
1391
|
-
# CENTER -> ellipse(center_x, center_y, width, height)
|
1392
|
-
# RADIUS -> ellipse(center_x, center_y, radius_h, radius_v)
|
1393
|
-
#
|
1394
|
-
# @param mode [CORNER, CORNERS, CENTER, RADIUS]
|
1395
|
-
#
|
1396
|
-
# @return [nil] nil
|
1397
|
-
#
|
1398
|
-
def ellipseMode(mode)
|
1399
|
-
@ellipseMode__ = mode
|
1400
|
-
end
|
1401
|
-
|
1402
|
-
# Sets image mode. Default is CORNER.
|
1403
|
-
#
|
1404
|
-
# CORNER -> image(img, left, top, width, height)
|
1405
|
-
# CORNERS -> image(img, left, top, right, bottom)
|
1406
|
-
# CENTER -> image(img, center_x, center_y, width, height)
|
1407
|
-
#
|
1408
|
-
# @param mode [CORNER, CORNERS, CENTER]
|
1409
|
-
#
|
1410
|
-
# @return [nil] nil
|
1411
|
-
#
|
1412
|
-
def imageMode(mode)
|
1413
|
-
@imageMode__ = mode
|
1414
|
-
end
|
1415
|
-
|
1416
|
-
# @private
|
1417
|
-
private def toXYWH__(mode, a, b, c, d)
|
1418
|
-
case mode
|
1419
|
-
when CORNER then [a, b, c, d]
|
1420
|
-
when CORNERS then [a, b, c - a, d - b]
|
1421
|
-
when CENTER then [a - c / 2.0, b - d / 2.0, c, d]
|
1422
|
-
when RADIUS then [a - c, b - d, c * 2, d * 2]
|
1423
|
-
else raise ArgumentError # ToDo: refine error message
|
1424
|
-
end
|
1425
|
-
end
|
1426
|
-
|
1427
|
-
# Sets blend mode. Default is BLEND.
|
1428
|
-
#
|
1429
|
-
# @param mode [BLEND, ADD, SUBTRACT, LIGHTEST, DARKEST, EXCLUSION, MULTIPLY, SCREEN, REPLACE]
|
1430
|
-
#
|
1431
|
-
# @return [nil] nil
|
1432
|
-
#
|
1433
|
-
def blendMode(mode)
|
1434
|
-
@painter__.blend_mode = mode
|
1435
|
-
nil
|
1436
|
-
end
|
1437
|
-
|
1438
|
-
# Sets fill color.
|
1439
|
-
#
|
1440
|
-
# @overload fill(rgb)
|
1441
|
-
# @overload fill(rgb, alpha)
|
1442
|
-
# @overload fill(gray)
|
1443
|
-
# @overload fill(gray, alpha)
|
1444
|
-
# @overload fill(r, g, b)
|
1445
|
-
# @overload fill(r, g, b, alpha)
|
1446
|
-
#
|
1447
|
-
# @param rgb [String] color code like '#00AAFF'
|
1448
|
-
# @param gray [Integer] gray value (0..255)
|
1449
|
-
# @param r [Integer] red value (0..255)
|
1450
|
-
# @param g [Integer] green value (0..255)
|
1451
|
-
# @param b [Integer] blue value (0..255)
|
1452
|
-
# @param alpha [Integer] alpha value (0..255)
|
1453
|
-
#
|
1454
|
-
# @return [nil] nil
|
1455
|
-
#
|
1456
|
-
def fill(*args)
|
1457
|
-
@painter__.fill(*toRGBA__(*args))
|
1458
|
-
nil
|
1459
|
-
end
|
1460
|
-
|
1461
|
-
# Disables filling.
|
1462
|
-
#
|
1463
|
-
# @return [nil] nil
|
1464
|
-
#
|
1465
|
-
def noFill()
|
1466
|
-
@painter__.fill nil
|
1467
|
-
nil
|
1468
|
-
end
|
1469
|
-
|
1470
|
-
# Sets stroke color.
|
1471
|
-
#
|
1472
|
-
# @overload stroke(rgb)
|
1473
|
-
# @overload stroke(rgb, alpha)
|
1474
|
-
# @overload stroke(gray)
|
1475
|
-
# @overload stroke(gray, alpha)
|
1476
|
-
# @overload stroke(r, g, b)
|
1477
|
-
# @overload stroke(r, g, b, alpha)
|
1478
|
-
#
|
1479
|
-
# @param rgb [String] color code like '#00AAFF'
|
1480
|
-
# @param gray [Integer] gray value (0..255)
|
1481
|
-
# @param r [Integer] red value (0..255)
|
1482
|
-
# @param g [Integer] green value (0..255)
|
1483
|
-
# @param b [Integer] blue value (0..255)
|
1484
|
-
# @param alpha [Integer] alpha value (0..255)
|
1485
|
-
#
|
1486
|
-
# @return [nil] nil
|
1487
|
-
#
|
1488
|
-
def stroke(*args)
|
1489
|
-
@painter__.stroke(*toRGBA__(*args))
|
1490
|
-
nil
|
1491
|
-
end
|
1492
|
-
|
1493
|
-
# Disables drawing stroke.
|
1494
|
-
#
|
1495
|
-
# @return [nil] nil
|
1496
|
-
#
|
1497
|
-
def noStroke()
|
1498
|
-
@painter__.stroke nil
|
1499
|
-
nil
|
1500
|
-
end
|
1501
|
-
|
1502
|
-
# Sets stroke weight.
|
1503
|
-
#
|
1504
|
-
# @param weight [Numeric] width of stroke
|
1505
|
-
#
|
1506
|
-
# @return [nil] nil
|
1507
|
-
#
|
1508
|
-
def strokeWeight(weight)
|
1509
|
-
@painter__.stroke_width weight
|
1510
|
-
nil
|
1511
|
-
end
|
1512
|
-
|
1513
|
-
# Sets stroke cap mode.
|
1514
|
-
#
|
1515
|
-
# @param cap [BUTT, ROUND, SQUARE]
|
1516
|
-
#
|
1517
|
-
# @return [nil] nil
|
1518
|
-
#
|
1519
|
-
def strokeCap(cap)
|
1520
|
-
@painter__.stroke_cap cap
|
1521
|
-
nil
|
1522
|
-
end
|
1523
|
-
|
1524
|
-
# Sets stroke join mode.
|
1525
|
-
#
|
1526
|
-
# @param join [MITER, ROUND, SQUARE]
|
1527
|
-
#
|
1528
|
-
# @return [nil] nil
|
1529
|
-
#
|
1530
|
-
def strokeJoin(join)
|
1531
|
-
@painter__.stroke_join join
|
1532
|
-
nil
|
1533
|
-
end
|
1534
|
-
|
1535
|
-
# Sets fill color for drawing images.
|
1536
|
-
#
|
1537
|
-
# @overload tint(rgb)
|
1538
|
-
# @overload tint(rgb, alpha)
|
1539
|
-
# @overload tint(gray)
|
1540
|
-
# @overload tint(gray, alpha)
|
1541
|
-
# @overload tint(r, g, b)
|
1542
|
-
# @overload tint(r, g, b, alpha)
|
1543
|
-
#
|
1544
|
-
# @param rgb [String] color code like '#00AAFF'
|
1545
|
-
# @param gray [Integer] gray value (0..255)
|
1546
|
-
# @param r [Integer] red value (0..255)
|
1547
|
-
# @param g [Integer] green value (0..255)
|
1548
|
-
# @param b [Integer] blue value (0..255)
|
1549
|
-
# @param alpha [Integer] alpha value (0..255)
|
1550
|
-
#
|
1551
|
-
# @return [nil] nil
|
1552
|
-
#
|
1553
|
-
def tint(*args)
|
1554
|
-
@tint__ = args
|
1555
|
-
nil
|
1556
|
-
end
|
1557
|
-
|
1558
|
-
# Resets tint color.
|
1559
|
-
#
|
1560
|
-
# @return [nil] nil
|
1561
|
-
#
|
1562
|
-
def noTint()
|
1563
|
-
@tint__ = nil
|
1564
|
-
end
|
1565
|
-
|
1566
|
-
# Limits the drawable rectangle.
|
1567
|
-
#
|
1568
|
-
# The parameters a, b, c, and d are determined by rectMode().
|
1569
|
-
#
|
1570
|
-
# @param a [Numeric] horizontal position of the drawable area, by default
|
1571
|
-
# @param b [Numeric] vertical position of the drawable area, by default
|
1572
|
-
# @param c [Numeric] width of the drawable area, by default
|
1573
|
-
# @param d [Numeric] height of the drawable area, by default
|
1574
|
-
#
|
1575
|
-
# @return [nil] nil
|
1576
|
-
#
|
1577
|
-
def clip(a, b, c, d)
|
1578
|
-
x, y, w, h = toXYWH__ @imageMode__, a, b, c, d
|
1579
|
-
@painter__.clip x, y, w, h
|
1580
|
-
nil
|
1581
|
-
end
|
1582
|
-
|
1583
|
-
# Disables clipping.
|
1584
|
-
#
|
1585
|
-
# @return [nil] nil
|
1586
|
-
#
|
1587
|
-
def noClip()
|
1588
|
-
@painter__.no_clip
|
1589
|
-
nil
|
1590
|
-
end
|
1591
|
-
|
1592
|
-
# Sets font.
|
1593
|
-
#
|
1594
|
-
# @overload textFont(font)
|
1595
|
-
# @overload textFont(name)
|
1596
|
-
# @overload textFont(font, size)
|
1597
|
-
# @overload textFont(name, size)
|
1598
|
-
#
|
1599
|
-
# @param font [Font] font
|
1600
|
-
# @param name [String] font name
|
1601
|
-
# @param size [Numeric] font size (max 256)
|
1602
|
-
#
|
1603
|
-
# @return [Font] current font
|
1604
|
-
#
|
1605
|
-
def textFont(font = nil, size = nil)
|
1606
|
-
setFont__ font, size if font || size
|
1607
|
-
Font.new @painter__.font
|
1608
|
-
end
|
1609
|
-
|
1610
|
-
# Sets text size.
|
1611
|
-
#
|
1612
|
-
# @param size [Numeric] font size (max 256)
|
1613
|
-
#
|
1614
|
-
# @return [nil] nil
|
1615
|
-
#
|
1616
|
-
def textSize(size)
|
1617
|
-
setFont__ nil, size
|
1618
|
-
nil
|
1619
|
-
end
|
1620
|
-
|
1621
|
-
def textWidth(str)
|
1622
|
-
@painter__.font.width str
|
1623
|
-
end
|
1624
|
-
|
1625
|
-
def textAscent()
|
1626
|
-
@painter__.font.ascent
|
1627
|
-
end
|
1628
|
-
|
1629
|
-
def textDescent()
|
1630
|
-
@painter__.font.descent
|
1631
|
-
end
|
1632
|
-
|
1633
|
-
def textAlign(horizontal, vertical = BASELINE)
|
1634
|
-
@textAlignH__ = horizontal
|
1635
|
-
@textAlignV__ = vertical
|
1636
|
-
end
|
1637
|
-
|
1638
|
-
# @private
|
1639
|
-
def setFont__(fontOrName, size)
|
1640
|
-
name = case fontOrName
|
1641
|
-
when Font then fontOrName.name
|
1642
|
-
else fontOrName || @painter__.font.name
|
1643
|
-
end
|
1644
|
-
size ||= @painter__.font.size
|
1645
|
-
size = 256 if size > 256
|
1646
|
-
font = @fontCache__[[name, size]] ||= Rays::Font.new name, size
|
1647
|
-
@painter__.font = font
|
1648
|
-
end
|
1649
|
-
|
1650
|
-
# Sets shader.
|
1651
|
-
#
|
1652
|
-
# @param shader [Shader] a shader to apply
|
1653
|
-
#
|
1654
|
-
# @return [nil] nil
|
1655
|
-
#
|
1656
|
-
def shader(shader)
|
1657
|
-
@painter__.shader shader&.getInternal__
|
1658
|
-
nil
|
1659
|
-
end
|
1660
|
-
|
1661
|
-
# Resets shader.
|
1662
|
-
#
|
1663
|
-
# @return [nil] nil
|
1664
|
-
#
|
1665
|
-
def resetShader()
|
1666
|
-
@painter__.no_shader
|
1667
|
-
nil
|
1668
|
-
end
|
1669
|
-
|
1670
|
-
# Applies an image filter to screen.
|
1671
|
-
#
|
1672
|
-
# overload filter(shader)
|
1673
|
-
# overload filter(type)
|
1674
|
-
# overload filter(type, param)
|
1675
|
-
#
|
1676
|
-
# @param shader [Shader] a shader to apply
|
1677
|
-
# @param type [THRESHOLD, GRAY, INVERT, BLUR] filter type
|
1678
|
-
# @param param [Numeric] a parameter for each filter
|
1679
|
-
#
|
1680
|
-
def filter(*args)
|
1681
|
-
@filter__ = Shader.createFilter__(*args)
|
1682
|
-
end
|
1683
|
-
|
1684
|
-
# Clears screen.
|
1685
|
-
#
|
1686
|
-
# @overload background(str)
|
1687
|
-
# @overload background(str, alpha)
|
1688
|
-
# @overload background(gray)
|
1689
|
-
# @overload background(gray, alpha)
|
1690
|
-
# @overload background(r, g, b)
|
1691
|
-
# @overload background(r, g, b, alpha)
|
1692
|
-
#
|
1693
|
-
# @param str [String] color code like '#00AAFF'
|
1694
|
-
# @param gray [Integer] gray value (0..255)
|
1695
|
-
# @param r [Integer] red value (0..255)
|
1696
|
-
# @param g [Integer] green value (0..255)
|
1697
|
-
# @param b [Integer] blue value (0..255)
|
1698
|
-
# @param alpha [Integer] alpha value (0..255)
|
1699
|
-
#
|
1700
|
-
# @return [nil] nil
|
1701
|
-
#
|
1702
|
-
def background(*args)
|
1703
|
-
assertDrawing__
|
1704
|
-
rgba = toRGBA__(*args)
|
1705
|
-
if rgba[3] == 1
|
1706
|
-
@painter__.background(*rgba)
|
1707
|
-
else
|
1708
|
-
@painter__.push fill: rgba, stroke: :none do |_|
|
1709
|
-
@painter__.rect 0, 0, width, height
|
1710
|
-
end
|
1711
|
-
end
|
1712
|
-
nil
|
1713
|
-
end
|
1714
|
-
|
1715
|
-
# Draws a point.
|
1716
|
-
#
|
1717
|
-
# @param x [Numeric] horizontal position
|
1718
|
-
# @param y [Numeric] vertical position
|
1719
|
-
#
|
1720
|
-
# @return [nil] nil
|
1721
|
-
#
|
1722
|
-
def point(x, y)
|
1723
|
-
assertDrawing__
|
1724
|
-
@painter__.line x, y, x, y
|
1725
|
-
nil
|
1726
|
-
end
|
1727
|
-
|
1728
|
-
# Draws a line.
|
1729
|
-
#
|
1730
|
-
# @param x1 [Numeric] horizontal position of first point
|
1731
|
-
# @param y1 [Numeric] vertical position of first point
|
1732
|
-
# @param x2 [Numeric] horizontal position of second point
|
1733
|
-
# @param y2 [Numeric] vertical position of second point
|
1734
|
-
#
|
1735
|
-
# @return [nil] nil
|
1736
|
-
#
|
1737
|
-
def line(x1, y1, x2, y2)
|
1738
|
-
assertDrawing__
|
1739
|
-
@painter__.line x1, y1, x2, y2
|
1740
|
-
nil
|
1741
|
-
end
|
1742
|
-
|
1743
|
-
# Draws a rectangle.
|
1744
|
-
#
|
1745
|
-
# The parameters a, b, c, and d are determined by rectMode().
|
1746
|
-
#
|
1747
|
-
# @overload rect(a, b, c, d)
|
1748
|
-
# @overload rect(a, b, c, d, r)
|
1749
|
-
# @overload rect(a, b, c, d, tl, tr, br, bl)
|
1750
|
-
#
|
1751
|
-
# @param a [Numeric] horizontal position of the shape, by default
|
1752
|
-
# @param b [Numeric] vertical position of the shape, by default
|
1753
|
-
# @param c [Numeric] width of the shape, by default
|
1754
|
-
# @param d [Numeric] height of the shape, by default
|
1755
|
-
# @param r [Numeric] radius for all corners
|
1756
|
-
# @param tl [Numeric] radius for top-left corner
|
1757
|
-
# @param tr [Numeric] radius for top-right corner
|
1758
|
-
# @param br [Numeric] radius for bottom-right corner
|
1759
|
-
# @param bl [Numeric] radius for bottom-left corner
|
1760
|
-
#
|
1761
|
-
# @return [nil] nil
|
1762
|
-
#
|
1763
|
-
def rect(a, b, c, d, *args)
|
1764
|
-
assertDrawing__
|
1765
|
-
x, y, w, h = toXYWH__ @rectMode__, a, b, c, d
|
1766
|
-
case args.size
|
1767
|
-
when 0 then @painter__.rect x, y, w, h
|
1768
|
-
when 1 then @painter__.rect x, y, w, h, round: args[0]
|
1769
|
-
when 4 then @painter__.rect x, y, w, h, lt: args[0], rt: args[1], rb: args[2], lb: args[3]
|
1770
|
-
else raise ArgumentError # ToDo: refine error message
|
1771
|
-
end
|
1772
|
-
nil
|
1773
|
-
end
|
1774
|
-
|
1775
|
-
# Draws an ellipse.
|
1776
|
-
#
|
1777
|
-
# The parameters a, b, c, and d are determined by ellipseMode().
|
1778
|
-
#
|
1779
|
-
# @param a [Numeric] horizontal position of the shape, by default
|
1780
|
-
# @param b [Numeric] vertical position of the shape, by default
|
1781
|
-
# @param c [Numeric] width of the shape, by default
|
1782
|
-
# @param d [Numeric] height of the shape, by default
|
1783
|
-
#
|
1784
|
-
# @return [nil] nil
|
1785
|
-
#
|
1786
|
-
def ellipse(a, b, c, d)
|
1787
|
-
assertDrawing__
|
1788
|
-
x, y, w, h = toXYWH__ @ellipseMode__, a, b, c, d
|
1789
|
-
@painter__.ellipse x, y, w, h
|
1790
|
-
nil
|
1791
|
-
end
|
1792
|
-
|
1793
|
-
# Draws a circle.
|
1794
|
-
#
|
1795
|
-
# @param x [Numeric] horizontal position of the shape
|
1796
|
-
# @param y [Numeric] vertical position of the shape
|
1797
|
-
# @param extent [Numeric] width and height of the shape
|
1798
|
-
#
|
1799
|
-
# @return [nil] nil
|
1800
|
-
#
|
1801
|
-
def circle(x, y, extent)
|
1802
|
-
ellipse x, y, extent, extent
|
1803
|
-
end
|
1804
|
-
|
1805
|
-
# Draws an arc.
|
1806
|
-
#
|
1807
|
-
# The parameters a, b, c, and d are determined by ellipseMode().
|
1808
|
-
#
|
1809
|
-
# @param a [Numeric] horizontal position of the shape, by default
|
1810
|
-
# @param b [Numeric] vertical position of the shape, by default
|
1811
|
-
# @param c [Numeric] width of the shape, by default
|
1812
|
-
# @param d [Numeric] height of the shape, by default
|
1813
|
-
# @param start [Numeric] angle to start the arc
|
1814
|
-
# @param stop [Numeric] angle to stop the arc
|
1815
|
-
#
|
1816
|
-
# @return [nil] nil
|
1817
|
-
#
|
1818
|
-
def arc(a, b, c, d, start, stop)
|
1819
|
-
assertDrawing__
|
1820
|
-
x, y, w, h = toXYWH__ @ellipseMode__, a, b, c, d
|
1821
|
-
start = toAngle__(-start)
|
1822
|
-
stop = toAngle__(-stop)
|
1823
|
-
@painter__.ellipse x, y, w, h, from: start, to: stop
|
1824
|
-
nil
|
1825
|
-
end
|
1826
|
-
|
1827
|
-
# Draws a square.
|
1828
|
-
#
|
1829
|
-
# @param x [Numeric] horizontal position of the shape
|
1830
|
-
# @param y [Numeric] vertical position of the shape
|
1831
|
-
# @param extent [Numeric] width and height of the shape
|
1832
|
-
#
|
1833
|
-
# @return [nil] nil
|
1834
|
-
#
|
1835
|
-
def square(x, y, extent)
|
1836
|
-
rect x, y, extent, extent
|
1837
|
-
end
|
1838
|
-
|
1839
|
-
# Draws a triangle.
|
1840
|
-
#
|
1841
|
-
# @param x1 [Numeric] horizontal position of first point
|
1842
|
-
# @param y1 [Numeric] vertical position of first point
|
1843
|
-
# @param x2 [Numeric] horizontal position of second point
|
1844
|
-
# @param y2 [Numeric] vertical position of second point
|
1845
|
-
# @param x3 [Numeric] horizontal position of third point
|
1846
|
-
# @param y3 [Numeric] vertical position of third point
|
1847
|
-
#
|
1848
|
-
# @return [nil] nil
|
1849
|
-
#
|
1850
|
-
def triangle(x1, y1, x2, y2, x3, y3)
|
1851
|
-
assertDrawing__
|
1852
|
-
@painter__.line x1, y1, x2, y2, x3, y3, loop: true
|
1853
|
-
nil
|
1854
|
-
end
|
1855
|
-
|
1856
|
-
# Draws a quad.
|
1857
|
-
#
|
1858
|
-
# @param x1 [Numeric] horizontal position of first point
|
1859
|
-
# @param y1 [Numeric] vertical position of first point
|
1860
|
-
# @param x2 [Numeric] horizontal position of second point
|
1861
|
-
# @param y2 [Numeric] vertical position of second point
|
1862
|
-
# @param x3 [Numeric] horizontal position of third point
|
1863
|
-
# @param y3 [Numeric] vertical position of third point
|
1864
|
-
# @param x4 [Numeric] horizontal position of fourth point
|
1865
|
-
# @param y4 [Numeric] vertical position of fourth point
|
1866
|
-
#
|
1867
|
-
# @return [nil] nil
|
1868
|
-
#
|
1869
|
-
def quad(x1, y1, x2, y2, x3, y3, x4, y4)
|
1870
|
-
assertDrawing__
|
1871
|
-
@painter__.line x1, y1, x2, y2, x3, y3, x4, y4, loop: true
|
1872
|
-
nil
|
1873
|
-
end
|
1874
|
-
|
1875
|
-
# Draws a Catmull-Rom spline curve.
|
1876
|
-
#
|
1877
|
-
# @param cx1 [Numeric] horizontal position of beginning control point
|
1878
|
-
# @param cy1 [Numeric] vertical position of beginning control point
|
1879
|
-
# @param x1 [Numeric] horizontal position of first point
|
1880
|
-
# @param y1 [Numeric] vertical position of first point
|
1881
|
-
# @param x2 [Numeric] horizontal position of second point
|
1882
|
-
# @param y2 [Numeric] vertical position of second point
|
1883
|
-
# @param cx2 [Numeric] horizontal position of ending control point
|
1884
|
-
# @param cy2 [Numeric] vertical position of ending control point
|
1885
|
-
#
|
1886
|
-
# @return [nil] nil
|
1887
|
-
#
|
1888
|
-
def curve(cx1, cy1, x1, y1, x2, y2, cx2, cy2)
|
1889
|
-
assertDrawing__
|
1890
|
-
@painter__.curve cx1, cy1, x1, y1, x2, y2, cx2, cy2
|
1891
|
-
nil
|
1892
|
-
end
|
1893
|
-
|
1894
|
-
# Draws a Bezier spline curve.
|
1895
|
-
#
|
1896
|
-
# @param x1 [Numeric] horizontal position of first point
|
1897
|
-
# @param y1 [Numeric] vertical position of first point
|
1898
|
-
# @param cx1 [Numeric] horizontal position of first control point
|
1899
|
-
# @param cy1 [Numeric] vertical position of first control point
|
1900
|
-
# @param cx2 [Numeric] horizontal position of second control point
|
1901
|
-
# @param cy2 [Numeric] vertical position of second control point
|
1902
|
-
# @param x2 [Numeric] horizontal position of second point
|
1903
|
-
# @param y2 [Numeric] vertical position of second point
|
1904
|
-
#
|
1905
|
-
# @return [nil] nil
|
1906
|
-
#
|
1907
|
-
def bezier(x1, y1, cx1, cy1, cx2, cy2, x2, y2)
|
1908
|
-
assertDrawing__
|
1909
|
-
@painter__.bezier x1, y1, cx1, cy1, cx2, cy2, x2, y2
|
1910
|
-
nil
|
1911
|
-
end
|
1912
|
-
|
1913
|
-
# Draws a text.
|
1914
|
-
#
|
1915
|
-
# The parameters a, b, c, and d are determined by rectMode().
|
1916
|
-
#
|
1917
|
-
# @overload text(str)
|
1918
|
-
# @overload text(str, x, y)
|
1919
|
-
# @overload text(str, a, b, c, d)
|
1920
|
-
#
|
1921
|
-
# @param str [String] text to draw
|
1922
|
-
# @param x [Numeric] horizontal position of the text
|
1923
|
-
# @param y [Numeric] vertical position of the text
|
1924
|
-
# @param a [Numeric] horizontal position of the text, by default
|
1925
|
-
# @param b [Numeric] vertical position of the text, by default
|
1926
|
-
# @param c [Numeric] width of the text, by default
|
1927
|
-
# @param d [Numeric] height of the text, by default
|
1928
|
-
#
|
1929
|
-
# @return [nil] nil
|
1930
|
-
#
|
1931
|
-
def text(str, x, y, x2 = nil, y2 = nil)
|
1932
|
-
assertDrawing__
|
1933
|
-
if x2
|
1934
|
-
raise ArgumentError, "missing y2 parameter" unless y2
|
1935
|
-
x, y, w, h = toXYWH__ @rectMode__, x, y, x2, y2
|
1936
|
-
case @textAlignH__
|
1937
|
-
when RIGHT then x += w - @painter__.font.width(str)
|
1938
|
-
when CENTER then x += (w - @painter__.font.width(str)) / 2
|
1939
|
-
end
|
1940
|
-
case @textAlignV__
|
1941
|
-
when BOTTOM then y += h - @painter__.font.height
|
1942
|
-
when CENTER then y += (h - @painter__.font.height) / 2
|
1943
|
-
else
|
1944
|
-
end
|
1945
|
-
else
|
1946
|
-
y -= @painter__.font.ascent
|
1947
|
-
end
|
1948
|
-
@painter__.text str, x, y
|
1949
|
-
nil
|
1950
|
-
end
|
1951
|
-
|
1952
|
-
# Draws an image.
|
1953
|
-
#
|
1954
|
-
# The parameters a, b, c, and d are determined by imageMode().
|
1955
|
-
#
|
1956
|
-
# @overload image(img, a, b)
|
1957
|
-
# @overload image(img, a, b, c, d)
|
1958
|
-
#
|
1959
|
-
# @param img [Image] image to draw
|
1960
|
-
# @param a [Numeric] horizontal position of the image, by default
|
1961
|
-
# @param b [Numeric] vertical position of the image, by default
|
1962
|
-
# @param c [Numeric] width of the image, by default
|
1963
|
-
# @param d [Numeric] height of the image, by default
|
1964
|
-
#
|
1965
|
-
# @return [nil] nil
|
1966
|
-
#
|
1967
|
-
def image(img, a, b, c = nil, d = nil)
|
1968
|
-
assertDrawing__
|
1969
|
-
x, y, w, h = toXYWH__ @imageMode__, a, b, c || img.width, d || img.height
|
1970
|
-
tint = @tint__ ? toRGBA__(*@tint__) : 1
|
1971
|
-
img.drawImage__ @painter__, x, y, w, h, fill: tint, stroke: :none
|
1972
|
-
nil
|
1973
|
-
end
|
1974
|
-
|
1975
|
-
# Copies image.
|
1976
|
-
#
|
1977
|
-
# @overload copy(sx, sy, sw, sh, dx, dy, dw, dh)
|
1978
|
-
# @overload copy(img, sx, sy, sw, sh, dx, dy, dw, dh)
|
1979
|
-
#
|
1980
|
-
# @param img [Image] image for copy source
|
1981
|
-
# @param sx [Numrtic] x position of source region
|
1982
|
-
# @param sy [Numrtic] y position of source region
|
1983
|
-
# @param sw [Numrtic] width of source region
|
1984
|
-
# @param sh [Numrtic] height of source region
|
1985
|
-
# @param dx [Numrtic] x position of destination region
|
1986
|
-
# @param dy [Numrtic] y position of destination region
|
1987
|
-
# @param dw [Numrtic] width of destination region
|
1988
|
-
# @param dh [Numrtic] height of destination region
|
1989
|
-
#
|
1990
|
-
# @return [nil] nil
|
1991
|
-
#
|
1992
|
-
def copy(img = nil, sx, sy, sw, sh, dx, dy, dw, dh)
|
1993
|
-
blend img, sx, sy, sw, sh, dx, dy, dw, dh, BLEND
|
1994
|
-
end
|
1995
|
-
|
1996
|
-
# Blends image.
|
1997
|
-
#
|
1998
|
-
# @overload blend(sx, sy, sw, sh, dx, dy, dw, dh, mode)
|
1999
|
-
# @overload blend(img, sx, sy, sw, sh, dx, dy, dw, dh, mode)
|
2000
|
-
#
|
2001
|
-
# @param img [Image] image for blend source
|
2002
|
-
# @param sx [Numrtic] x position of source region
|
2003
|
-
# @param sy [Numrtic] y position of source region
|
2004
|
-
# @param sw [Numrtic] width of source region
|
2005
|
-
# @param sh [Numrtic] height of source region
|
2006
|
-
# @param dx [Numrtic] x position of destination region
|
2007
|
-
# @param dy [Numrtic] y position of destination region
|
2008
|
-
# @param dw [Numrtic] width of destination region
|
2009
|
-
# @param dh [Numrtic] height of destination region
|
2010
|
-
# @param mode [BLEND, ADD, SUBTRACT, LIGHTEST, DARKEST, EXCLUSION, MULTIPLY, SCREEN, REPLACE] blend mode
|
2011
|
-
#
|
2012
|
-
# @return [nil] nil
|
2013
|
-
#
|
2014
|
-
def blend(img = nil, sx, sy, sw, sh, dx, dy, dw, dh, mode)
|
2015
|
-
assertDrawing__
|
2016
|
-
img ||= self
|
2017
|
-
img.drawImage__ @painter__, sx, sy, sw, sh, dx, dy, dw, dh, blend_mode: mode
|
2018
|
-
end
|
2019
|
-
|
2020
|
-
# Saves screen image to file.
|
2021
|
-
#
|
2022
|
-
# @param filename [String] file name to save image
|
2023
|
-
#
|
2024
|
-
def save(filename)
|
2025
|
-
@window__.canvas_image.save filename
|
2026
|
-
end
|
2027
|
-
|
2028
|
-
# Applies translation matrix to current transformation matrix.
|
2029
|
-
#
|
2030
|
-
# @overload translate(x, y)
|
2031
|
-
# @overload translate(x, y, z)
|
2032
|
-
#
|
2033
|
-
# @param x [Numeric] left/right translation
|
2034
|
-
# @param y [Numeric] up/down translation
|
2035
|
-
# @param y [Numeric] forward/backward translation
|
2036
|
-
#
|
2037
|
-
# @return [nil] nil
|
2038
|
-
#
|
2039
|
-
def translate(x, y, z = 0)
|
2040
|
-
assertDrawing__
|
2041
|
-
@painter__.translate x, y, z
|
2042
|
-
nil
|
2043
|
-
end
|
2044
|
-
|
2045
|
-
# Applies scale matrix to current transformation matrix.
|
2046
|
-
#
|
2047
|
-
# @overload scale(s)
|
2048
|
-
# @overload scale(x, y)
|
2049
|
-
#
|
2050
|
-
# @param s [Numeric] horizontal and vertical scale
|
2051
|
-
# @param x [Numeric] horizontal scale
|
2052
|
-
# @param y [Numeric] vertical scale
|
2053
|
-
#
|
2054
|
-
# @return [nil] nil
|
2055
|
-
#
|
2056
|
-
def scale(x, y)
|
2057
|
-
assertDrawing__
|
2058
|
-
@painter__.scale x, y
|
2059
|
-
nil
|
2060
|
-
end
|
2061
|
-
|
2062
|
-
# Applies rotation matrix to current transformation matrix.
|
2063
|
-
#
|
2064
|
-
# @param angle [Numeric] angle for rotation
|
2065
|
-
#
|
2066
|
-
# @return [nil] nil
|
2067
|
-
#
|
2068
|
-
def rotate(angle)
|
2069
|
-
assertDrawing__
|
2070
|
-
@painter__.rotate toAngle__ angle
|
2071
|
-
nil
|
2072
|
-
end
|
2073
|
-
|
2074
|
-
# Pushes the current transformation matrix to stack.
|
2075
|
-
#
|
2076
|
-
# @return [nil] nil
|
2077
|
-
#
|
2078
|
-
def pushMatrix(&block)
|
2079
|
-
assertDrawing__
|
2080
|
-
@matrixStack__.push @painter__.matrix
|
2081
|
-
block.call if block
|
2082
|
-
nil
|
2083
|
-
ensure
|
2084
|
-
popMatrix if block
|
2085
|
-
end
|
2086
|
-
|
2087
|
-
# Pops the current transformation matrix from stack.
|
2088
|
-
#
|
2089
|
-
# @return [nil] nil
|
2090
|
-
#
|
2091
|
-
def popMatrix()
|
2092
|
-
assertDrawing__
|
2093
|
-
raise "matrix stack underflow" if @matrixStack__.empty?
|
2094
|
-
@painter__.matrix = @matrixStack__.pop
|
2095
|
-
nil
|
2096
|
-
end
|
2097
|
-
|
2098
|
-
# Reset current transformation matrix with identity matrix.
|
2099
|
-
#
|
2100
|
-
# @return [nil] nil
|
2101
|
-
#
|
2102
|
-
def resetMatrix()
|
2103
|
-
assertDrawing__
|
2104
|
-
@painter__.matrix = 1
|
2105
|
-
nil
|
2106
|
-
end
|
2107
|
-
|
2108
|
-
# Save current style values to the style stack.
|
2109
|
-
#
|
2110
|
-
# @return [nil] nil
|
2111
|
-
#
|
2112
|
-
def pushStyle(&block)
|
2113
|
-
assertDrawing__
|
2114
|
-
@styleStack__.push [
|
2115
|
-
@painter__.fill,
|
2116
|
-
@painter__.stroke,
|
2117
|
-
@painter__.stroke_width,
|
2118
|
-
@painter__.stroke_cap,
|
2119
|
-
@painter__.stroke_join,
|
2120
|
-
@painter__.clip,
|
2121
|
-
@painter__.blend_mode,
|
2122
|
-
@painter__.font,
|
2123
|
-
@painter__.shader,
|
2124
|
-
@hsbColor__,
|
2125
|
-
@colorMaxes__,
|
2126
|
-
@angleScale__,
|
2127
|
-
@rectMode__,
|
2128
|
-
@ellipseMode__,
|
2129
|
-
@imageMode__,
|
2130
|
-
@textAlignH__,
|
2131
|
-
@textAlignV__,
|
2132
|
-
@tint__,
|
2133
|
-
@filter__,
|
2134
|
-
]
|
2135
|
-
block.call if block
|
2136
|
-
nil
|
2137
|
-
ensure
|
2138
|
-
popStyle if block
|
2139
|
-
end
|
2140
|
-
|
2141
|
-
# Restore style values from the style stack.
|
2142
|
-
#
|
2143
|
-
# @return [nil] nil
|
2144
|
-
#
|
2145
|
-
def popStyle()
|
2146
|
-
assertDrawing__
|
2147
|
-
raise "style stack underflow" if @styleStack__.empty?
|
2148
|
-
@painter__.fill,
|
2149
|
-
@painter__.stroke,
|
2150
|
-
@painter__.stroke_width,
|
2151
|
-
@painter__.stroke_cap,
|
2152
|
-
@painter__.stroke_join,
|
2153
|
-
@painter__.clip,
|
2154
|
-
@painter__.blend_mode,
|
2155
|
-
@painter__.font,
|
2156
|
-
@painter__.shader,
|
2157
|
-
@hsbColor__,
|
2158
|
-
@colorMaxes__,
|
2159
|
-
@angleScale__,
|
2160
|
-
@rectMode__,
|
2161
|
-
@ellipseMode__,
|
2162
|
-
@imageMode__,
|
2163
|
-
@textAlignH__,
|
2164
|
-
@textAlignV__,
|
2165
|
-
@tint__,
|
2166
|
-
@filter__ = @styleStack__.pop
|
2167
|
-
nil
|
2168
|
-
end
|
2169
|
-
|
2170
|
-
# Save current styles and transformations to stack.
|
2171
|
-
#
|
2172
|
-
# @return [nil] nil
|
2173
|
-
#
|
2174
|
-
def push(&block)
|
2175
|
-
pushMatrix
|
2176
|
-
pushStyle
|
2177
|
-
block.call if block
|
2178
|
-
ensure
|
2179
|
-
pop if block
|
2180
|
-
end
|
2181
|
-
|
2182
|
-
# Restore styles and transformations from stack.
|
2183
|
-
#
|
2184
|
-
# @return [nil] nil
|
2185
|
-
#
|
2186
|
-
def pop()
|
2187
|
-
popMatrix
|
2188
|
-
popStyle
|
2189
|
-
end
|
2190
|
-
|
2191
|
-
# @private
|
2192
|
-
def getInternal__()
|
2193
|
-
@image__
|
2194
|
-
end
|
2195
|
-
|
2196
|
-
# @private
|
2197
|
-
def drawImage__(painter, *args, **states)
|
2198
|
-
shader = painter.shader || @filter__&.getInternal__
|
2199
|
-
painter.push shader: shader, **states do |_|
|
2200
|
-
painter.image getInternal__, *args
|
2201
|
-
end
|
2202
|
-
end
|
2203
|
-
|
2204
|
-
# @private
|
2205
|
-
private def assertDrawing__()
|
2206
|
-
raise "call beginDraw() before drawing" unless @drawing__
|
2207
|
-
end
|
2208
|
-
|
2209
|
-
#
|
2210
|
-
# Utilities
|
2211
|
-
#
|
2212
|
-
|
2213
|
-
# Returns the absolute number of the value.
|
2214
|
-
#
|
2215
|
-
# @param value [Numeric] number
|
2216
|
-
#
|
2217
|
-
# @return [Numeric] absolute number
|
2218
|
-
#
|
2219
|
-
def abs(value)
|
2220
|
-
value.abs
|
2221
|
-
end
|
2222
|
-
|
2223
|
-
# Returns the closest integer number greater than or equal to the value.
|
2224
|
-
#
|
2225
|
-
# @param value [Numeric] number
|
2226
|
-
#
|
2227
|
-
# @return [Numeric] rounded up number
|
2228
|
-
#
|
2229
|
-
def ceil(value)
|
2230
|
-
value.ceil
|
2231
|
-
end
|
2232
|
-
|
2233
|
-
# Returns the closest integer number less than or equal to the value.
|
2234
|
-
#
|
2235
|
-
# @param value [Numeric] number
|
2236
|
-
#
|
2237
|
-
# @return [Numeric] rounded down number
|
2238
|
-
#
|
2239
|
-
def floor(value)
|
2240
|
-
value.floor
|
2241
|
-
end
|
2242
|
-
|
2243
|
-
# Returns the closest integer number.
|
2244
|
-
#
|
2245
|
-
# @param value [Numeric] number
|
2246
|
-
#
|
2247
|
-
# @return [Numeric] rounded number
|
2248
|
-
#
|
2249
|
-
def round(value)
|
2250
|
-
value.round
|
2251
|
-
end
|
2252
|
-
|
2253
|
-
# Returns the natural logarithm (the base-e logarithm) of a number.
|
2254
|
-
#
|
2255
|
-
# @param value [Numeric] number (> 0.0)
|
2256
|
-
#
|
2257
|
-
# @return [Numeric] result number
|
2258
|
-
#
|
2259
|
-
def log(n)
|
2260
|
-
Math.log n
|
2261
|
-
end
|
2262
|
-
|
2263
|
-
# Returns Euler's number e raised to the power of value.
|
2264
|
-
#
|
2265
|
-
# @param value [Numeric] number
|
2266
|
-
#
|
2267
|
-
# @return [Numeric] result number
|
2268
|
-
#
|
2269
|
-
def exp(n)
|
2270
|
-
Math.exp n
|
2271
|
-
end
|
2272
|
-
|
2273
|
-
# Returns value raised to the power of exponent.
|
2274
|
-
#
|
2275
|
-
# @param value [Numeric] base number
|
2276
|
-
# @param exponent [Numeric] exponent number
|
2277
|
-
#
|
2278
|
-
# @return [Numeric] value ** exponent
|
2279
|
-
#
|
2280
|
-
def pow(value, exponent)
|
2281
|
-
value ** exponent
|
2282
|
-
end
|
2283
|
-
|
2284
|
-
# Returns squared value.
|
2285
|
-
#
|
2286
|
-
# @param value [Numeric] number
|
2287
|
-
#
|
2288
|
-
# @return [Numeric] squared value
|
2289
|
-
#
|
2290
|
-
def sq(value)
|
2291
|
-
value * value
|
2292
|
-
end
|
2293
|
-
|
2294
|
-
# Returns squared value.
|
2295
|
-
#
|
2296
|
-
# @param value [Numeric] number
|
2297
|
-
#
|
2298
|
-
# @return [Numeric] squared value
|
2299
|
-
#
|
2300
|
-
def sqrt(value)
|
2301
|
-
Math.sqrt value
|
2302
|
-
end
|
2303
|
-
|
2304
|
-
# Returns the magnitude (or length) of a vector.
|
2305
|
-
#
|
2306
|
-
# @overload mag(x, y)
|
2307
|
-
# @overload mag(x, y, z)
|
2308
|
-
#
|
2309
|
-
# @param x [Numeric] x of point
|
2310
|
-
# @param y [Numeric] y of point
|
2311
|
-
# @param z [Numeric] z of point
|
2312
|
-
#
|
2313
|
-
# @return [Numeric] magnitude
|
2314
|
-
#
|
2315
|
-
def mag(*args)
|
2316
|
-
x, y, z = *args
|
2317
|
-
case args.size
|
2318
|
-
when 2 then Math.sqrt x * x + y * y
|
2319
|
-
when 3 then Math.sqrt x * x + y * y + z * z
|
2320
|
-
else raise ArgumentError
|
2321
|
-
end
|
2322
|
-
end
|
2323
|
-
|
2324
|
-
# Returns distance between 2 points.
|
2325
|
-
#
|
2326
|
-
# @overload dist(x1, y1, x2, y2)
|
2327
|
-
# @overload dist(x1, y1, z1, x2, y2, z2)
|
2328
|
-
#
|
2329
|
-
# @param x1 [Numeric] x of first point
|
2330
|
-
# @param y1 [Numeric] y of first point
|
2331
|
-
# @param z1 [Numeric] z of first point
|
2332
|
-
# @param x2 [Numeric] x of second point
|
2333
|
-
# @param y2 [Numeric] y of second point
|
2334
|
-
# @param z2 [Numeric] z of second point
|
2335
|
-
#
|
2336
|
-
# @return [Numeric] distance between 2 points
|
2337
|
-
#
|
2338
|
-
def dist(*args)
|
2339
|
-
case args.size
|
2340
|
-
when 4
|
2341
|
-
x1, y1, x2, y2 = *args
|
2342
|
-
xx, yy = x2 - x1, y2 - y1
|
2343
|
-
Math.sqrt xx * xx + yy * yy
|
2344
|
-
when 3
|
2345
|
-
x1, y1, z1, x2, y2, z2 = *args
|
2346
|
-
xx, yy, zz = x2 - x1, y2 - y1, z2 - z1
|
2347
|
-
Math.sqrt xx * xx + yy * yy + zz * zz
|
2348
|
-
else raise ArgumentError
|
2349
|
-
end
|
2350
|
-
end
|
2351
|
-
|
2352
|
-
# Normalize the value from range start..stop into 0..1.
|
2353
|
-
#
|
2354
|
-
# @param value [Numeric] number to be normalized
|
2355
|
-
# @param start [Numeric] lower bound of the range
|
2356
|
-
# @param stop [Numeric] upper bound of the range
|
2357
|
-
#
|
2358
|
-
# @return [Numeric] normalized value between 0..1
|
2359
|
-
#
|
2360
|
-
def norm(value, start, stop)
|
2361
|
-
(value.to_f - start.to_f) / (stop.to_f - start.to_f)
|
2362
|
-
end
|
2363
|
-
|
2364
|
-
# Returns the interpolated number between range start..stop.
|
2365
|
-
#
|
2366
|
-
# @param start [Numeric] lower bound of the range
|
2367
|
-
# @param stop [Numeric] upper bound of the range
|
2368
|
-
# @param amount [Numeric] amount to interpolate
|
2369
|
-
#
|
2370
|
-
# @return [Numeric] interporated number
|
2371
|
-
#
|
2372
|
-
def lerp(start, stop, amount)
|
2373
|
-
start + (stop - start) * amount
|
2374
|
-
end
|
2375
|
-
|
2376
|
-
# Maps a number from range start1..stop1 to range start2..stop2.
|
2377
|
-
#
|
2378
|
-
# @param value [Numeric] number to be mapped
|
2379
|
-
# @param start1 [Numeric] lower bound of the range1
|
2380
|
-
# @param stop1 [Numeric] upper bound of the range1
|
2381
|
-
# @param start2 [Numeric] lower bound of the range2
|
2382
|
-
# @param stop2 [Numeric] upper bound of the range2
|
2383
|
-
#
|
2384
|
-
# @return [Numeric] mapped number
|
2385
|
-
#
|
2386
|
-
def map(value, start1, stop1, start2, stop2)
|
2387
|
-
lerp start2, stop2, norm(value, start1, stop1)
|
2388
|
-
end
|
2389
|
-
|
2390
|
-
# Returns minimum value.
|
2391
|
-
#
|
2392
|
-
# @overload min(a, b)
|
2393
|
-
# @overload min(a, b, c)
|
2394
|
-
# @overload min(array)
|
2395
|
-
#
|
2396
|
-
# @param a [Numeric] value to compare
|
2397
|
-
# @param b [Numeric] value to compare
|
2398
|
-
# @param c [Numeric] value to compare
|
2399
|
-
# @param array [Numeric] values to compare
|
2400
|
-
#
|
2401
|
-
# @return [Numeric] minimum value
|
2402
|
-
#
|
2403
|
-
def min(*args)
|
2404
|
-
args.flatten.min
|
2405
|
-
end
|
2406
|
-
|
2407
|
-
# Returns maximum value.
|
2408
|
-
#
|
2409
|
-
# @overload max(a, b)
|
2410
|
-
# @overload max(a, b, c)
|
2411
|
-
# @overload max(array)
|
2412
|
-
#
|
2413
|
-
# @param a [Numeric] value to compare
|
2414
|
-
# @param b [Numeric] value to compare
|
2415
|
-
# @param c [Numeric] value to compare
|
2416
|
-
# @param array [Numeric] values to compare
|
2417
|
-
#
|
2418
|
-
# @return [Numeric] maximum value
|
2419
|
-
#
|
2420
|
-
def max(*args)
|
2421
|
-
args.flatten.max
|
2422
|
-
end
|
2423
|
-
|
2424
|
-
# Constrains the number between min..max.
|
2425
|
-
#
|
2426
|
-
# @param value [Numeric] number to be constrained
|
2427
|
-
# @param min [Numeric] lower bound of the range
|
2428
|
-
# @param max [Numeric] upper bound of the range
|
2429
|
-
#
|
2430
|
-
# @return [Numeric] constrained number
|
2431
|
-
#
|
2432
|
-
def constrain(value, min, max)
|
2433
|
-
value < min ? min : (value > max ? max : value)
|
2434
|
-
end
|
2435
|
-
|
2436
|
-
# Converts degree to radian.
|
2437
|
-
#
|
2438
|
-
# @param degree [Numeric] degree to convert
|
2439
|
-
#
|
2440
|
-
# @return [Numeric] radian
|
2441
|
-
#
|
2442
|
-
def radians(degree)
|
2443
|
-
degree * DEG2RAD__
|
2444
|
-
end
|
2445
|
-
|
2446
|
-
# Converts radian to degree.
|
2447
|
-
#
|
2448
|
-
# @param radian [Numeric] radian to convert
|
2449
|
-
#
|
2450
|
-
# @return [Numeric] degree
|
2451
|
-
#
|
2452
|
-
def degrees(radian)
|
2453
|
-
radian * RAD2DEG__
|
2454
|
-
end
|
2455
|
-
|
2456
|
-
# Returns the sine of an angle.
|
2457
|
-
#
|
2458
|
-
# @param angle [Numeric] angle in radians
|
2459
|
-
#
|
2460
|
-
# @return [Numeric] the sine
|
2461
|
-
#
|
2462
|
-
def sin(angle)
|
2463
|
-
Math.sin angle
|
2464
|
-
end
|
2465
|
-
|
2466
|
-
# Returns the cosine of an angle.
|
2467
|
-
#
|
2468
|
-
# @param angle [Numeric] angle in radians
|
2469
|
-
#
|
2470
|
-
# @return [Numeric] the cosine
|
2471
|
-
#
|
2472
|
-
def cos(angle)
|
2473
|
-
Math.cos angle
|
2474
|
-
end
|
2475
|
-
|
2476
|
-
# Returns the ratio of the sine and cosine of an angle.
|
2477
|
-
#
|
2478
|
-
# @param angle [Numeric] angle in radians
|
2479
|
-
#
|
2480
|
-
# @return [Numeric] the tangent
|
2481
|
-
#
|
2482
|
-
def tan(angle)
|
2483
|
-
Math.tan angle
|
2484
|
-
end
|
2485
|
-
|
2486
|
-
# Returns the inverse of sin().
|
2487
|
-
#
|
2488
|
-
# @param value [Numeric] value for calculation
|
2489
|
-
#
|
2490
|
-
# @return [Numeric] the arc sine
|
2491
|
-
#
|
2492
|
-
def asin(value)
|
2493
|
-
Math.asin value
|
2494
|
-
end
|
2495
|
-
|
2496
|
-
# Returns the inverse of cos().
|
2497
|
-
#
|
2498
|
-
# @param value [Numeric] value for calculation
|
2499
|
-
#
|
2500
|
-
# @return [Numeric] the arc cosine
|
2501
|
-
#
|
2502
|
-
def acos(value)
|
2503
|
-
Math.acos value
|
2504
|
-
end
|
2505
|
-
|
2506
|
-
# Returns the inverse of tan().
|
2507
|
-
#
|
2508
|
-
# @param value [Numeric] value for valculation
|
2509
|
-
#
|
2510
|
-
# @return [Numeric] the arc tangent
|
2511
|
-
#
|
2512
|
-
def atan(value)
|
2513
|
-
Math.atan value
|
2514
|
-
end
|
2515
|
-
|
2516
|
-
# Returns the angle from a specified point.
|
2517
|
-
#
|
2518
|
-
# @param y [Numeric] y of the point
|
2519
|
-
# @param x [Numeric] x of the point
|
2520
|
-
#
|
2521
|
-
# @return [Numeric] the angle in radians
|
2522
|
-
#
|
2523
|
-
def atan2(y, x)
|
2524
|
-
Math.atan2 y, x
|
2525
|
-
end
|
2526
|
-
|
2527
|
-
# Returns the perlin noise value.
|
2528
|
-
#
|
2529
|
-
# @overload noise(x)
|
2530
|
-
# @overload noise(x, y)
|
2531
|
-
# @overload noise(x, y, z)
|
2532
|
-
#
|
2533
|
-
# @param x [Numeric] horizontal point in noise space
|
2534
|
-
# @param y [Numeric] vertical point in noise space
|
2535
|
-
# @param z [Numeric] depth point in noise space
|
2536
|
-
#
|
2537
|
-
# @return [Numeric] noise value (0.0..1.0)
|
2538
|
-
#
|
2539
|
-
def noise(x, y = 0, z = 0)
|
2540
|
-
Rays.perlin(x, y, z) / 2.0 + 0.5
|
2541
|
-
end
|
2542
|
-
|
2543
|
-
# Returns a random number in range low...high
|
2544
|
-
#
|
2545
|
-
# @overload random()
|
2546
|
-
# @overload random(high)
|
2547
|
-
# @overload random(low, high)
|
2548
|
-
# @overload random(choices)
|
2549
|
-
#
|
2550
|
-
# @param low [Numeric] lower limit
|
2551
|
-
# @param high [Numeric] upper limit
|
2552
|
-
# @param choices [Array] array to choose from
|
2553
|
-
#
|
2554
|
-
# @return [Float] random number
|
2555
|
-
#
|
2556
|
-
def random(*args)
|
2557
|
-
return args.first.sample if args.first.kind_of? Array
|
2558
|
-
high, low = args.reverse
|
2559
|
-
rand (low || 0).to_f...(high || 1).to_f
|
2560
|
-
end
|
2561
|
-
|
2562
|
-
# Creates a new vector.
|
2563
|
-
#
|
2564
|
-
# @overload createVector()
|
2565
|
-
# @overload createVector(x, y)
|
2566
|
-
# @overload createVector(x, y, z)
|
2567
|
-
#
|
2568
|
-
# @param x [Numeric] x of new vector
|
2569
|
-
# @param y [Numeric] y of new vector
|
2570
|
-
# @param z [Numeric] z of new vector
|
2571
|
-
#
|
2572
|
-
# @return [Vector] new vector
|
2573
|
-
#
|
2574
|
-
def createVector(*args)
|
2575
|
-
Vector.new(*args, context: self)
|
2576
|
-
end
|
2577
|
-
|
2578
|
-
# Creates a new image.
|
2579
|
-
#
|
2580
|
-
# @overload createImage(w, h)
|
2581
|
-
# @overload createImage(w, h, format)
|
2582
|
-
#
|
2583
|
-
# @param w [Numeric] width of new image
|
2584
|
-
# @param h [Numeric] height of new image
|
2585
|
-
# @param format [RGB, RGBA] image format
|
2586
|
-
#
|
2587
|
-
# @return [Image] new image
|
2588
|
-
#
|
2589
|
-
def createImage(w, h, format = RGBA)
|
2590
|
-
colorspace = {RGB => Rays::RGB, RGBA => Rays::RGBA}[format]
|
2591
|
-
raise ArgumentError, "Unknown image format" unless colorspace
|
2592
|
-
Image.new Rays::Image.new(w, h, colorspace).paint {background 0, 0}
|
2593
|
-
end
|
2594
|
-
|
2595
|
-
# Creates a new off-screen graphics context object.
|
2596
|
-
#
|
2597
|
-
# @param width [Numeric] width of graphics image
|
2598
|
-
# @param height [Numeric] height of graphics image
|
2599
|
-
#
|
2600
|
-
# @return [Graphics] graphics object
|
2601
|
-
#
|
2602
|
-
def createGraphics(width, height)
|
2603
|
-
Graphics.new width, height
|
2604
|
-
end
|
2605
|
-
|
2606
|
-
# Creates a shader object.
|
2607
|
-
#
|
2608
|
-
# Passing nil for a vertex shader parameter causes the following default vertex shader to be used.
|
2609
|
-
# ```
|
2610
|
-
# attribute vec3 position;
|
2611
|
-
# attribute vec3 texCoord;
|
2612
|
-
# attribute vec4 color;
|
2613
|
-
# varying vec4 vertPosition;
|
2614
|
-
# varying vec4 vertTexCoord;
|
2615
|
-
# varying vec4 vertColor;
|
2616
|
-
# uniform mat4 transform;
|
2617
|
-
# uniform mat4 texMatrix;
|
2618
|
-
# void main ()
|
2619
|
-
# {
|
2620
|
-
# vec4 pos__ = vec4(position, 1.0);
|
2621
|
-
# vertPosition = pos__;
|
2622
|
-
# vertTexCoord = texMatrix * vec4(texCoord, 1.0);
|
2623
|
-
# vertColor = color;
|
2624
|
-
# gl_Position = transform * pos__;
|
2625
|
-
# }
|
2626
|
-
# ```
|
2627
|
-
#
|
2628
|
-
# @overload createShader(vertPath, fragPath)
|
2629
|
-
# @overload createShader(vertSource, fragSource)
|
2630
|
-
#
|
2631
|
-
# @param vertPath [String] vertex shader file path
|
2632
|
-
# @param fragPath [String] fragment shader file path
|
2633
|
-
# @param vertSource [String] vertex shader source
|
2634
|
-
# @param fragSource [String] fragment shader source
|
2635
|
-
#
|
2636
|
-
# @return [Shader] shader object
|
2637
|
-
#
|
2638
|
-
def createShader(vert, frag)
|
2639
|
-
vert = File.read if vert && File.exist?(vert)
|
2640
|
-
frag = File.read if frag && File.exist?(frag)
|
2641
|
-
Shader.new vert, frag
|
2642
|
-
end
|
2643
|
-
|
2644
|
-
# Creates a camera object as a video input device.
|
2645
|
-
#
|
2646
|
-
# @return [Capture] camera object
|
2647
|
-
#
|
2648
|
-
def createCapture(*args)
|
2649
|
-
Capture.new(*args)
|
2650
|
-
end
|
2651
|
-
|
2652
|
-
# Loads image.
|
2653
|
-
#
|
2654
|
-
# @param filename [String] file name to load image
|
2655
|
-
# @param extension [String] type of image to load (ex. 'png')
|
2656
|
-
#
|
2657
|
-
# @return [Image] loaded image object
|
2658
|
-
#
|
2659
|
-
def loadImage(filename, extension = nil)
|
2660
|
-
filename = getImage__ filename, extension if filename =~ %r|^https?://|
|
2661
|
-
Image.new Rays::Image.load filename
|
2662
|
-
end
|
2663
|
-
|
2664
|
-
# Loads shader file.
|
2665
|
-
#
|
2666
|
-
# @overload loadShader(fragPath)
|
2667
|
-
# @overload loadShader(fragPath, vertPath)
|
2668
|
-
#
|
2669
|
-
# @param fragPath [String] fragment shader file path
|
2670
|
-
# @param vertPath [String] vertex shader file path
|
2671
|
-
#
|
2672
|
-
# @return [Shader] loaded shader object
|
2673
|
-
#
|
2674
|
-
def loadShader(fragPath, vertPath = nil)
|
2675
|
-
createShader vertPath, fragPath
|
2676
|
-
end
|
2677
|
-
|
2678
|
-
# @private
|
2679
|
-
private def getImage__(uri, ext)
|
2680
|
-
ext ||= File.extname uri
|
2681
|
-
raise "unsupported image type -- #{ext}" unless ext =~ /^\.?(png|jpg|gif)$/i
|
2682
|
-
|
2683
|
-
tmpdir = tmpdir__
|
2684
|
-
path = tmpdir + Digest::SHA1.hexdigest(uri)
|
2685
|
-
path = path.sub_ext ext
|
2686
|
-
|
2687
|
-
unless path.file?
|
2688
|
-
URI.open uri do |input|
|
2689
|
-
input.set_encoding nil# disable default_internal
|
2690
|
-
tmpdir.mkdir unless tmpdir.directory?
|
2691
|
-
path.open('w') do |output|
|
2692
|
-
output.set_encoding Encoding::ASCII_8BIT
|
2693
|
-
while buf = input.read(2 ** 16)
|
2694
|
-
output.write buf
|
2695
|
-
end
|
2696
|
-
end
|
2697
|
-
end
|
2698
|
-
end
|
2699
|
-
path.to_s
|
2700
|
-
end
|
2701
|
-
|
2702
|
-
# @private
|
2703
|
-
private def tmpdir__()
|
2704
|
-
Pathname(Dir.tmpdir) + Digest::SHA1.hexdigest(self.class.name)
|
2705
|
-
end
|
2706
|
-
|
2707
|
-
end# GraphicsContext
|
2708
|
-
|
2709
|
-
|
2710
|
-
# Draws graphics into an offscreen buffer
|
2711
|
-
#
|
2712
|
-
class Graphics
|
2713
|
-
|
2714
|
-
include GraphicsContext
|
2715
|
-
|
2716
|
-
# Initialize graphics object.
|
2717
|
-
#
|
2718
|
-
def initialize(width, height)
|
2719
|
-
image = Rays::Image.new width, height
|
2720
|
-
init__ image, image.painter
|
2721
|
-
end
|
2722
|
-
|
2723
|
-
# Start drawing.
|
2724
|
-
#
|
2725
|
-
def beginDraw(&block)
|
2726
|
-
beginDraw__
|
2727
|
-
@painter__.__send__ :begin_paint
|
2728
|
-
push
|
2729
|
-
if block
|
2730
|
-
block.call
|
2731
|
-
endDraw
|
2732
|
-
end
|
2733
|
-
end
|
2734
|
-
|
2735
|
-
# End drawing.
|
2736
|
-
#
|
2737
|
-
def endDraw()
|
2738
|
-
pop
|
2739
|
-
@painter__.__send__ :end_paint
|
2740
|
-
endDraw__
|
2741
|
-
end
|
2742
|
-
|
2743
|
-
end# Graphics
|
2744
|
-
|
2745
|
-
|
2746
|
-
# Processing context
|
2747
|
-
#
|
2748
|
-
class Context
|
2749
|
-
|
2750
|
-
include GraphicsContext
|
2751
|
-
|
2752
|
-
Vector = Processing::Vector
|
2753
|
-
Capture = Processing::Capture
|
2754
|
-
Graphics = Processing::Graphics
|
2755
|
-
Shader = Processing::Shader
|
2756
|
-
|
2757
|
-
# @private
|
2758
|
-
@@context__ = nil
|
2759
|
-
|
2760
|
-
# @private
|
2761
|
-
def self.context__()
|
2762
|
-
@@context__
|
2763
|
-
end
|
2764
|
-
|
2765
|
-
# @private
|
2766
|
-
def initialize(window)
|
2767
|
-
@@context__ = self
|
2768
|
-
|
2769
|
-
tmpdir__.tap {|dir| FileUtils.rm_r dir.to_s if dir.directory?}
|
2770
|
-
|
2771
|
-
@window__ = window
|
2772
|
-
init__(
|
2773
|
-
@window__.canvas_image,
|
2774
|
-
@window__.canvas_painter.paint {background 0.8})
|
2775
|
-
|
2776
|
-
@loop__ = true
|
2777
|
-
@redraw__ = false
|
2778
|
-
@frameCount__ = 0
|
2779
|
-
@key__ = nil
|
2780
|
-
@keyCode__ = nil
|
2781
|
-
@keysPressed__ = Set.new
|
2782
|
-
@pointerPos__ =
|
2783
|
-
@pointerPrevPos__ = Rays::Point.new 0
|
2784
|
-
@pointersPressed__ = []
|
2785
|
-
@touches__ = []
|
2786
|
-
@motionGravity__ = createVector 0, 0
|
2787
|
-
|
2788
|
-
@window__.before_draw = proc {beginDraw__}
|
2789
|
-
@window__.after_draw = proc {endDraw__}
|
2790
|
-
@window__.update_canvas = proc {|i, p| updateCanvas__ i, p}
|
2791
|
-
|
2792
|
-
@window__.instance_variable_set :@context, self
|
2793
|
-
def @window__.draw_screen(painter)
|
2794
|
-
@context.drawImage__ painter
|
2795
|
-
end
|
2796
|
-
|
2797
|
-
drawFrame = -> {
|
2798
|
-
begin
|
2799
|
-
push
|
2800
|
-
@drawBlock__.call if @drawBlock__
|
2801
|
-
ensure
|
2802
|
-
pop
|
2803
|
-
@frameCount__ += 1
|
2804
|
-
end
|
2805
|
-
}
|
2806
|
-
|
2807
|
-
@window__.draw = proc do |e|
|
2808
|
-
if @loop__ || @redraw__
|
2809
|
-
@redraw__ = false
|
2810
|
-
drawFrame.call
|
2811
|
-
end
|
2812
|
-
end
|
2813
|
-
|
2814
|
-
updateKeyStates = -> event, pressed {
|
2815
|
-
@key__ = event.chars
|
2816
|
-
@keyCode__ = event.key
|
2817
|
-
if pressed != nil
|
2818
|
-
set, key = @keysPressed__, event.key
|
2819
|
-
pressed ? set.add(key) : set.delete(key)
|
2820
|
-
end
|
2821
|
-
}
|
2822
|
-
|
2823
|
-
mouseButtonMap = {
|
2824
|
-
mouse_left: LEFT,
|
2825
|
-
mouse_right: RIGHT,
|
2826
|
-
mouse_middle: CENTER
|
2827
|
-
}
|
2828
|
-
|
2829
|
-
updatePointerStates = -> event, pressed = nil {
|
2830
|
-
@pointerPrevPos__ = @pointerPos__
|
2831
|
-
@pointerPos__ = event.pos.dup
|
2832
|
-
@touches__ = event.pointers.map {|p| Touch.new(p.id, *p.pos.to_a)}
|
2833
|
-
if pressed != nil
|
2834
|
-
array = @pointersPressed__
|
2835
|
-
event.types
|
2836
|
-
.tap {|types| types.delete :mouse}
|
2837
|
-
.map {|type| mouseButtonMap[type] || type}
|
2838
|
-
.each {|type| pressed ? array.push(type) : array.delete(type)}
|
2839
|
-
end
|
2840
|
-
}
|
2841
|
-
|
2842
|
-
@window__.key_down = proc do |e|
|
2843
|
-
updateKeyStates.call e, true
|
2844
|
-
@keyPressedBlock__&.call
|
2845
|
-
@keyTypedBlock__&.call if @key__ && !@key__.empty?
|
2846
|
-
end
|
2847
|
-
|
2848
|
-
@window__.key_up = proc do |e|
|
2849
|
-
updateKeyStates.call e, false
|
2850
|
-
@keyReleasedBlock__&.call
|
2851
|
-
end
|
2852
|
-
|
2853
|
-
@window__.pointer_down = proc do |e|
|
2854
|
-
updatePointerStates.call e, true
|
2855
|
-
@pointerDownStartPos__ = @pointerPos__.dup
|
2856
|
-
(@touchStartedBlock__ || @mousePressedBlock__)&.call
|
2857
|
-
end
|
2858
|
-
|
2859
|
-
@window__.pointer_up = proc do |e|
|
2860
|
-
updatePointerStates.call e, false
|
2861
|
-
(@touchEndedBlock__ || @mouseReleasedBlock__)&.call
|
2862
|
-
if startPos = @pointerDownStartPos__
|
2863
|
-
@mouseClickedBlock__&.call if (@pointerPos__ - startPos).length < 3
|
2864
|
-
@pointerDownStartPos__ = nil
|
2865
|
-
end
|
2866
|
-
end
|
2867
|
-
|
2868
|
-
@window__.pointer_move = proc do |e|
|
2869
|
-
updatePointerStates.call e
|
2870
|
-
(@touchMovedBlock__ || @mouseMovedBlock__)&.call
|
2871
|
-
end
|
2872
|
-
|
2873
|
-
@window__.pointer_drag = proc do |e|
|
2874
|
-
updatePointerStates.call e
|
2875
|
-
(@touchMovedBlock__ || @mouseDraggedBlock__)&.call
|
2876
|
-
end
|
2877
|
-
|
2878
|
-
@window__.motion = proc do |e|
|
2879
|
-
@motionGravity__ = createVector(*e.gravity.to_a(3))
|
2880
|
-
@motionBlock__&.call
|
2881
|
-
end
|
2882
|
-
end
|
2883
|
-
|
2884
|
-
# Defines setup block.
|
2885
|
-
#
|
2886
|
-
# @return [nil] nil
|
2887
|
-
#
|
2888
|
-
def setup(&block)
|
2889
|
-
@window__.setup = block
|
2890
|
-
nil
|
2891
|
-
end
|
2892
|
-
|
2893
|
-
# Defines draw block.
|
2894
|
-
#
|
2895
|
-
# @return [nil] nil
|
2896
|
-
#
|
2897
|
-
def draw(&block)
|
2898
|
-
@drawBlock__ = block if block
|
2899
|
-
nil
|
2900
|
-
end
|
2901
|
-
|
2902
|
-
# Defines keyPressed block.
|
2903
|
-
#
|
2904
|
-
# @return [Boolean] is any key pressed or not
|
2905
|
-
#
|
2906
|
-
def keyPressed(&block)
|
2907
|
-
@keyPressedBlock__ = block if block
|
2908
|
-
not @keysPressed__.empty?
|
2909
|
-
end
|
2910
|
-
|
2911
|
-
# Defines keyReleased block.
|
2912
|
-
#
|
2913
|
-
# @return [nil] nil
|
2914
|
-
#
|
2915
|
-
def keyReleased(&block)
|
2916
|
-
@keyReleasedBlock__ = block if block
|
2917
|
-
nil
|
2918
|
-
end
|
2919
|
-
|
2920
|
-
# Defines keyTyped block.
|
2921
|
-
#
|
2922
|
-
# @return [nil] nil
|
2923
|
-
#
|
2924
|
-
def keyTyped(&block)
|
2925
|
-
@keyTypedBlock__ = block if block
|
2926
|
-
nil
|
2927
|
-
end
|
2928
|
-
|
2929
|
-
# Defines mousePressed block.
|
2930
|
-
#
|
2931
|
-
# @return [Boolean] is any mouse button pressed or not
|
2932
|
-
#
|
2933
|
-
def mousePressed(&block)
|
2934
|
-
@mousePressedBlock__ = block if block
|
2935
|
-
not @pointersPressed__.empty?
|
2936
|
-
end
|
2937
|
-
|
2938
|
-
# Defines mouseReleased block.
|
2939
|
-
#
|
2940
|
-
# @return [nil] nil
|
2941
|
-
#
|
2942
|
-
def mouseReleased(&block)
|
2943
|
-
@mouseReleasedBlock__ = block if block
|
2944
|
-
nil
|
2945
|
-
end
|
2946
|
-
|
2947
|
-
# Defines mouseMoved block.
|
2948
|
-
#
|
2949
|
-
# @return [nil] nil
|
2950
|
-
#
|
2951
|
-
def mouseMoved(&block)
|
2952
|
-
@mouseMovedBlock__ = block if block
|
2953
|
-
nil
|
2954
|
-
end
|
2955
|
-
|
2956
|
-
# Defines mouseDragged block.
|
2957
|
-
#
|
2958
|
-
# @return [nil] nil
|
2959
|
-
#
|
2960
|
-
def mouseDragged(&block)
|
2961
|
-
@mouseDraggedBlock__ = block if block
|
2962
|
-
nil
|
2963
|
-
end
|
2964
|
-
|
2965
|
-
# Defines mouseClicked block.
|
2966
|
-
#
|
2967
|
-
# @return [nil] nil
|
2968
|
-
#
|
2969
|
-
def mouseClicked(&block)
|
2970
|
-
@mouseClickedBlock__ = block if block
|
2971
|
-
nil
|
2972
|
-
end
|
2973
|
-
|
2974
|
-
# Defines touchStarted block.
|
2975
|
-
#
|
2976
|
-
# @return [nil] nil
|
2977
|
-
#
|
2978
|
-
def touchStarted(&block)
|
2979
|
-
@touchStartedBlock__ = block if block
|
2980
|
-
nil
|
2981
|
-
end
|
2982
|
-
|
2983
|
-
# Defines touchEnded block.
|
2984
|
-
#
|
2985
|
-
# @return [nil] nil
|
2986
|
-
#
|
2987
|
-
def touchEnded(&block)
|
2988
|
-
@touchEndedBlock__ = block if block
|
2989
|
-
nil
|
2990
|
-
end
|
2991
|
-
|
2992
|
-
# Defines touchMoved block.
|
2993
|
-
#
|
2994
|
-
# @return [nil] nil
|
2995
|
-
#
|
2996
|
-
def touchMoved(&block)
|
2997
|
-
@touchMovedBlock__ = block if block
|
2998
|
-
nil
|
2999
|
-
end
|
3000
|
-
|
3001
|
-
# Defines motion block.
|
3002
|
-
#
|
3003
|
-
# @return [nil] nil
|
3004
|
-
#
|
3005
|
-
def motion(&block)
|
3006
|
-
@motionBlock__ = block if block
|
3007
|
-
nil
|
3008
|
-
end
|
3009
|
-
|
3010
|
-
# Changes canvas size.
|
3011
|
-
#
|
3012
|
-
# @param width [Integer] new width
|
3013
|
-
# @param height [Integer] new height
|
3014
|
-
# @param pixelDensity [Numeric] new pixel density
|
3015
|
-
#
|
3016
|
-
# @return [nil] nil
|
3017
|
-
#
|
3018
|
-
def size(width, height, pixelDensity: self.pixelDensity)
|
3019
|
-
resizeCanvas__ :size, width, height, pixelDensity
|
3020
|
-
nil
|
3021
|
-
end
|
3022
|
-
|
3023
|
-
# Changes canvas size.
|
3024
|
-
#
|
3025
|
-
# @param width [Integer] new width
|
3026
|
-
# @param height [Integer] new height
|
3027
|
-
# @param pixelDensity [Numeric] new pixel density
|
3028
|
-
#
|
3029
|
-
# @return [nil] nil
|
3030
|
-
#
|
3031
|
-
def createCanvas(width, height, pixelDensity: self.pixelDensity)
|
3032
|
-
resizeCanvas__ :createCanvas, width, height, pixelDensity
|
3033
|
-
nil
|
3034
|
-
end
|
3035
|
-
|
3036
|
-
# Changes title of window.
|
3037
|
-
#
|
3038
|
-
# @param title [String] new title
|
3039
|
-
#
|
3040
|
-
# @return [nil] nil
|
3041
|
-
#
|
3042
|
-
def setTitle(title)
|
3043
|
-
@window__.title = title
|
3044
|
-
nil
|
3045
|
-
end
|
3046
|
-
|
3047
|
-
# Changes and returns canvas pixel density.
|
3048
|
-
#
|
3049
|
-
# @param density [Numeric] new pixel density
|
3050
|
-
#
|
3051
|
-
# @return [Numeric] current pixel density
|
3052
|
-
#
|
3053
|
-
def pixelDensity(density = nil)
|
3054
|
-
resizeCanvas__ :pixelDensity, width, height, density if density
|
3055
|
-
@painter__.pixel_density
|
3056
|
-
end
|
3057
|
-
|
3058
|
-
# @private
|
3059
|
-
def resizeCanvas__(name, width, height, pixelDensity)
|
3060
|
-
raise '#{name}() must be called on startup or setup block' if @started__
|
3061
|
-
|
3062
|
-
@painter__.__send__ :end_paint
|
3063
|
-
@window__.resize_canvas width, height, pixelDensity
|
3064
|
-
@window__.auto_resize = false
|
3065
|
-
ensure
|
3066
|
-
@painter__.__send__ :begin_paint
|
3067
|
-
end
|
3068
|
-
|
3069
|
-
# Returns pixel density of display.
|
3070
|
-
#
|
3071
|
-
# @return [Numeric] pixel density
|
3072
|
-
#
|
3073
|
-
def displayDensity()
|
3074
|
-
@window__.painter.pixel_density
|
3075
|
-
end
|
3076
|
-
|
3077
|
-
# Returns window width.
|
3078
|
-
#
|
3079
|
-
# @return [Numeric] window width
|
3080
|
-
#
|
3081
|
-
def windowWidth()
|
3082
|
-
@window__.width
|
3083
|
-
end
|
3084
|
-
|
3085
|
-
# Returns window height.
|
3086
|
-
#
|
3087
|
-
# @return [Numeric] window height
|
3088
|
-
#
|
3089
|
-
def windowHeight()
|
3090
|
-
@window__.height
|
3091
|
-
end
|
3092
|
-
|
3093
|
-
# Returns number of frames since program started.
|
3094
|
-
#
|
3095
|
-
# @return [Integer] total number of frames
|
3096
|
-
#
|
3097
|
-
def frameCount()
|
3098
|
-
@frameCount__
|
3099
|
-
end
|
3100
|
-
|
3101
|
-
# Returns number of frames per second.
|
3102
|
-
#
|
3103
|
-
# @return [Float] frames per second
|
3104
|
-
#
|
3105
|
-
def frameRate()
|
3106
|
-
@window__.event.fps
|
3107
|
-
end
|
3108
|
-
|
3109
|
-
# Returns the last key that was pressed or released.
|
3110
|
-
#
|
3111
|
-
# @return [String] last key
|
3112
|
-
#
|
3113
|
-
def key()
|
3114
|
-
@key__
|
3115
|
-
end
|
3116
|
-
|
3117
|
-
# Returns the last key code that was pressed or released.
|
3118
|
-
#
|
3119
|
-
# @return [Symbol] last key code
|
3120
|
-
#
|
3121
|
-
def keyCode()
|
3122
|
-
@keyCode__
|
3123
|
-
end
|
3124
|
-
|
3125
|
-
# Returns mouse x position
|
3126
|
-
#
|
3127
|
-
# @return [Numeric] horizontal position of mouse
|
3128
|
-
#
|
3129
|
-
def mouseX()
|
3130
|
-
@pointerPos__.x
|
3131
|
-
end
|
3132
|
-
|
3133
|
-
# Returns mouse y position
|
3134
|
-
#
|
3135
|
-
# @return [Numeric] vertical position of mouse
|
3136
|
-
#
|
3137
|
-
def mouseY()
|
3138
|
-
@pointerPos__.y
|
3139
|
-
end
|
3140
|
-
|
3141
|
-
# Returns mouse x position in previous frame
|
3142
|
-
#
|
3143
|
-
# @return [Numeric] horizontal position of mouse
|
3144
|
-
#
|
3145
|
-
def pmouseX()
|
3146
|
-
@pointerPrevPos__.x
|
3147
|
-
end
|
3148
|
-
|
3149
|
-
# Returns mouse y position in previous frame
|
3150
|
-
#
|
3151
|
-
# @return [Numeric] vertical position of mouse
|
3152
|
-
#
|
3153
|
-
def pmouseY()
|
3154
|
-
@pointerPrevPos__.y
|
3155
|
-
end
|
3156
|
-
|
3157
|
-
# Returns which mouse button was pressed
|
3158
|
-
#
|
3159
|
-
# @return [Numeric] LEFT, RIGHT, CENTER or 0
|
3160
|
-
#
|
3161
|
-
def mouseButton()
|
3162
|
-
(@pointersPressed__ & [LEFT, RIGHT, CENTER]).last || 0
|
3163
|
-
end
|
3164
|
-
|
3165
|
-
# Returns array of touches
|
3166
|
-
#
|
3167
|
-
# @return [Array] Touch objects
|
3168
|
-
#
|
3169
|
-
def touches()
|
3170
|
-
@touches__
|
3171
|
-
end
|
3172
|
-
|
3173
|
-
# Returns vector for real world gravity
|
3174
|
-
#
|
3175
|
-
# @return [Vector] gravity vector
|
3176
|
-
#
|
3177
|
-
def motionGravity()
|
3178
|
-
@motionGravity__
|
3179
|
-
end
|
3180
|
-
|
3181
|
-
# Enables calling draw block on every frame.
|
3182
|
-
#
|
3183
|
-
# @return [nil] nil
|
3184
|
-
#
|
3185
|
-
def loop()
|
3186
|
-
@loop__ = true
|
3187
|
-
end
|
3188
|
-
|
3189
|
-
# Disables calling draw block on every frame.
|
3190
|
-
#
|
3191
|
-
# @return [nil] nil
|
3192
|
-
#
|
3193
|
-
def noLoop()
|
3194
|
-
@loop__ = false
|
3195
|
-
end
|
3196
|
-
|
3197
|
-
# Calls draw block to redraw frame.
|
3198
|
-
#
|
3199
|
-
# @return [nil] nil
|
3200
|
-
#
|
3201
|
-
def redraw()
|
3202
|
-
@redraw__ = true
|
3203
|
-
end
|
3204
|
-
|
3205
|
-
end# Context
|
3206
|
-
|
3207
|
-
|
3208
|
-
end# Processing
|
3209
|
-
|
3210
|
-
|
3211
|
-
end# Processing
|