rubysketch 0.3.0 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a044fb62451ebcd69c89a5a9cb2781c747d4298142a9e6828f71cdbc63da999
4
- data.tar.gz: 6dade74829619df93d947160f930fdc19563cc9042b826ef7b8b4bd6015cfb00
3
+ metadata.gz: 0df24de4fc3eabd1c7880d51ff34ef8389b44bef43a8159c75e9e6c651953c0d
4
+ data.tar.gz: cf03a57e9ecbf8a63f0b089c4588c0cd041ef93e2b92c69a580b8aa1f013659e
5
5
  SHA512:
6
- metadata.gz: 7801ba15e151b5c519047b2145b71e820428b2b9601c9fccaffd1eb6d6b67ff344b6aa7b0cd12c9151d431df01d201c5cc63e3a8ffa92d854b5934a2357fb8ec
7
- data.tar.gz: 44f7ad0c273aa88974356dfcc3fbc7d080d8bccb023ab4137db23f2d7b85b0fa2b06b590a97b487f803575d903a87a8747f26ff3e0518b5c76623f26dcafd35d
6
+ metadata.gz: 953e09a5b8da7f8798186e3f0a4e4b9ca636a5c7a34cdd1eca26da30f09221ac31fe3c5ed9ebc8e498060f84b88de4bb14738ef8054e30544c38ca664522f050
7
+ data.tar.gz: 4c4ae42689cfda821c84617c2925fc48b6af3ad3672d8dd1c603b999427762b5439cbf7c879a06fdf8830f83632d5e01bd9197d1cf528f6ae948a38728063a2a
@@ -1,6 +1,44 @@
1
1
  # RubySketch ChangeLog
2
2
 
3
3
 
4
+ ## [0.3.5] - 2020-08-02
5
+
6
+ - add random()
7
+ - add sin(), cos(), tan(), asin(), acos(), atan() and atan2()
8
+ - make Vector class accessible from user script context
9
+ - fix error on calling rotate()
10
+
11
+
12
+ ## [0.3.4] - 2020-08-02
13
+
14
+ - delete Utility module
15
+
16
+
17
+ ## [0.3.3] - 2020-08-01
18
+
19
+ - add Vector class
20
+
21
+
22
+ ## [0.3.2] - 2020-07-22
23
+
24
+ - text() draws to the baseline by default
25
+ - add textWidth(), textAscent(), textDescent() and textAlign()
26
+ - change initial color for fill() and stroke()
27
+ - change initial background color to grayscale 0.8
28
+
29
+
30
+ ## [0.3.1] - 2020-07-17
31
+
32
+ - add touchStarted(), touchEnded(), touchMoved() and touches()
33
+ - make all event handler drawable
34
+ - limit font max size to 256
35
+
36
+
37
+ ## [0.3.0] - 2020-05-21
38
+
39
+ - add createGraphics()
40
+
41
+
4
42
  ## [0.2.7] - 2020-04-17
5
43
 
6
44
  - add strokeCap() and strokeJoin()
data/Rakefile CHANGED
@@ -18,6 +18,7 @@ MODULES = [Xot, Rucy, Rays, Reflex, RubySketch]
18
18
 
19
19
  ENV['RDOC'] = 'yardoc --no-private'
20
20
 
21
+ test_ruby_extension
21
22
  generate_documents
22
23
  build_ruby_gem
23
24
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.5
@@ -6,13 +6,574 @@ module RubySketch
6
6
  module Processing
7
7
 
8
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 = Context.lerp x, v.x, amount
145
+ self.y = Context.lerp y, v.y, amount
146
+ self.z = Context.lerp z, v.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
+ protected 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
+
9
570
  # Image object.
10
571
  #
11
572
  class Image
12
573
 
13
574
  # @private
14
575
  def initialize (image)
15
- @image__ = image
576
+ @image = image
16
577
  end
17
578
 
18
579
  # Gets width of image.
@@ -20,7 +581,7 @@ module RubySketch
20
581
  # @return [Numeric] width of image
21
582
  #
22
583
  def width ()
23
- @image__.width
584
+ @image.width
24
585
  end
25
586
 
26
587
  # Gets height of image.
@@ -28,7 +589,7 @@ module RubySketch
28
589
  # @return [Numeric] height of image
29
590
  #
30
591
  def height ()
31
- @image__.height
592
+ @image.height
32
593
  end
33
594
 
34
595
  # Resizes image.
@@ -39,8 +600,8 @@ module RubySketch
39
600
  # @return [nil] nil
40
601
  #
41
602
  def resize (width, height)
42
- @image__ = Rays::Image.new(width, height).paint do |painter|
43
- painter.image @image__, 0, 0, width, height
603
+ @image = Rays::Image.new(width, height).paint do |painter|
604
+ painter.image @image, 0, 0, width, height
44
605
  end
45
606
  nil
46
607
  end
@@ -64,7 +625,7 @@ module RubySketch
64
625
  #
65
626
  def copy (img = nil, sx, sy, sw, sh, dx, dy, dw, dh)
66
627
  img ||= self
67
- @image__.paint do |painter|
628
+ @image.paint do |painter|
68
629
  painter.image img.getInternal__, sx, sy, sw, sh, dx, dy, dw, dh
69
630
  end
70
631
  end
@@ -74,12 +635,12 @@ module RubySketch
74
635
  # @param filename [String] file name to save image
75
636
  #
76
637
  def save (filename)
77
- @image__.save filename
638
+ @image.save filename
78
639
  end
79
640
 
80
641
  # @private
81
642
  def getInternal__ ()
82
- @image__
643
+ @image
83
644
  end
84
645
 
85
646
  end# Image
@@ -143,10 +704,36 @@ module RubySketch
143
704
  end# TextBounds
144
705
 
145
706
 
707
+ # Touch object.
708
+ #
709
+ class Touch
710
+
711
+ # Horizontal position of touch
712
+ #
713
+ attr_reader :x
714
+
715
+ # Vertical position of touch
716
+ #
717
+ attr_reader :y
718
+
719
+ # @private
720
+ def initialize (x, y)
721
+ @x, @y = x, y
722
+ end
723
+
724
+ def id ()
725
+ raise NotImplementedError
726
+ end
727
+
728
+ end# Touch
729
+
730
+
146
731
  # Drawing context
147
732
  #
148
733
  module GraphicsContext
149
734
 
735
+ Vector = Processing::Vector
736
+
150
737
  # PI / 2
151
738
  #
152
739
  HALF_PI = Math::PI / 2
@@ -187,7 +774,7 @@ module RubySketch
187
774
  #
188
775
  CORNERS = :CORNERS
189
776
 
190
- # Mode for rectMode(), ellipseMode() and imageMode().
777
+ # Mode for rectMode(), ellipseMode(), imageMode() and textAlign().
191
778
  #
192
779
  CENTER = :CENTER
193
780
 
@@ -195,6 +782,21 @@ module RubySketch
195
782
  #
196
783
  RADIUS = :RADIUS
197
784
 
785
+ # Mode for textAlign().
786
+ LEFT = :LEFT
787
+
788
+ # Mode for textAlign().
789
+ RIGHT = :RIGHT
790
+
791
+ # Mode for textAlign().
792
+ TOP = :TOP
793
+
794
+ # Mode for textAlign().
795
+ BOTTOM = :BOTTOM
796
+
797
+ # Mode for textAlign().
798
+ BASELINE = :BASELINE
799
+
198
800
  # Mode for strokeCap().
199
801
  #
200
802
  BUTT = :butt
@@ -211,7 +813,10 @@ module RubySketch
211
813
  #
212
814
  SQUARE = :square
213
815
 
214
- def setup__ ()
816
+ def setup__ (painter)
817
+ @painter__ = painter
818
+ @painter__.miter_limit = 10
819
+
215
820
  @drawing = false
216
821
  @hsbColor__ = false
217
822
  @colorMaxes__ = [1.0] * 4
@@ -219,6 +824,8 @@ module RubySketch
219
824
  @rectMode__ = nil
220
825
  @ellipseMode__ = nil
221
826
  @imageMode__ = nil
827
+ @textAlignH__ = nil
828
+ @textAlignV__ = nil
222
829
  @matrixStack__ = []
223
830
  @styleStack__ = []
224
831
 
@@ -227,6 +834,10 @@ module RubySketch
227
834
  rectMode CORNER
228
835
  ellipseMode CENTER
229
836
  imageMode CORNER
837
+ textAlign LEFT
838
+
839
+ fill 255
840
+ stroke 0
230
841
  end
231
842
 
232
843
  def beginDraw ()
@@ -264,10 +875,11 @@ module RubySketch
264
875
  # @return [nil] nil
265
876
  #
266
877
  def colorMode (mode, *maxes)
878
+ mode = mode.upcase.to_sym
267
879
  raise ArgumentError, "invalid color mode: #{mode}" unless [RGB, HSB].include?(mode)
268
880
  raise ArgumentError unless [0, 1, 3, 4].include?(maxes.size)
269
881
 
270
- @hsbColor__ = mode.upcase == HSB
882
+ @hsbColor__ = mode == HSB
271
883
  case maxes.size
272
884
  when 1 then @colorMaxes__ = [maxes.first.to_f] * 4
273
885
  when 3, 4 then @colorMaxes__[0...maxes.size] = maxes.map &:to_f
@@ -311,8 +923,8 @@ module RubySketch
311
923
  # @return [nil] nil
312
924
  #
313
925
  def angleMode (mode)
314
- @angleScale__ = case mode
315
- when RADIANS then Utility::RAD2DEG__
926
+ @angleScale__ = case mode.upcase.to_sym
927
+ when RADIANS then RAD2DEG__
316
928
  when DEGREES then 1.0
317
929
  else raise ArgumentError, "invalid angle mode: #{mode}"
318
930
  end
@@ -320,7 +932,7 @@ module RubySketch
320
932
  end
321
933
 
322
934
  # @private
323
- private def toAngle__ (angle)
935
+ def toAngle__ (angle)
324
936
  angle * @angleScale__
325
937
  end
326
938
 
@@ -479,26 +1091,49 @@ module RubySketch
479
1091
  # Sets font.
480
1092
  #
481
1093
  # @param name [String] font name
482
- # @param size [Numeric] font size
1094
+ # @param size [Numeric] font size (max 256)
483
1095
  #
484
1096
  # @return [Font] current font
485
1097
  #
486
1098
  def textFont (name = nil, size = nil)
487
- @painter__.font name, size if name || size
1099
+ setFont__ name, size if name || size
488
1100
  Font.new @painter__.font
489
1101
  end
490
1102
 
491
1103
  # Sets text size.
492
1104
  #
493
- # @param size [Numeric] font size
1105
+ # @param size [Numeric] font size (max 256)
494
1106
  #
495
1107
  # @return [nil] nil
496
1108
  #
497
1109
  def textSize (size)
498
- @painter__.font @painter__.font.name, size
1110
+ setFont__ @painter__.font.name, size
499
1111
  nil
500
1112
  end
501
1113
 
1114
+ def textWidth (str)
1115
+ @painter__.font.width str
1116
+ end
1117
+
1118
+ def textAscent ()
1119
+ @painter__.font.ascent
1120
+ end
1121
+
1122
+ def textDescent ()
1123
+ @painter__.font.descent
1124
+ end
1125
+
1126
+ def textAlign (horizontal, vertical = BASELINE)
1127
+ @textAlignH__ = horizontal
1128
+ @textAlignV__ = vertical
1129
+ end
1130
+
1131
+ # @private
1132
+ def setFont__ (name, size)
1133
+ size = 256 if size && size > 256
1134
+ @painter__.font name, size
1135
+ end
1136
+
502
1137
  # Clears screen.
503
1138
  #
504
1139
  # @overload background(str)
@@ -728,15 +1363,35 @@ module RubySketch
728
1363
  #
729
1364
  # @overload text(str)
730
1365
  # @overload text(str, x, y)
1366
+ # @overload text(str, a, b, c, d)
731
1367
  #
732
1368
  # @param str [String] text to draw
733
1369
  # @param x [Numeric] horizontal position of the text
734
1370
  # @param y [Numeric] vertical position of the text
1371
+ # @param a [Numeric] equivalent to parameters of the rect(), see rectMode()
1372
+ # @param b [Numeric] equivalent to parameters of the rect(), see rectMode()
1373
+ # @param c [Numeric] equivalent to parameters of the rect(), see rectMode()
1374
+ # @param d [Numeric] equivalent to parameters of the rect(), see rectMode()
735
1375
  #
736
1376
  # @return [nil] nil
737
1377
  #
738
- def text (str, x, y)
1378
+ def text (str, x, y, x2 = nil, y2 = nil)
739
1379
  assertDrawing__
1380
+ if x2
1381
+ raise ArgumentError, "missing y2 parameter" unless y2
1382
+ x, y, w, h = toXYWH__ @rectMode__, x, y, x2, y2
1383
+ case @textAlignH__
1384
+ when RIGHT then x += w - @painter__.font.width(str)
1385
+ when CENTER then x += (w - @painter__.font.width(str)) / 2
1386
+ end
1387
+ case @textAlignV__
1388
+ when BOTTOM then y += h - @painter__.font.height
1389
+ when CENTER then y += (h - @painter__.font.height) / 2
1390
+ else
1391
+ end
1392
+ else
1393
+ y -= @painter__.font.ascent
1394
+ end
740
1395
  @painter__.text str, x, y
741
1396
  nil
742
1397
  end
@@ -933,12 +1588,12 @@ module RubySketch
933
1588
  end
934
1589
 
935
1590
  # @private
936
- def getInternal__ ()
1591
+ private def getInternal__ ()
937
1592
  @image__
938
1593
  end
939
1594
 
940
1595
  # @private
941
- def assertDrawing__ ()
1596
+ private def assertDrawing__ ()
942
1597
  raise "call beginDraw() before drawing" unless @drawing
943
1598
  end
944
1599
 
@@ -952,9 +1607,8 @@ module RubySketch
952
1607
  include GraphicsContext
953
1608
 
954
1609
  def initialize (width, height)
955
- setup__
956
- @image__ = Rays::Image.new width, height
957
- @painter__ = @image__.painter
1610
+ @image__ = Rays::Image.new width, height
1611
+ setup__ @image__.painter
958
1612
  end
959
1613
 
960
1614
  def beginDraw ()
@@ -972,34 +1626,247 @@ module RubySketch
972
1626
  end# Graphics
973
1627
 
974
1628
 
975
- module Utility
1629
+ # Processing context
1630
+ #
1631
+ module Context
1632
+
1633
+ include GraphicsContext, Math
1634
+
1635
+ @@context__ = nil
1636
+
1637
+ def self.context__ ()
1638
+ @@context__
1639
+ end
976
1640
 
977
1641
  # @private
978
- DEG2RAD__ = Math::PI / 180.0
1642
+ def setup__ (window)
1643
+ @@context__ = self
1644
+
1645
+ @window__ = window
1646
+ @image__ = @window__.canvas
1647
+ super @window__.canvas_painter.paint {background 0.8}
1648
+
1649
+ @loop__ = true
1650
+ @redraw__ = false
1651
+ @frameCount__ = 0
1652
+ @mousePos__ =
1653
+ @mousePrevPos__ = Rays::Point.new 0
1654
+ @mousePressed__ = false
1655
+ @touches__ = []
1656
+
1657
+ @window__.before_draw = proc {beginDraw}
1658
+ @window__.after_draw = proc {endDraw}
1659
+
1660
+ drawFrame = -> {
1661
+ @image__ = @window__.canvas
1662
+ @painter__ = @window__.canvas_painter
1663
+ begin
1664
+ push
1665
+ @drawBlock__.call if @drawBlock__
1666
+ ensure
1667
+ pop
1668
+ @frameCount__ += 1
1669
+ end
1670
+ }
1671
+
1672
+ @window__.draw = proc do |e|
1673
+ if @loop__ || @redraw__
1674
+ @redraw__ = false
1675
+ drawFrame.call
1676
+ end
1677
+ @mousePrevPos__ = @mousePos__
1678
+ end
1679
+
1680
+ updatePointerStates = -> event, pressed = nil {
1681
+ @mousePos__ = event.pos
1682
+ @mousePressed__ = pressed if pressed != nil
1683
+ @touches__ = event.positions.map {|pos| Touch.new pos.x, pos.y}
1684
+ }
1685
+
1686
+ @window__.pointer_down = proc do |e|
1687
+ updatePointerStates.call e, true
1688
+ (@touchStartedBlock__ || @mousePressedBlock__)&.call
1689
+ end
1690
+
1691
+ @window__.pointer_up = proc do |e|
1692
+ updatePointerStates.call e, false
1693
+ (@touchEndedBlock__ || @mouseReleasedBlock__)&.call
1694
+ end
1695
+
1696
+ @window__.pointer_move = proc do |e|
1697
+ updatePointerStates.call e
1698
+ (@touchMovedBlock__ || @mouseMovedBlock__)&.call
1699
+ end
1700
+
1701
+ @window__.pointer_drag = proc do |e|
1702
+ updatePointerStates.call e
1703
+ (@touchMovedBlock__ || @mouseDraggedBlock__)&.call
1704
+ end
1705
+ end
1706
+
1707
+ # Define setup block.
1708
+ #
1709
+ def setup (&block)
1710
+ @window__.setup = block
1711
+ nil
1712
+ end
1713
+
1714
+ # Define draw block.
1715
+ #
1716
+ def draw (&block)
1717
+ @drawBlock__ = block if block
1718
+ nil
1719
+ end
1720
+
1721
+ def key (&block)
1722
+ @window__.key = block
1723
+ nil
1724
+ end
1725
+
1726
+ def mousePressed (&block)
1727
+ @mousePressedBlock__ = block if block
1728
+ @mousePressed__
1729
+ end
1730
+
1731
+ def mouseReleased (&block)
1732
+ @mouseReleasedBlock__ = block if block
1733
+ nil
1734
+ end
1735
+
1736
+ def mouseMoved (&block)
1737
+ @mouseMovedBlock__ = block if block
1738
+ nil
1739
+ end
1740
+
1741
+ def mouseDragged (&block)
1742
+ @mouseDraggedBlock__ = block if block
1743
+ nil
1744
+ end
1745
+
1746
+ def touchStarted (&block)
1747
+ @touchStartedBlock__ = block if block
1748
+ nil
1749
+ end
1750
+
1751
+ def touchEnded (&block)
1752
+ @touchEndedBlock__ = block if block
1753
+ nil
1754
+ end
1755
+
1756
+ def touchMoved (&block)
1757
+ @touchMovedBlock__ = block if block
1758
+ nil
1759
+ end
979
1760
 
980
1761
  # @private
981
- RAD2DEG__ = 180.0 / Math::PI
1762
+ private def size__ (width, height)
1763
+ raise 'size() must be called on startup or setup block' if @started__
982
1764
 
983
- # Converts degree to radian.
1765
+ @painter__.__send__ :end_paint
1766
+ @window__.__send__ :reset_canvas, width, height
1767
+ @painter__.__send__ :begin_paint
1768
+
1769
+ @auto_resize__ = false
1770
+ end
1771
+
1772
+ def windowWidth ()
1773
+ @window__.width
1774
+ end
1775
+
1776
+ def windowHeight ()
1777
+ @window__.height
1778
+ end
1779
+
1780
+ # Returns number of frames since program started.
984
1781
  #
985
- # @param degree [Numeric] degree to convert
1782
+ # @return [Integer] total number of frames
986
1783
  #
987
- # @return [Numeric] radian
1784
+ def frameCount ()
1785
+ @frameCount__
1786
+ end
1787
+
1788
+ # Returns number of frames per second.
988
1789
  #
989
- def radians (degree)
990
- degree * DEG2RAD__
1790
+ # @return [Float] frames per second
1791
+ #
1792
+ def frameRate ()
1793
+ @window__.event.fps
991
1794
  end
992
1795
 
993
- # Converts radian to degree.
1796
+ # Returns pixel density
994
1797
  #
995
- # @param radian [Numeric] radian to convert
1798
+ # @return [Numeric] pixel density
996
1799
  #
997
- # @return [Numeric] degree
1800
+ def displayDensity ()
1801
+ @painter__.pixel_density
1802
+ end
1803
+
1804
+ # Returns mouse x position
998
1805
  #
999
- def degrees (radian)
1000
- radian * RAD2DEG__
1806
+ # @return [Numeric] horizontal position of mouse
1807
+ #
1808
+ def mouseX ()
1809
+ @mousePos__.x
1810
+ end
1811
+
1812
+ # Returns mouse y position
1813
+ #
1814
+ # @return [Numeric] vertical position of mouse
1815
+ #
1816
+ def mouseY ()
1817
+ @mousePos__.y
1818
+ end
1819
+
1820
+ # Returns mouse x position in previous frame
1821
+ #
1822
+ # @return [Numeric] horizontal position of mouse
1823
+ #
1824
+ def pmouseX ()
1825
+ @mousePrevPos__.x
1001
1826
  end
1002
1827
 
1828
+ # Returns mouse y position in previous frame
1829
+ #
1830
+ # @return [Numeric] vertical position of mouse
1831
+ #
1832
+ def pmouseY ()
1833
+ @mousePrevPos__.y
1834
+ end
1835
+
1836
+ # Returns array of touches
1837
+ #
1838
+ # @return [Array] Touch objects
1839
+ #
1840
+ def touches ()
1841
+ @touches__
1842
+ end
1843
+
1844
+ # Enables calling draw block on every frame.
1845
+ #
1846
+ # @return [nil] nil
1847
+ #
1848
+ def loop ()
1849
+ @loop__ = true
1850
+ end
1851
+
1852
+ # Disables calling draw block on every frame.
1853
+ #
1854
+ # @return [nil] nil
1855
+ #
1856
+ def noLoop ()
1857
+ @loop__ = false
1858
+ end
1859
+
1860
+ # Calls draw block to redraw frame.
1861
+ #
1862
+ # @return [nil] nil
1863
+ #
1864
+ def redraw ()
1865
+ @redraw__ = true
1866
+ end
1867
+
1868
+ module_function
1869
+
1003
1870
  # Returns the absolute number of the value.
1004
1871
  #
1005
1872
  # @param value [Numeric] number
@@ -1193,278 +2060,186 @@ module RubySketch
1193
2060
  value < min ? min : (value > max ? max : value)
1194
2061
  end
1195
2062
 
1196
- # Returns the perlin noise value.
1197
- #
1198
- # @overload noise(x)
1199
- # @overload noise(x, y)
1200
- # @overload noise(x, y, z)
2063
+ # Converts degree to radian.
1201
2064
  #
1202
- # @param x [Numeric] horizontal point in noise space
1203
- # @param y [Numeric] vertical point in noise space
1204
- # @param z [Numeric] depth point in noise space
2065
+ # @param degree [Numeric] degree to convert
1205
2066
  #
1206
- # @return [Numeric] noise value (0.0..1.0)
2067
+ # @return [Numeric] radian
1207
2068
  #
1208
- def noise (x, y = 0, z = 0)
1209
- Rays.perlin(x, y, z) / 2.0 + 0.5
2069
+ def radians (degree)
2070
+ degree * DEG2RAD__
1210
2071
  end
1211
2072
 
1212
- # Loads image.
2073
+ # Converts radian to degree.
1213
2074
  #
1214
- # @param filename [String] file name to load image
1215
- # @param extension [String] type of image to load (ex. 'png')
2075
+ # @param radian [Numeric] radian to convert
1216
2076
  #
1217
- # @return [Image] loaded image object
2077
+ # @return [Numeric] degree
1218
2078
  #
1219
- def loadImage (filename, extension = nil)
1220
- filename = getImage__ filename, extension if filename =~ %r|^https?://|
1221
- Image.new Rays::Image.load filename
1222
- end
1223
-
1224
- # @private
1225
- private def getImage__ (uri, ext)
1226
- ext ||= File.extname uri
1227
- raise "unsupported image type -- #{ext}" unless ext =~ /^\.?(png)$/i
1228
-
1229
- tmpdir = Pathname(Dir.tmpdir) + Digest::SHA1.hexdigest(self.class.name)
1230
- path = tmpdir + Digest::SHA1.hexdigest(uri)
1231
- path = path.sub_ext ext
1232
-
1233
- unless path.file?
1234
- URI.open uri do |input|
1235
- tmpdir.mkdir unless tmpdir.directory?
1236
- path.open('w') do |output|
1237
- while buf = input.read(2 ** 16)
1238
- output.write buf
1239
- end
1240
- end
1241
- end
1242
- end
1243
- path.to_s
1244
- end
1245
-
1246
- def createGraphics (width, height)
1247
- Graphics.new width, height
1248
- end
1249
-
1250
- end# Utility
1251
-
1252
-
1253
- # Processing context
1254
- #
1255
- module Context
1256
-
1257
- include GraphicsContext, Utility, Math
1258
-
1259
- # @private
1260
- def setup__ (window)
1261
- super()
1262
- @loop__ = true
1263
- @redraw__ = false
1264
- @frameCount__ = 0
1265
- @mouseX__ =
1266
- @mouseY__ =
1267
- @mousePrevX__ =
1268
- @mousePrevY__ = 0
1269
- @mousePressed__ = false
1270
-
1271
- @window__ = window
1272
- @image__ = @window__.canvas
1273
- @painter__ = @window__.canvas_painter
1274
-
1275
- @painter__.miter_limit = 10
1276
-
1277
- drawFrame = -> event {
1278
- @image__ = @window__.canvas
1279
- @painter__ = @window__.canvas_painter
1280
- begin
1281
- push
1282
- @drawBlock__.call event if @drawBlock__
1283
- ensure
1284
- pop
1285
- @frameCount__ += 1
1286
- end
1287
- }
1288
-
1289
- updateMouseState = -> x, y, pressed = nil {
1290
- @mouseX__ = x
1291
- @mouseY__ = y
1292
- @mousePressed__ = pressed if pressed != nil
1293
- }
1294
-
1295
- updateMousePrevPos = -> {
1296
- @mousePrevX__ = @mouseX__
1297
- @mousePrevY__ = @mouseY__
1298
- }
1299
-
1300
- @window__.before_draw = proc {beginDraw}
1301
- @window__.after_draw = proc {endDraw}
1302
-
1303
- @window__.draw = proc do |e|
1304
- if @loop__ || @redraw__
1305
- @redraw__ = false
1306
- drawFrame.call e
1307
- end
1308
- updateMousePrevPos.call
1309
- end
1310
-
1311
- @window__.pointer_down = proc do |e|
1312
- updateMouseState.call e.x, e.y, true
1313
- @mousePressedBlock__.call e if @mousePressedBlock__
1314
- end
1315
-
1316
- @window__.pointer_up = proc do |e|
1317
- updateMouseState.call e.x, e.y, false
1318
- @mouseReleasedBlock__.call e if @mouseReleasedBlock__
1319
- end
1320
-
1321
- @window__.pointer_move = proc do |e|
1322
- updateMouseState.call e.x, e.y
1323
- @mouseMovedBlock__.call e if @mouseMovedBlock__
1324
- end
1325
-
1326
- @window__.pointer_drag = proc do |e|
1327
- updateMouseState.call e.x, e.y
1328
- @mouseDraggedBlock__.call e if @mouseDraggedBlock__
1329
- end
2079
+ def degrees (radian)
2080
+ radian * RAD2DEG__
1330
2081
  end
1331
2082
 
1332
- # Define setup block.
2083
+ # Returns the sine of an angle.
1333
2084
  #
1334
- def setup (&block)
1335
- @window__.setup = block
1336
- nil
1337
- end
1338
-
1339
- # Define draw block.
2085
+ # @param angle [Numeric] angle in radians
1340
2086
  #
1341
- def draw (&block)
1342
- @drawBlock__ = block if block
1343
- nil
1344
- end
1345
-
1346
- def key (&block)
1347
- @window__.key = block
1348
- nil
1349
- end
1350
-
1351
- def mousePressed (&block)
1352
- @mousePressedBlock__ = block if block
1353
- @mousePressed__
1354
- end
1355
-
1356
- def mouseReleased (&block)
1357
- @mouseReleasedBlock__ = block if block
1358
- nil
1359
- end
1360
-
1361
- def mouseMoved (&block)
1362
- @mouseMovedBlock__ = block if block
1363
- nil
1364
- end
1365
-
1366
- def mouseDragged (&block)
1367
- @mouseDraggedBlock__ = block if block
1368
- nil
1369
- end
1370
-
1371
- # @private
1372
- private def size__ (width, height)
1373
- raise 'size() must be called on startup or setup block' if @started__
1374
-
1375
- @painter__.__send__ :end_paint
1376
- @window__.__send__ :reset_canvas, width, height
1377
- @painter__.__send__ :begin_paint
1378
-
1379
- @auto_resize__ = false
1380
- end
1381
-
1382
- def windowWidth ()
1383
- @window__.width
2087
+ # @return [Numeric] the sine
2088
+ #
2089
+ def sin (angle)
2090
+ Math.sin angle
1384
2091
  end
1385
2092
 
1386
- def windowHeight ()
1387
- @window__.height
2093
+ # Returns the cosine of an angle.
2094
+ #
2095
+ # @param angle [Numeric] angle in radians
2096
+ #
2097
+ # @return [Numeric] the cosine
2098
+ #
2099
+ def cos (angle)
2100
+ Math.cos angle
1388
2101
  end
1389
2102
 
1390
- # Returns number of frames since program started.
2103
+ # Returns the ratio of the sine and cosine of an angle.
1391
2104
  #
1392
- # @return [Integer] total number of frames
2105
+ # @param angle [Numeric] angle in radians
1393
2106
  #
1394
- def frameCount ()
1395
- @frameCount__
2107
+ # @return [Numeric] the tangent
2108
+ #
2109
+ def tan (angle)
2110
+ Math.tan angle
1396
2111
  end
1397
2112
 
1398
- # Returns number of frames per second.
2113
+ # Returns the inverse of sin().
1399
2114
  #
1400
- # @return [Float] frames per second
2115
+ # @param value [Numeric] value for calculation
1401
2116
  #
1402
- def frameRate ()
1403
- @window__.event.fps
2117
+ # @return [Numeric] the arc sine
2118
+ #
2119
+ def asin (value)
2120
+ Math.asin value
1404
2121
  end
1405
2122
 
1406
- # Returns pixel density
2123
+ # Returns the inverse of cos().
1407
2124
  #
1408
- # @return [Numeric] pixel density
2125
+ # @param value [Numeric] value for calculation
1409
2126
  #
1410
- def displayDensity ()
1411
- @painter__.pixel_density
2127
+ # @return [Numeric] the arc cosine
2128
+ #
2129
+ def acos (value)
2130
+ Math.acos value
1412
2131
  end
1413
2132
 
1414
- # Returns mouse x position
2133
+ # Returns the inverse of tan().
1415
2134
  #
1416
- # @return [Numeric] horizontal position of mouse
2135
+ # @param value [Numeric] value for valculation
1417
2136
  #
1418
- def mouseX ()
1419
- @mouseX__
2137
+ # @return [Numeric] the arc tangent
2138
+ #
2139
+ def atan (value)
2140
+ Math.atan value
1420
2141
  end
1421
2142
 
1422
- # Returns mouse y position
2143
+ # Returns the angle from a specified point.
1423
2144
  #
1424
- # @return [Numeric] vertical position of mouse
2145
+ # @param y [Numeric] y of the point
2146
+ # @param x [Numeric] x of the point
1425
2147
  #
1426
- def mouseY ()
1427
- @mouseY__
2148
+ # @return [Numeric] the angle in radians
2149
+ #
2150
+ def atan2 (y, x)
2151
+ Math.atan2 y, x
1428
2152
  end
1429
2153
 
1430
- # Returns mouse x position in previous frame
2154
+ # Returns the perlin noise value.
1431
2155
  #
1432
- # @return [Numeric] horizontal position of mouse
2156
+ # @overload noise(x)
2157
+ # @overload noise(x, y)
2158
+ # @overload noise(x, y, z)
1433
2159
  #
1434
- def pmouseX ()
1435
- @mousePrevX__
2160
+ # @param x [Numeric] horizontal point in noise space
2161
+ # @param y [Numeric] vertical point in noise space
2162
+ # @param z [Numeric] depth point in noise space
2163
+ #
2164
+ # @return [Numeric] noise value (0.0..1.0)
2165
+ #
2166
+ def noise (x, y = 0, z = 0)
2167
+ Rays.perlin(x, y, z) / 2.0 + 0.5
1436
2168
  end
1437
2169
 
1438
- # Returns mouse y position in previous frame
2170
+ # Returns a random number in range low...high
1439
2171
  #
1440
- # @return [Numeric] vertical position of mouse
2172
+ # @overload random(high)
2173
+ # @overload random(low, high)
1441
2174
  #
1442
- def pmouseY ()
1443
- @mousePrevY__
2175
+ # @param low [Numeric] lower limit
2176
+ # @param high [Numeric] upper limit
2177
+ #
2178
+ # @return [Float] random number
2179
+ #
2180
+ def random (low = nil, high)
2181
+ rand (low || 0).to_f...high.to_f
1444
2182
  end
1445
2183
 
1446
- # Enables calling draw block on every frame.
2184
+ # Creates a new vector.
1447
2185
  #
1448
- # @return [nil] nil
2186
+ # @overload createVector()
2187
+ # @overload createVector(x, y)
2188
+ # @overload createVector(x, y, z)
1449
2189
  #
1450
- def loop ()
1451
- @loop__ = true
2190
+ # @param x [Numeric] x of new vector
2191
+ # @param y [Numeric] y of new vector
2192
+ # @param z [Numeric] z of new vector
2193
+ #
2194
+ # @return [Vector] new vector
2195
+ #
2196
+ def createVector (*args)
2197
+ Vector.new *args
1452
2198
  end
1453
2199
 
1454
- # Disables calling draw block on every frame.
2200
+ # Creates a new off-screen graphics context object.
1455
2201
  #
1456
- # @return [nil] nil
2202
+ # @param width [Numeric] width of graphics image
2203
+ # @param height [Numeric] height of graphics image
1457
2204
  #
1458
- def noLoop ()
1459
- @loop__ = false
2205
+ # @return [Graphics] graphics object
2206
+ #
2207
+ def createGraphics (width, height)
2208
+ Graphics.new width, height
1460
2209
  end
1461
2210
 
1462
- # Calls draw block to redraw frame.
2211
+ # Loads image.
1463
2212
  #
1464
- # @return [nil] nil
2213
+ # @param filename [String] file name to load image
2214
+ # @param extension [String] type of image to load (ex. 'png')
1465
2215
  #
1466
- def redraw ()
1467
- @redraw__ = true
2216
+ # @return [Image] loaded image object
2217
+ #
2218
+ def loadImage (filename, extension = nil)
2219
+ filename = getImage__ filename, extension if filename =~ %r|^https?://|
2220
+ Image.new Rays::Image.load filename
2221
+ end
2222
+
2223
+ # @private
2224
+ private def getImage__ (uri, ext)
2225
+ ext ||= File.extname uri
2226
+ raise "unsupported image type -- #{ext}" unless ext =~ /^\.?(png)$/i
2227
+
2228
+ tmpdir = Pathname(Dir.tmpdir) + Digest::SHA1.hexdigest(self.class.name)
2229
+ path = tmpdir + Digest::SHA1.hexdigest(uri)
2230
+ path = path.sub_ext ext
2231
+
2232
+ unless path.file?
2233
+ URI.open uri do |input|
2234
+ tmpdir.mkdir unless tmpdir.directory?
2235
+ path.open('w') do |output|
2236
+ while buf = input.read(2 ** 16)
2237
+ output.write buf
2238
+ end
2239
+ end
2240
+ end
2241
+ end
2242
+ path.to_s
1468
2243
  end
1469
2244
 
1470
2245
  end# Context