processing 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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