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.
@@ -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