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 +4 -4
- data/.github/workflows/release.yml +62 -0
- data/.github/workflows/test.yml +27 -0
- data/ChangeLog.md +32 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/rubysketch/processing.rb +1001 -268
- data/rubysketch.gemspec +0 -8
- data/test/helper.rb +24 -0
- data/test/processing/test_utility.rb +34 -0
- data/test/processing/test_vector.rb +397 -0
- metadata +16 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a40d65c055cc2baacd0a7489ec511a0db37b8e534f58fc02d5c095f78ecca66
|
4
|
+
data.tar.gz: 9c8634c610e0df8201655809b82bc8e7dbc2adab8cad405e2033ecc321c09137
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/ChangeLog.md
CHANGED
@@ -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
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
43
|
-
painter.image @
|
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
|
-
@
|
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
|
-
@
|
638
|
+
@image.save filename
|
78
639
|
end
|
79
640
|
|
80
641
|
# @private
|
81
642
|
def getInternal__ ()
|
82
|
-
@
|
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
|
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
|
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
|
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
|
-
|
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
|
-
|
986
|
-
@image__
|
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
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
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
|
-
|
1642
|
+
def setup__ (window)
|
1643
|
+
@@context__ = self
|
1012
1644
|
|
1013
|
-
|
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
|
-
|
1709
|
+
def setup (&block)
|
1710
|
+
@window__.setup = block
|
1711
|
+
nil
|
1712
|
+
end
|
1713
|
+
|
1714
|
+
# Define draw block.
|
1016
1715
|
#
|
1017
|
-
|
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
|
-
|
1020
|
-
|
1782
|
+
# @return [Integer] total number of frames
|
1783
|
+
#
|
1784
|
+
def frameCount ()
|
1785
|
+
@frameCount__
|
1021
1786
|
end
|
1022
1787
|
|
1023
|
-
#
|
1788
|
+
# Returns number of frames per second.
|
1024
1789
|
#
|
1025
|
-
# @
|
1790
|
+
# @return [Float] frames per second
|
1026
1791
|
#
|
1027
|
-
|
1792
|
+
def frameRate ()
|
1793
|
+
@window__.event.fps
|
1794
|
+
end
|
1795
|
+
|
1796
|
+
# Returns pixel density
|
1028
1797
|
#
|
1029
|
-
|
1030
|
-
|
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
|
-
#
|
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
|
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]
|
2067
|
+
# @return [Numeric] radian
|
1237
2068
|
#
|
1238
|
-
def
|
1239
|
-
|
2069
|
+
def radians (degree)
|
2070
|
+
degree * DEG2RAD__
|
1240
2071
|
end
|
1241
2072
|
|
1242
|
-
#
|
2073
|
+
# Converts radian to degree.
|
1243
2074
|
#
|
1244
|
-
# @param
|
1245
|
-
# @param extension [String] type of image to load (ex. 'png')
|
2075
|
+
# @param radian [Numeric] radian to convert
|
1246
2076
|
#
|
1247
|
-
# @return [
|
2077
|
+
# @return [Numeric] degree
|
1248
2078
|
#
|
1249
|
-
def
|
1250
|
-
|
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
|
-
#
|
2083
|
+
# Returns the sine of an angle.
|
1357
2084
|
#
|
1358
|
-
|
1359
|
-
@window__.setup = block
|
1360
|
-
nil
|
1361
|
-
end
|
1362
|
-
|
1363
|
-
# Define draw block.
|
2085
|
+
# @param angle [Numeric] angle in radians
|
1364
2086
|
#
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
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
|
2093
|
+
# Returns the cosine of an angle.
|
1430
2094
|
#
|
1431
|
-
# @
|
2095
|
+
# @param angle [Numeric] angle in radians
|
1432
2096
|
#
|
1433
|
-
|
1434
|
-
|
2097
|
+
# @return [Numeric] the cosine
|
2098
|
+
#
|
2099
|
+
def cos (angle)
|
2100
|
+
Math.cos angle
|
1435
2101
|
end
|
1436
2102
|
|
1437
|
-
# Returns
|
2103
|
+
# Returns the ratio of the sine and cosine of an angle.
|
1438
2104
|
#
|
1439
|
-
# @
|
2105
|
+
# @param angle [Numeric] angle in radians
|
1440
2106
|
#
|
1441
|
-
|
1442
|
-
|
2107
|
+
# @return [Numeric] the tangent
|
2108
|
+
#
|
2109
|
+
def tan (angle)
|
2110
|
+
Math.tan angle
|
1443
2111
|
end
|
1444
2112
|
|
1445
|
-
# Returns
|
2113
|
+
# Returns the inverse of sin().
|
1446
2114
|
#
|
1447
|
-
# @
|
2115
|
+
# @param value [Numeric] value for calculation
|
1448
2116
|
#
|
1449
|
-
|
1450
|
-
|
2117
|
+
# @return [Numeric] the arc sine
|
2118
|
+
#
|
2119
|
+
def asin (value)
|
2120
|
+
Math.asin value
|
1451
2121
|
end
|
1452
2122
|
|
1453
|
-
# Returns
|
2123
|
+
# Returns the inverse of cos().
|
1454
2124
|
#
|
1455
|
-
# @
|
2125
|
+
# @param value [Numeric] value for calculation
|
1456
2126
|
#
|
1457
|
-
|
1458
|
-
|
2127
|
+
# @return [Numeric] the arc cosine
|
2128
|
+
#
|
2129
|
+
def acos (value)
|
2130
|
+
Math.acos value
|
1459
2131
|
end
|
1460
2132
|
|
1461
|
-
# Returns
|
2133
|
+
# Returns the inverse of tan().
|
1462
2134
|
#
|
1463
|
-
# @
|
2135
|
+
# @param value [Numeric] value for valculation
|
1464
2136
|
#
|
1465
|
-
|
1466
|
-
|
2137
|
+
# @return [Numeric] the arc tangent
|
2138
|
+
#
|
2139
|
+
def atan (value)
|
2140
|
+
Math.atan value
|
1467
2141
|
end
|
1468
2142
|
|
1469
|
-
# Returns
|
2143
|
+
# Returns the angle from a specified point.
|
1470
2144
|
#
|
1471
|
-
# @
|
2145
|
+
# @param y [Numeric] y of the point
|
2146
|
+
# @param x [Numeric] x of the point
|
1472
2147
|
#
|
1473
|
-
|
1474
|
-
|
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
|
2154
|
+
# Returns the perlin noise value.
|
1478
2155
|
#
|
1479
|
-
# @
|
2156
|
+
# @overload noise(x)
|
2157
|
+
# @overload noise(x, y)
|
2158
|
+
# @overload noise(x, y, z)
|
1480
2159
|
#
|
1481
|
-
|
1482
|
-
|
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
|
2170
|
+
# Returns a random number in range low...high
|
1486
2171
|
#
|
1487
|
-
# @
|
2172
|
+
# @overload random()
|
2173
|
+
# @overload random(high)
|
2174
|
+
# @overload random(low, high)
|
2175
|
+
# @overload random(choices)
|
1488
2176
|
#
|
1489
|
-
|
1490
|
-
|
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
|
-
#
|
2189
|
+
# Creates a new vector.
|
1494
2190
|
#
|
1495
|
-
# @
|
2191
|
+
# @overload createVector()
|
2192
|
+
# @overload createVector(x, y)
|
2193
|
+
# @overload createVector(x, y, z)
|
1496
2194
|
#
|
1497
|
-
|
1498
|
-
|
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
|
-
#
|
2205
|
+
# Creates a new off-screen graphics context object.
|
1502
2206
|
#
|
1503
|
-
# @
|
2207
|
+
# @param width [Numeric] width of graphics image
|
2208
|
+
# @param height [Numeric] height of graphics image
|
1504
2209
|
#
|
1505
|
-
|
1506
|
-
|
2210
|
+
# @return [Graphics] graphics object
|
2211
|
+
#
|
2212
|
+
def createGraphics (width, height)
|
2213
|
+
Graphics.new width, height
|
1507
2214
|
end
|
1508
2215
|
|
1509
|
-
#
|
2216
|
+
# Loads image.
|
1510
2217
|
#
|
1511
|
-
# @
|
2218
|
+
# @param filename [String] file name to load image
|
2219
|
+
# @param extension [String] type of image to load (ex. 'png')
|
1512
2220
|
#
|
1513
|
-
|
1514
|
-
|
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
|