rubysketch 0.3.1 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f63f771b469d060307fa88a2992cc373c2439cec8facf531984533303f0a023
4
- data.tar.gz: 5787db4cf63408b746fb538a6a612c2b90f440e08c1ded38b382b69200d372c9
3
+ metadata.gz: 1a40d65c055cc2baacd0a7489ec511a0db37b8e534f58fc02d5c095f78ecca66
4
+ data.tar.gz: 9c8634c610e0df8201655809b82bc8e7dbc2adab8cad405e2033ecc321c09137
5
5
  SHA512:
6
- metadata.gz: 1bcb9bfe5d0f1732c7e44a509d8c5e83b5b84f28bb988fe3e4d9083cb342b6fc4cb44df48c0f176a18599cfd334583e808db41dadb377ac5c78436ed55533c29
7
- data.tar.gz: ac78631d29b3843a32f376b7330011477523e33f40b1adb5d40dc1a66335bc294fdf91720146194b016497e4444b9531dbdc9529723c936c939c518df343c671
6
+ metadata.gz: 04d5e9096e7cef9ea5d6c16e3397d5965bc8da07f699fc3b241e91ad982c755fe7b4faf4296b6ce74612da690cc7d7cfd507612387f43276b0e2ab0d05566ddf
7
+ data.tar.gz: 224f32277392e5b84c84b6ef13a437813859f960e47dce696f97dd547273d0d86a3e62685a171a7055981989fd99679e60b843e12b839bc2b501c4e9fbb7e622
@@ -0,0 +1,62 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ['v[0-9]*']
6
+
7
+ jobs:
8
+ release:
9
+ runs-on: macos-latest
10
+
11
+ steps:
12
+ - name: checkout
13
+ uses: actions/checkout@v2
14
+
15
+ - name: ruby 2.6
16
+ uses: actions/setup-ruby@v1
17
+ with:
18
+ ruby-version: 2.6.x
19
+
20
+ - name: install gems
21
+ run: |
22
+ gem install bundler
23
+ bundle install --jobs 4 --retry 3
24
+
25
+ - name: version
26
+ id: version
27
+ run: |
28
+ echo ::set-output name=value::$(ruby -e 'print "${{ github.ref }}"[/\/v([\w\.\-]+)/, 1]')
29
+
30
+ - name: create gem
31
+ run: rake clean gem
32
+
33
+ - name: create release
34
+ id: create_release
35
+ uses: actions/create-release@v1
36
+ env:
37
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38
+ with:
39
+ tag_name: ${{ github.ref }}
40
+ release_name: ${{ github.ref }}
41
+ draft: false
42
+ prerelease: false
43
+
44
+ - name: upload to releases
45
+ uses: actions/upload-release-asset@v1
46
+ env:
47
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48
+ with:
49
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
50
+ asset_path: ./rubysketch-${{ steps.version.outputs.value }}.gem
51
+ asset_name: rubysketch-${{ steps.version.outputs.value }}.gem
52
+ asset_content_type: application/zip
53
+
54
+ - name: upload to rubygems
55
+ env:
56
+ GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_AUTH_TOKEN }}
57
+ run: |
58
+ mkdir -p $HOME/.gem
59
+ touch $HOME/.gem/credentials
60
+ chmod 0600 $HOME/.gem/credentials
61
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
62
+ rake upload
@@ -0,0 +1,27 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: macos-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+
16
+ - name: ruby 2.6
17
+ uses: actions/setup-ruby@v1
18
+ with:
19
+ ruby-version: 2.6.x
20
+
21
+ - name: install gems
22
+ run: |
23
+ gem install bundler
24
+ bundle install --jobs 4 --retry 3
25
+
26
+ - name: test
27
+ run: rake test
@@ -1,6 +1,38 @@
1
1
  # RubySketch ChangeLog
2
2
 
3
3
 
4
+ ## [0.3.6] - 2020-08-02
5
+
6
+ - random() can take array or nothing
7
+ - use github actions to release gem package
8
+
9
+
10
+ ## [0.3.5] - 2020-08-02
11
+
12
+ - add random()
13
+ - add sin(), cos(), tan(), asin(), acos(), atan() and atan2()
14
+ - make Vector class accessible from user script context
15
+ - fix error on calling rotate()
16
+
17
+
18
+ ## [0.3.4] - 2020-08-02
19
+
20
+ - delete Utility module
21
+
22
+
23
+ ## [0.3.3] - 2020-08-01
24
+
25
+ - add Vector class
26
+
27
+
28
+ ## [0.3.2] - 2020-07-22
29
+
30
+ - text() draws to the baseline by default
31
+ - add textWidth(), textAscent(), textDescent() and textAlign()
32
+ - change initial color for fill() and stroke()
33
+ - change initial background color to grayscale 0.8
34
+
35
+
4
36
  ## [0.3.1] - 2020-07-17
5
37
 
6
38
  - add touchStarted(), touchEnded(), touchMoved() and touches()
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'yard'
4
+ gem 'reflexion'
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.1
1
+ 0.3.6
@@ -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
@@ -171,6 +732,8 @@ module RubySketch
171
732
  #
172
733
  module GraphicsContext
173
734
 
735
+ Vector = Processing::Vector
736
+
174
737
  # PI / 2
175
738
  #
176
739
  HALF_PI = Math::PI / 2
@@ -211,7 +774,7 @@ module RubySketch
211
774
  #
212
775
  CORNERS = :CORNERS
213
776
 
214
- # Mode for rectMode(), ellipseMode() and imageMode().
777
+ # Mode for rectMode(), ellipseMode(), imageMode() and textAlign().
215
778
  #
216
779
  CENTER = :CENTER
217
780
 
@@ -219,6 +782,21 @@ module RubySketch
219
782
  #
220
783
  RADIUS = :RADIUS
221
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
+
222
800
  # Mode for strokeCap().
223
801
  #
224
802
  BUTT = :butt
@@ -235,7 +813,10 @@ module RubySketch
235
813
  #
236
814
  SQUARE = :square
237
815
 
238
- def setup__ ()
816
+ def setup__ (painter)
817
+ @painter__ = painter
818
+ @painter__.miter_limit = 10
819
+
239
820
  @drawing = false
240
821
  @hsbColor__ = false
241
822
  @colorMaxes__ = [1.0] * 4
@@ -243,6 +824,8 @@ module RubySketch
243
824
  @rectMode__ = nil
244
825
  @ellipseMode__ = nil
245
826
  @imageMode__ = nil
827
+ @textAlignH__ = nil
828
+ @textAlignV__ = nil
246
829
  @matrixStack__ = []
247
830
  @styleStack__ = []
248
831
 
@@ -251,6 +834,10 @@ module RubySketch
251
834
  rectMode CORNER
252
835
  ellipseMode CENTER
253
836
  imageMode CORNER
837
+ textAlign LEFT
838
+
839
+ fill 255
840
+ stroke 0
254
841
  end
255
842
 
256
843
  def beginDraw ()
@@ -288,10 +875,11 @@ module RubySketch
288
875
  # @return [nil] nil
289
876
  #
290
877
  def colorMode (mode, *maxes)
878
+ mode = mode.upcase.to_sym
291
879
  raise ArgumentError, "invalid color mode: #{mode}" unless [RGB, HSB].include?(mode)
292
880
  raise ArgumentError unless [0, 1, 3, 4].include?(maxes.size)
293
881
 
294
- @hsbColor__ = mode.upcase == HSB
882
+ @hsbColor__ = mode == HSB
295
883
  case maxes.size
296
884
  when 1 then @colorMaxes__ = [maxes.first.to_f] * 4
297
885
  when 3, 4 then @colorMaxes__[0...maxes.size] = maxes.map &:to_f
@@ -335,8 +923,8 @@ module RubySketch
335
923
  # @return [nil] nil
336
924
  #
337
925
  def angleMode (mode)
338
- @angleScale__ = case mode
339
- when RADIANS then Utility::RAD2DEG__
926
+ @angleScale__ = case mode.upcase.to_sym
927
+ when RADIANS then RAD2DEG__
340
928
  when DEGREES then 1.0
341
929
  else raise ArgumentError, "invalid angle mode: #{mode}"
342
930
  end
@@ -344,7 +932,7 @@ module RubySketch
344
932
  end
345
933
 
346
934
  # @private
347
- private def toAngle__ (angle)
935
+ def toAngle__ (angle)
348
936
  angle * @angleScale__
349
937
  end
350
938
 
@@ -523,6 +1111,23 @@ module RubySketch
523
1111
  nil
524
1112
  end
525
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
+
526
1131
  # @private
527
1132
  def setFont__ (name, size)
528
1133
  size = 256 if size && size > 256
@@ -758,15 +1363,35 @@ module RubySketch
758
1363
  #
759
1364
  # @overload text(str)
760
1365
  # @overload text(str, x, y)
1366
+ # @overload text(str, a, b, c, d)
761
1367
  #
762
1368
  # @param str [String] text to draw
763
1369
  # @param x [Numeric] horizontal position of the text
764
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()
765
1375
  #
766
1376
  # @return [nil] nil
767
1377
  #
768
- def text (str, x, y)
1378
+ def text (str, x, y, x2 = nil, y2 = nil)
769
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
770
1395
  @painter__.text str, x, y
771
1396
  nil
772
1397
  end
@@ -963,12 +1588,12 @@ module RubySketch
963
1588
  end
964
1589
 
965
1590
  # @private
966
- def getInternal__ ()
1591
+ private def getInternal__ ()
967
1592
  @image__
968
1593
  end
969
1594
 
970
1595
  # @private
971
- def assertDrawing__ ()
1596
+ private def assertDrawing__ ()
972
1597
  raise "call beginDraw() before drawing" unless @drawing
973
1598
  end
974
1599
 
@@ -982,9 +1607,8 @@ module RubySketch
982
1607
  include GraphicsContext
983
1608
 
984
1609
  def initialize (width, height)
985
- setup__
986
- @image__ = Rays::Image.new width, height
987
- @painter__ = @image__.painter
1610
+ @image__ = Rays::Image.new width, height
1611
+ setup__ @image__.painter
988
1612
  end
989
1613
 
990
1614
  def beginDraw ()
@@ -1002,34 +1626,247 @@ module RubySketch
1002
1626
  end# Graphics
1003
1627
 
1004
1628
 
1005
- module Utility
1006
-
1007
- # @private
1008
- DEG2RAD__ = Math::PI / 180.0
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
1009
1640
 
1010
1641
  # @private
1011
- RAD2DEG__ = 180.0 / Math::PI
1642
+ def setup__ (window)
1643
+ @@context__ = self
1012
1644
 
1013
- # Converts degree to radian.
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.
1014
1708
  #
1015
- # @param degree [Numeric] degree to convert
1709
+ def setup (&block)
1710
+ @window__.setup = block
1711
+ nil
1712
+ end
1713
+
1714
+ # Define draw block.
1016
1715
  #
1017
- # @return [Numeric] radian
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
1760
+
1761
+ # @private
1762
+ private def size__ (width, height)
1763
+ raise 'size() must be called on startup or setup block' if @started__
1764
+
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.
1018
1781
  #
1019
- def radians (degree)
1020
- degree * DEG2RAD__
1782
+ # @return [Integer] total number of frames
1783
+ #
1784
+ def frameCount ()
1785
+ @frameCount__
1021
1786
  end
1022
1787
 
1023
- # Converts radian to degree.
1788
+ # Returns number of frames per second.
1024
1789
  #
1025
- # @param radian [Numeric] radian to convert
1790
+ # @return [Float] frames per second
1026
1791
  #
1027
- # @return [Numeric] degree
1792
+ def frameRate ()
1793
+ @window__.event.fps
1794
+ end
1795
+
1796
+ # Returns pixel density
1028
1797
  #
1029
- def degrees (radian)
1030
- radian * RAD2DEG__
1798
+ # @return [Numeric] pixel density
1799
+ #
1800
+ def displayDensity ()
1801
+ @painter__.pixel_density
1802
+ end
1803
+
1804
+ # Returns mouse x position
1805
+ #
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
1826
+ end
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
1031
1866
  end
1032
1867
 
1868
+ module_function
1869
+
1033
1870
  # Returns the absolute number of the value.
1034
1871
  #
1035
1872
  # @param value [Numeric] number
@@ -1223,295 +2060,191 @@ module RubySketch
1223
2060
  value < min ? min : (value > max ? max : value)
1224
2061
  end
1225
2062
 
1226
- # Returns the perlin noise value.
1227
- #
1228
- # @overload noise(x)
1229
- # @overload noise(x, y)
1230
- # @overload noise(x, y, z)
2063
+ # Converts degree to radian.
1231
2064
  #
1232
- # @param x [Numeric] horizontal point in noise space
1233
- # @param y [Numeric] vertical point in noise space
1234
- # @param z [Numeric] depth point in noise space
2065
+ # @param degree [Numeric] degree to convert
1235
2066
  #
1236
- # @return [Numeric] noise value (0.0..1.0)
2067
+ # @return [Numeric] radian
1237
2068
  #
1238
- def noise (x, y = 0, z = 0)
1239
- Rays.perlin(x, y, z) / 2.0 + 0.5
2069
+ def radians (degree)
2070
+ degree * DEG2RAD__
1240
2071
  end
1241
2072
 
1242
- # Loads image.
2073
+ # Converts radian to degree.
1243
2074
  #
1244
- # @param filename [String] file name to load image
1245
- # @param extension [String] type of image to load (ex. 'png')
2075
+ # @param radian [Numeric] radian to convert
1246
2076
  #
1247
- # @return [Image] loaded image object
2077
+ # @return [Numeric] degree
1248
2078
  #
1249
- def loadImage (filename, extension = nil)
1250
- filename = getImage__ filename, extension if filename =~ %r|^https?://|
1251
- Image.new Rays::Image.load filename
1252
- end
1253
-
1254
- # @private
1255
- private def getImage__ (uri, ext)
1256
- ext ||= File.extname uri
1257
- raise "unsupported image type -- #{ext}" unless ext =~ /^\.?(png)$/i
1258
-
1259
- tmpdir = Pathname(Dir.tmpdir) + Digest::SHA1.hexdigest(self.class.name)
1260
- path = tmpdir + Digest::SHA1.hexdigest(uri)
1261
- path = path.sub_ext ext
1262
-
1263
- unless path.file?
1264
- URI.open uri do |input|
1265
- tmpdir.mkdir unless tmpdir.directory?
1266
- path.open('w') do |output|
1267
- while buf = input.read(2 ** 16)
1268
- output.write buf
1269
- end
1270
- end
1271
- end
1272
- end
1273
- path.to_s
1274
- end
1275
-
1276
- def createGraphics (width, height)
1277
- Graphics.new width, height
1278
- end
1279
-
1280
- end# Utility
1281
-
1282
-
1283
- # Processing context
1284
- #
1285
- module Context
1286
-
1287
- include GraphicsContext, Utility, Math
1288
-
1289
- # @private
1290
- def setup__ (window)
1291
- super()
1292
- @loop__ = true
1293
- @redraw__ = false
1294
- @frameCount__ = 0
1295
- @mousePos__ =
1296
- @mousePrevPos__ = Rays::Point.new 0
1297
- @mousePressed__ = false
1298
- @touches__ = []
1299
-
1300
- @window__ = window
1301
- @image__ = @window__.canvas
1302
- @painter__ = @window__.canvas_painter
1303
-
1304
- @painter__.miter_limit = 10
1305
-
1306
- @window__.before_draw = proc {beginDraw}
1307
- @window__.after_draw = proc {endDraw}
1308
-
1309
- drawFrame = -> {
1310
- @image__ = @window__.canvas
1311
- @painter__ = @window__.canvas_painter
1312
- begin
1313
- push
1314
- @drawBlock__.call if @drawBlock__
1315
- ensure
1316
- pop
1317
- @frameCount__ += 1
1318
- end
1319
- }
1320
-
1321
- @window__.draw = proc do |e|
1322
- if @loop__ || @redraw__
1323
- @redraw__ = false
1324
- drawFrame.call
1325
- end
1326
- @mousePrevPos__ = @mousePos__
1327
- end
1328
-
1329
- updatePointerStates = -> event, pressed = nil {
1330
- @mousePos__ = event.pos
1331
- @mousePressed__ = pressed if pressed != nil
1332
- @touches__ = event.positions.map {|pos| Touch.new pos.x, pos.y}
1333
- }
1334
-
1335
- @window__.pointer_down = proc do |e|
1336
- updatePointerStates.call e, true
1337
- (@touchStartedBlock__ || @mousePressedBlock__)&.call
1338
- end
1339
-
1340
- @window__.pointer_up = proc do |e|
1341
- updatePointerStates.call e, false
1342
- (@touchEndedBlock__ || @mouseReleasedBlock__)&.call
1343
- end
1344
-
1345
- @window__.pointer_move = proc do |e|
1346
- updatePointerStates.call e
1347
- (@touchMovedBlock__ || @mouseMovedBlock__)&.call
1348
- end
1349
-
1350
- @window__.pointer_drag = proc do |e|
1351
- updatePointerStates.call e
1352
- (@touchMovedBlock__ || @mouseDraggedBlock__)&.call
1353
- end
2079
+ def degrees (radian)
2080
+ radian * RAD2DEG__
1354
2081
  end
1355
2082
 
1356
- # Define setup block.
2083
+ # Returns the sine of an angle.
1357
2084
  #
1358
- def setup (&block)
1359
- @window__.setup = block
1360
- nil
1361
- end
1362
-
1363
- # Define draw block.
2085
+ # @param angle [Numeric] angle in radians
1364
2086
  #
1365
- def draw (&block)
1366
- @drawBlock__ = block if block
1367
- nil
1368
- end
1369
-
1370
- def key (&block)
1371
- @window__.key = block
1372
- nil
1373
- end
1374
-
1375
- def mousePressed (&block)
1376
- @mousePressedBlock__ = block if block
1377
- @mousePressed__
1378
- end
1379
-
1380
- def mouseReleased (&block)
1381
- @mouseReleasedBlock__ = block if block
1382
- nil
1383
- end
1384
-
1385
- def mouseMoved (&block)
1386
- @mouseMovedBlock__ = block if block
1387
- nil
1388
- end
1389
-
1390
- def mouseDragged (&block)
1391
- @mouseDraggedBlock__ = block if block
1392
- nil
1393
- end
1394
-
1395
- def touchStarted (&block)
1396
- @touchStartedBlock__ = block if block
1397
- nil
1398
- end
1399
-
1400
- def touchEnded (&block)
1401
- @touchEndedBlock__ = block if block
1402
- nil
1403
- end
1404
-
1405
- def touchMoved (&block)
1406
- @touchMovedBlock__ = block if block
1407
- nil
1408
- end
1409
-
1410
- # @private
1411
- private def size__ (width, height)
1412
- raise 'size() must be called on startup or setup block' if @started__
1413
-
1414
- @painter__.__send__ :end_paint
1415
- @window__.__send__ :reset_canvas, width, height
1416
- @painter__.__send__ :begin_paint
1417
-
1418
- @auto_resize__ = false
1419
- end
1420
-
1421
- def windowWidth ()
1422
- @window__.width
1423
- end
1424
-
1425
- def windowHeight ()
1426
- @window__.height
2087
+ # @return [Numeric] the sine
2088
+ #
2089
+ def sin (angle)
2090
+ Math.sin angle
1427
2091
  end
1428
2092
 
1429
- # Returns number of frames since program started.
2093
+ # Returns the cosine of an angle.
1430
2094
  #
1431
- # @return [Integer] total number of frames
2095
+ # @param angle [Numeric] angle in radians
1432
2096
  #
1433
- def frameCount ()
1434
- @frameCount__
2097
+ # @return [Numeric] the cosine
2098
+ #
2099
+ def cos (angle)
2100
+ Math.cos angle
1435
2101
  end
1436
2102
 
1437
- # Returns number of frames per second.
2103
+ # Returns the ratio of the sine and cosine of an angle.
1438
2104
  #
1439
- # @return [Float] frames per second
2105
+ # @param angle [Numeric] angle in radians
1440
2106
  #
1441
- def frameRate ()
1442
- @window__.event.fps
2107
+ # @return [Numeric] the tangent
2108
+ #
2109
+ def tan (angle)
2110
+ Math.tan angle
1443
2111
  end
1444
2112
 
1445
- # Returns pixel density
2113
+ # Returns the inverse of sin().
1446
2114
  #
1447
- # @return [Numeric] pixel density
2115
+ # @param value [Numeric] value for calculation
1448
2116
  #
1449
- def displayDensity ()
1450
- @painter__.pixel_density
2117
+ # @return [Numeric] the arc sine
2118
+ #
2119
+ def asin (value)
2120
+ Math.asin value
1451
2121
  end
1452
2122
 
1453
- # Returns mouse x position
2123
+ # Returns the inverse of cos().
1454
2124
  #
1455
- # @return [Numeric] horizontal position of mouse
2125
+ # @param value [Numeric] value for calculation
1456
2126
  #
1457
- def mouseX ()
1458
- @mousePos__.x
2127
+ # @return [Numeric] the arc cosine
2128
+ #
2129
+ def acos (value)
2130
+ Math.acos value
1459
2131
  end
1460
2132
 
1461
- # Returns mouse y position
2133
+ # Returns the inverse of tan().
1462
2134
  #
1463
- # @return [Numeric] vertical position of mouse
2135
+ # @param value [Numeric] value for valculation
1464
2136
  #
1465
- def mouseY ()
1466
- @mousePos__.y
2137
+ # @return [Numeric] the arc tangent
2138
+ #
2139
+ def atan (value)
2140
+ Math.atan value
1467
2141
  end
1468
2142
 
1469
- # Returns mouse x position in previous frame
2143
+ # Returns the angle from a specified point.
1470
2144
  #
1471
- # @return [Numeric] horizontal position of mouse
2145
+ # @param y [Numeric] y of the point
2146
+ # @param x [Numeric] x of the point
1472
2147
  #
1473
- def pmouseX ()
1474
- @mousePrevPos__.x
2148
+ # @return [Numeric] the angle in radians
2149
+ #
2150
+ def atan2 (y, x)
2151
+ Math.atan2 y, x
1475
2152
  end
1476
2153
 
1477
- # Returns mouse y position in previous frame
2154
+ # Returns the perlin noise value.
1478
2155
  #
1479
- # @return [Numeric] vertical position of mouse
2156
+ # @overload noise(x)
2157
+ # @overload noise(x, y)
2158
+ # @overload noise(x, y, z)
1480
2159
  #
1481
- def pmouseY ()
1482
- @mousePrevPos__.y
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
1483
2168
  end
1484
2169
 
1485
- # Returns array of touches
2170
+ # Returns a random number in range low...high
1486
2171
  #
1487
- # @return [Array] Touch objects
2172
+ # @overload random()
2173
+ # @overload random(high)
2174
+ # @overload random(low, high)
2175
+ # @overload random(choices)
1488
2176
  #
1489
- def touches ()
1490
- @touches__
2177
+ # @param low [Numeric] lower limit
2178
+ # @param high [Numeric] upper limit
2179
+ # @param choices [Array] array to choose from
2180
+ #
2181
+ # @return [Float] random number
2182
+ #
2183
+ def random (*args)
2184
+ return args.first.sample if args.first.kind_of? Array
2185
+ high, low = args.reverse
2186
+ rand (low || 0).to_f...(high || 1).to_f
1491
2187
  end
1492
2188
 
1493
- # Enables calling draw block on every frame.
2189
+ # Creates a new vector.
1494
2190
  #
1495
- # @return [nil] nil
2191
+ # @overload createVector()
2192
+ # @overload createVector(x, y)
2193
+ # @overload createVector(x, y, z)
1496
2194
  #
1497
- def loop ()
1498
- @loop__ = true
2195
+ # @param x [Numeric] x of new vector
2196
+ # @param y [Numeric] y of new vector
2197
+ # @param z [Numeric] z of new vector
2198
+ #
2199
+ # @return [Vector] new vector
2200
+ #
2201
+ def createVector (*args)
2202
+ Vector.new *args
1499
2203
  end
1500
2204
 
1501
- # Disables calling draw block on every frame.
2205
+ # Creates a new off-screen graphics context object.
1502
2206
  #
1503
- # @return [nil] nil
2207
+ # @param width [Numeric] width of graphics image
2208
+ # @param height [Numeric] height of graphics image
1504
2209
  #
1505
- def noLoop ()
1506
- @loop__ = false
2210
+ # @return [Graphics] graphics object
2211
+ #
2212
+ def createGraphics (width, height)
2213
+ Graphics.new width, height
1507
2214
  end
1508
2215
 
1509
- # Calls draw block to redraw frame.
2216
+ # Loads image.
1510
2217
  #
1511
- # @return [nil] nil
2218
+ # @param filename [String] file name to load image
2219
+ # @param extension [String] type of image to load (ex. 'png')
1512
2220
  #
1513
- def redraw ()
1514
- @redraw__ = true
2221
+ # @return [Image] loaded image object
2222
+ #
2223
+ def loadImage (filename, extension = nil)
2224
+ filename = getImage__ filename, extension if filename =~ %r|^https?://|
2225
+ Image.new Rays::Image.load filename
2226
+ end
2227
+
2228
+ # @private
2229
+ private def getImage__ (uri, ext)
2230
+ ext ||= File.extname uri
2231
+ raise "unsupported image type -- #{ext}" unless ext =~ /^\.?(png)$/i
2232
+
2233
+ tmpdir = Pathname(Dir.tmpdir) + Digest::SHA1.hexdigest(self.class.name)
2234
+ path = tmpdir + Digest::SHA1.hexdigest(uri)
2235
+ path = path.sub_ext ext
2236
+
2237
+ unless path.file?
2238
+ URI.open uri do |input|
2239
+ tmpdir.mkdir unless tmpdir.directory?
2240
+ path.open('w') do |output|
2241
+ while buf = input.read(2 ** 16)
2242
+ output.write buf
2243
+ end
2244
+ end
2245
+ end
2246
+ end
2247
+ path.to_s
1515
2248
  end
1516
2249
 
1517
2250
  end# Context