rubysketch 0.3.1 → 0.3.6

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: 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