rubysketch 0.2.7 → 0.3.4
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/ChangeLog.md +30 -0
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/rubysketch-processing.rb +6 -24
- data/lib/rubysketch/processing.rb +1990 -1189
- data/lib/rubysketch/window.rb +26 -10
- data/test/helper.rb +24 -0
- data/test/processing/test_vector.rb +397 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9914f7b869e2dfeb80a8ba58a8c6678c0a995a974124b2b88974e477af3fdd8
|
4
|
+
data.tar.gz: 2b7d45e918f60be716bc9edc8f5bfbb7ceb800954965af32163431e681709250
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f1192007cfb3a80c6335dd8a881358a9fa2b9dac8b6a0931836f295f2658ac0d4723b9a9d51800e6923ccfcc625f6fd92fd9444732339a338773681d6921299
|
7
|
+
data.tar.gz: afefa27c322e08e0be3c1c6099b3ef3a3c86d0fadfc3140e4ec4c26c4686573d1a733ce0791f94241a4e73a67cda5998029fcfd4ebc6e7f3a1de6c8994ecdb0e
|
data/ChangeLog.md
CHANGED
@@ -1,6 +1,36 @@
|
|
1
1
|
# RubySketch ChangeLog
|
2
2
|
|
3
3
|
|
4
|
+
## [0.3.4] - 2020-08-02
|
5
|
+
|
6
|
+
- delete Utility module
|
7
|
+
|
8
|
+
|
9
|
+
## [0.3.3] - 2020-08-01
|
10
|
+
|
11
|
+
- add Vector class
|
12
|
+
|
13
|
+
|
14
|
+
## [0.3.2] - 2020-07-22
|
15
|
+
|
16
|
+
- text() draws to the baseline by default
|
17
|
+
- add textWidth(), textAscent(), textDescent() and textAlign()
|
18
|
+
- change initial color for fill() and stroke()
|
19
|
+
- change initial background color to grayscale 0.8
|
20
|
+
|
21
|
+
|
22
|
+
## [0.3.1] - 2020-07-17
|
23
|
+
|
24
|
+
- add touchStarted(), touchEnded(), touchMoved() and touches()
|
25
|
+
- make all event handler drawable
|
26
|
+
- limit font max size to 256
|
27
|
+
|
28
|
+
|
29
|
+
## [0.3.0] - 2020-05-21
|
30
|
+
|
31
|
+
- add createGraphics()
|
32
|
+
|
33
|
+
|
4
34
|
## [0.2.7] - 2020-04-17
|
5
35
|
|
6
36
|
- add strokeCap() and strokeJoin()
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.4
|
@@ -2,32 +2,14 @@ require 'rubysketch'
|
|
2
2
|
|
3
3
|
|
4
4
|
begin
|
5
|
-
|
6
|
-
methods = context.class.instance_methods(false)
|
7
|
-
.reject {|name| name =~ /__$/}
|
8
|
-
consts = context.class.constants
|
9
|
-
.reject {|name| name =~ /__$/}
|
10
|
-
.each_with_object({}) {|name, h| h[name] = context.class.const_get name}
|
5
|
+
include RubySketch::Processing::Context
|
11
6
|
|
12
|
-
|
13
|
-
|
14
|
-
define_method name do |*args, &block|
|
15
|
-
context.__send__ name, *args, &block
|
16
|
-
end
|
17
|
-
end
|
18
|
-
consts.each do |(name, value)|
|
19
|
-
const_set name, value
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
window = RubySketch::Window.new do |_|
|
24
|
-
window.start
|
25
|
-
end
|
26
|
-
context.setup__ window
|
7
|
+
window = RubySketch::Window.new {start}
|
8
|
+
setup__ window
|
27
9
|
|
28
|
-
window.
|
10
|
+
window.__send__ :begin_draw
|
29
11
|
at_exit do
|
30
|
-
window.
|
31
|
-
Reflex.start {window.show}
|
12
|
+
window.__send__ :end_draw
|
13
|
+
Reflex.start {window.show} unless $!
|
32
14
|
end
|
33
15
|
end
|
@@ -3,1112 +3,1551 @@ module RubySketch
|
|
3
3
|
|
4
4
|
# Processing compatible API
|
5
5
|
#
|
6
|
-
|
6
|
+
module Processing
|
7
7
|
|
8
|
-
include Math
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
TWO_PI = PI * 2
|
13
|
-
TAU = PI * 2
|
9
|
+
# @private
|
10
|
+
DEG2RAD__ = Math::PI / 180.0
|
14
11
|
|
15
|
-
#
|
16
|
-
|
17
|
-
|
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
|
18
46
|
|
19
|
-
|
20
|
-
|
21
|
-
|
47
|
+
# Initializer for dup or clone
|
48
|
+
#
|
49
|
+
def initialize_copy (o)
|
50
|
+
@point = o.getInternal__.dup
|
51
|
+
end
|
22
52
|
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
26
79
|
|
27
|
-
|
28
|
-
|
29
|
-
|
80
|
+
# Gets x value.
|
81
|
+
#
|
82
|
+
# @return [Numeric] x value of vector
|
83
|
+
#
|
84
|
+
def x ()
|
85
|
+
@point.x
|
86
|
+
end
|
30
87
|
|
31
|
-
|
32
|
-
|
33
|
-
|
88
|
+
# Gets y value.
|
89
|
+
#
|
90
|
+
# @return [Numeric] y value of vector
|
91
|
+
#
|
92
|
+
def y ()
|
93
|
+
@point.y
|
94
|
+
end
|
34
95
|
|
35
|
-
|
36
|
-
|
37
|
-
|
96
|
+
# Gets z value.
|
97
|
+
#
|
98
|
+
# @return [Numeric] z value of vector
|
99
|
+
#
|
100
|
+
def z ()
|
101
|
+
@point.z
|
102
|
+
end
|
38
103
|
|
39
|
-
|
40
|
-
|
41
|
-
|
104
|
+
# Sets x value.
|
105
|
+
#
|
106
|
+
# @return [Numeric] x value of vector
|
107
|
+
#
|
108
|
+
def x= (x)
|
109
|
+
@point.x = x
|
110
|
+
end
|
42
111
|
|
43
|
-
|
44
|
-
|
45
|
-
|
112
|
+
# Sets y value.
|
113
|
+
#
|
114
|
+
# @return [Numeric] y value of vector
|
115
|
+
#
|
116
|
+
def y= (y)
|
117
|
+
@point.y = y
|
118
|
+
end
|
46
119
|
|
47
|
-
|
48
|
-
|
49
|
-
|
120
|
+
# Sets z value.
|
121
|
+
#
|
122
|
+
# @return [Numeric] z value of vector
|
123
|
+
#
|
124
|
+
def z= (z)
|
125
|
+
@point.z = z
|
126
|
+
end
|
50
127
|
|
51
|
-
|
52
|
-
|
53
|
-
|
128
|
+
# Returns the interpolated vector between 2 vectors.
|
129
|
+
#
|
130
|
+
# @overload lerp(v, amount)
|
131
|
+
# @overload lerp(x, y, amount)
|
132
|
+
# @overload lerp(x, y, z, amount)
|
133
|
+
#
|
134
|
+
# @param v [Vector] vector to interpolate
|
135
|
+
# @param x [Numeric] x of vector to interpolate
|
136
|
+
# @param y [Numeric] y of vector to interpolate
|
137
|
+
# @param z [Numeric] z of vector to interpolate
|
138
|
+
# @param amount [Numeric] amount to interpolate
|
139
|
+
#
|
140
|
+
# @return [Vector] interporated vector
|
141
|
+
#
|
142
|
+
def lerp (*args, amount)
|
143
|
+
v = toVector__ *args
|
144
|
+
self.x = x + (v.x - x) * amount
|
145
|
+
self.y = y + (v.y - y) * amount
|
146
|
+
self.z = z + (v.z - z) * amount
|
147
|
+
self
|
148
|
+
end
|
54
149
|
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
58
161
|
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
62
169
|
|
63
|
-
|
64
|
-
|
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
|
65
187
|
|
66
|
-
|
67
|
-
|
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
|
68
205
|
|
69
|
-
|
70
|
-
|
71
|
-
@
|
72
|
-
|
73
|
-
@
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
@mouseX__ =
|
80
|
-
@mouseY__ =
|
81
|
-
@mousePrevX__ =
|
82
|
-
@mousePrevY__ = 0
|
83
|
-
@mousePressed__ = false
|
84
|
-
|
85
|
-
colorMode RGB, 255
|
86
|
-
angleMode RADIANS
|
87
|
-
rectMode CORNER
|
88
|
-
ellipseMode CENTER
|
89
|
-
imageMode CORNER
|
90
|
-
end
|
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
|
91
216
|
|
92
|
-
|
93
|
-
|
94
|
-
@
|
95
|
-
|
96
|
-
|
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
|
97
226
|
end
|
98
227
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
pop
|
108
|
-
end
|
109
|
-
@frameCount__ += 1
|
110
|
-
}
|
111
|
-
|
112
|
-
updateMouseState = -> x, y, pressed = nil {
|
113
|
-
@mouseX__ = x
|
114
|
-
@mouseY__ = y
|
115
|
-
@mousePressed__ = pressed if pressed != nil
|
116
|
-
}
|
117
|
-
|
118
|
-
updateMousePrevPos = -> {
|
119
|
-
@mousePrevX__ = @mouseX__
|
120
|
-
@mousePrevY__ = @mouseY__
|
121
|
-
}
|
122
|
-
|
123
|
-
@window__.draw = proc do |e|
|
124
|
-
if @loop__ || @redraw__
|
125
|
-
@redraw__ = false
|
126
|
-
drawFrame.call e
|
127
|
-
end
|
128
|
-
updateMousePrevPos.call
|
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
|
129
236
|
end
|
130
237
|
|
131
|
-
|
132
|
-
|
133
|
-
|
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
|
134
246
|
end
|
135
247
|
|
136
|
-
|
137
|
-
|
138
|
-
|
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
|
139
256
|
end
|
140
257
|
|
141
|
-
|
142
|
-
|
143
|
-
|
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
|
144
266
|
end
|
145
267
|
|
146
|
-
|
147
|
-
|
148
|
-
|
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
|
149
283
|
end
|
150
|
-
end
|
151
284
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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
|
161
301
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
171
318
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|
181
335
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
value.round
|
190
|
-
end
|
336
|
+
# Returns the length of the vector.
|
337
|
+
#
|
338
|
+
# @return [Numeric] length
|
339
|
+
#
|
340
|
+
def mag ()
|
341
|
+
@point.length
|
342
|
+
end
|
191
343
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
def pow (value, exponent)
|
200
|
-
value ** exponent
|
201
|
-
end
|
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
|
202
351
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
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
|
212
365
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
#
|
222
|
-
# @return [Numeric] magnitude
|
223
|
-
#
|
224
|
-
def mag (*args)
|
225
|
-
x, y, z = *args
|
226
|
-
case args.size
|
227
|
-
when 2 then sqrt x * x + y * y
|
228
|
-
when 3 then sqrt x * x + y * y + z * z
|
229
|
-
else raise ArgumentError
|
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
|
230
374
|
end
|
231
|
-
end
|
232
375
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
# @param y2 [Numeric] y of second point
|
243
|
-
# @param z2 [Numeric] z of second point
|
244
|
-
#
|
245
|
-
# @return [Numeric] distance between 2 points
|
246
|
-
#
|
247
|
-
def dist (*args)
|
248
|
-
case args.size
|
249
|
-
when 4
|
250
|
-
x1, y1, x2, y2 = *args
|
251
|
-
xx, yy = x2 - x1, y2 - y1
|
252
|
-
sqrt xx * xx + yy * yy
|
253
|
-
when 3
|
254
|
-
x1, y1, z1, x2, y2, z2 = *args
|
255
|
-
xx, yy, zz = x2 - x1, y2 - y1, z2 - z1
|
256
|
-
sqrt xx * xx + yy * yy + zz * zz
|
257
|
-
else raise ArgumentError
|
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
|
258
385
|
end
|
259
|
-
end
|
260
386
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
(value.to_f - start.to_f) / (stop.to_f - start.to_f)
|
271
|
-
end
|
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
|
272
396
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
end
|
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
|
284
407
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
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
|
298
424
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
#
|
310
|
-
# @return [Numeric] minimum value
|
311
|
-
#
|
312
|
-
def min (*args)
|
313
|
-
args.flatten.min
|
314
|
-
end
|
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
|
315
435
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
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
|
332
455
|
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
end
|
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
|
344
466
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
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
|
354
478
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
radian * RAD2DEG__
|
363
|
-
end
|
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
|
364
486
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
@
|
369
|
-
|
370
|
-
|
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
|
371
499
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
@
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
def mouseReleased (&block)
|
390
|
-
@mouseReleasedBlock__ = block if block
|
391
|
-
nil
|
392
|
-
end
|
393
|
-
|
394
|
-
def mouseMoved (&block)
|
395
|
-
@mouseMovedBlock__ = block if block
|
396
|
-
nil
|
397
|
-
end
|
398
|
-
|
399
|
-
def mouseDragged (&block)
|
400
|
-
@mouseDraggedBlock__ = block if block
|
401
|
-
nil
|
402
|
-
end
|
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
|
403
517
|
|
404
|
-
|
405
|
-
|
406
|
-
|
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
|
407
529
|
|
408
|
-
|
409
|
-
|
410
|
-
@
|
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
|
411
546
|
|
412
|
-
@
|
413
|
-
|
547
|
+
# @private
|
548
|
+
def inspect ()
|
549
|
+
"<##{self.class.name} #{x}, #{y}, #{z}>"
|
550
|
+
end
|
414
551
|
|
415
|
-
|
416
|
-
|
417
|
-
|
552
|
+
# @private
|
553
|
+
def <=> (o)
|
554
|
+
@point <=> o.getInternal__
|
555
|
+
end
|
418
556
|
|
419
|
-
|
420
|
-
|
421
|
-
|
557
|
+
# @private
|
558
|
+
protected def getInternal__ ()
|
559
|
+
@point
|
560
|
+
end
|
422
561
|
|
423
|
-
|
424
|
-
|
425
|
-
|
562
|
+
# @private
|
563
|
+
private def toVector__ (*args)
|
564
|
+
self.class === args.first ? args.first : self.class.new(*args)
|
565
|
+
end
|
426
566
|
|
427
|
-
|
428
|
-
@window__.height
|
429
|
-
end
|
567
|
+
end# Vector
|
430
568
|
|
431
|
-
# Returns number of frames since program started.
|
432
|
-
#
|
433
|
-
# @return [Integer] total number of frames
|
434
|
-
#
|
435
|
-
def frameCount ()
|
436
|
-
@frameCount__
|
437
|
-
end
|
438
569
|
|
439
|
-
#
|
570
|
+
# Image object.
|
440
571
|
#
|
441
|
-
|
442
|
-
#
|
443
|
-
def frameRate ()
|
444
|
-
@window__.event.fps
|
445
|
-
end
|
572
|
+
class Image
|
446
573
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
def displayDensity ()
|
452
|
-
@painter__.pixel_density
|
453
|
-
end
|
574
|
+
# @private
|
575
|
+
def initialize (image)
|
576
|
+
@image = image
|
577
|
+
end
|
454
578
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
579
|
+
# Gets width of image.
|
580
|
+
#
|
581
|
+
# @return [Numeric] width of image
|
582
|
+
#
|
583
|
+
def width ()
|
584
|
+
@image.width
|
585
|
+
end
|
462
586
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
587
|
+
# Gets height of image.
|
588
|
+
#
|
589
|
+
# @return [Numeric] height of image
|
590
|
+
#
|
591
|
+
def height ()
|
592
|
+
@image.height
|
593
|
+
end
|
470
594
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
@
|
477
|
-
|
595
|
+
# Resizes image.
|
596
|
+
#
|
597
|
+
# @param width [Numeric] width for resized image
|
598
|
+
# @param height [Numeric] height for resized image
|
599
|
+
#
|
600
|
+
# @return [nil] nil
|
601
|
+
#
|
602
|
+
def resize (width, height)
|
603
|
+
@image = Rays::Image.new(width, height).paint do |painter|
|
604
|
+
painter.image @image, 0, 0, width, height
|
605
|
+
end
|
606
|
+
nil
|
607
|
+
end
|
478
608
|
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
@
|
485
|
-
|
609
|
+
# Copies image.
|
610
|
+
#
|
611
|
+
# @overload copy(sx, sy, sw, sh, dx, dy, dw, dh)
|
612
|
+
# @overload copy(img, sx, sy, sw, sh, dx, dy, dw, dh)
|
613
|
+
#
|
614
|
+
# @param img [Image] image for copy source
|
615
|
+
# @param sx [Numrtic] x position of source region
|
616
|
+
# @param sy [Numrtic] y position of source region
|
617
|
+
# @param sw [Numrtic] width of source region
|
618
|
+
# @param sh [Numrtic] height of source region
|
619
|
+
# @param dx [Numrtic] x position of destination region
|
620
|
+
# @param dy [Numrtic] y position of destination region
|
621
|
+
# @param dw [Numrtic] width of destination region
|
622
|
+
# @param dh [Numrtic] height of destination region
|
623
|
+
#
|
624
|
+
# @return [nil] nil
|
625
|
+
#
|
626
|
+
def copy (img = nil, sx, sy, sw, sh, dx, dy, dw, dh)
|
627
|
+
img ||= self
|
628
|
+
@image.paint do |painter|
|
629
|
+
painter.image img.getInternal__, sx, sy, sw, sh, dx, dy, dw, dh
|
630
|
+
end
|
631
|
+
end
|
486
632
|
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
# @param mode [RGB, HSB] RGB or HSB
|
495
|
-
# @param max [Numeric] max values for all color values
|
496
|
-
# @param max1 [Numeric] max value for red or hue
|
497
|
-
# @param max2 [Numeric] max value for green or saturation
|
498
|
-
# @param max3 [Numeric] max value for blue or brightness
|
499
|
-
# @param maxA [Numeric] max value for alpha
|
500
|
-
#
|
501
|
-
# @return [nil] nil
|
502
|
-
#
|
503
|
-
def colorMode (mode, *maxes)
|
504
|
-
raise ArgumentError, "invalid color mode: #{mode}" unless [RGB, HSB].include?(mode)
|
505
|
-
raise ArgumentError unless [0, 1, 3, 4].include?(maxes.size)
|
633
|
+
# Saves image to file.
|
634
|
+
#
|
635
|
+
# @param filename [String] file name to save image
|
636
|
+
#
|
637
|
+
def save (filename)
|
638
|
+
@image.save filename
|
639
|
+
end
|
506
640
|
|
507
|
-
@
|
508
|
-
|
509
|
-
|
510
|
-
when 3, 4 then @colorMaxes__[0...maxes.size] = maxes.map &:to_f
|
641
|
+
# @private
|
642
|
+
def getInternal__ ()
|
643
|
+
@image
|
511
644
|
end
|
512
|
-
nil
|
513
|
-
end
|
514
645
|
|
515
|
-
#
|
516
|
-
private def toRGBA__ (*args)
|
517
|
-
a, b, c, d = args
|
518
|
-
return parseColor__(a, b || alphaMax__) if a.kind_of?(String)
|
646
|
+
end# Image
|
519
647
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
648
|
+
|
649
|
+
# Font object.
|
650
|
+
#
|
651
|
+
class Font
|
652
|
+
|
653
|
+
# @private
|
654
|
+
def initialize (font)
|
655
|
+
@font = font
|
524
656
|
end
|
525
|
-
rgba = rgba.map.with_index {|value, i| value / @colorMaxes__[i]}
|
526
|
-
color = @hsbColor__ ? Rays::Color.hsv(*rgba) : Rays::Color.new(*rgba)
|
527
|
-
color.to_a
|
528
|
-
end
|
529
657
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
658
|
+
# Returns bounding box.
|
659
|
+
#
|
660
|
+
# @overload textBounds(str)
|
661
|
+
# @overload textBounds(str, x, y)
|
662
|
+
# @overload textBounds(str, x, y, fontSize)
|
663
|
+
#
|
664
|
+
# @param str [String] text to calculate bounding box
|
665
|
+
# @param x [Numeric] horizontal position of bounding box
|
666
|
+
# @param y [Numeric] vertical position of bounding box
|
667
|
+
# @param fontSize [Numeric] font size
|
668
|
+
#
|
669
|
+
# @return [TextBounds] bounding box for text
|
670
|
+
#
|
671
|
+
def textBounds (str, x = 0, y = 0, fontSize = nil)
|
672
|
+
f = fontSize ? Rays::Font.new(@font.name, fontSize) : @font
|
673
|
+
TextBounds.new x, y, x + f.width(str), y + f.height
|
674
|
+
end
|
534
675
|
|
535
|
-
|
536
|
-
return *rgb, (alpha / alphaMax__)
|
537
|
-
end
|
676
|
+
end# Font
|
538
677
|
|
539
|
-
# @private
|
540
|
-
private def alphaMax__ ()
|
541
|
-
@colorMaxes__[3]
|
542
|
-
end
|
543
678
|
|
544
|
-
#
|
545
|
-
#
|
546
|
-
# @param mode [RADIANS, DEGREES] RADIANS or DEGREES
|
679
|
+
# Bounding box for text.
|
547
680
|
#
|
548
|
-
|
549
|
-
#
|
550
|
-
def angleMode (mode)
|
551
|
-
@angleScale__ = case mode
|
552
|
-
when RADIANS then RAD2DEG__
|
553
|
-
when DEGREES then 1.0
|
554
|
-
else raise ArgumentError, "invalid angle mode: #{mode}"
|
555
|
-
end
|
556
|
-
nil
|
557
|
-
end
|
681
|
+
class TextBounds
|
558
682
|
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
end
|
683
|
+
# Horizontal position
|
684
|
+
#
|
685
|
+
attr_reader :x
|
563
686
|
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
# CORNERS -> rect(left, top, right, bottom)
|
568
|
-
# CENTER -> rect(center_x, center_y, width, height)
|
569
|
-
# RADIUS -> rect(center_x, center_y, radius_h, radius_v)
|
570
|
-
#
|
571
|
-
# @param mode [CORNER, CORNERS, CENTER, RADIUS]
|
572
|
-
#
|
573
|
-
# @return [nil] nil
|
574
|
-
#
|
575
|
-
def rectMode (mode)
|
576
|
-
@rectMode__ = mode
|
577
|
-
end
|
687
|
+
# Vertical position
|
688
|
+
#
|
689
|
+
attr_reader :y
|
578
690
|
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
# CORNERS -> ellipse(left, top, right, bottom)
|
583
|
-
# CENTER -> ellipse(center_x, center_y, width, height)
|
584
|
-
# RADIUS -> ellipse(center_x, center_y, radius_h, radius_v)
|
585
|
-
#
|
586
|
-
# @param mode [CORNER, CORNERS, CENTER, RADIUS]
|
587
|
-
#
|
588
|
-
# @return [nil] nil
|
589
|
-
#
|
590
|
-
def ellipseMode (mode)
|
591
|
-
@ellipseMode__ = mode
|
592
|
-
end
|
691
|
+
# Width of bounding box
|
692
|
+
#
|
693
|
+
attr_reader :w
|
593
694
|
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
# CORNERS -> image(img, left, top, right, bottom)
|
598
|
-
# CENTER -> image(img, center_x, center_y, width, height)
|
599
|
-
#
|
600
|
-
# @param mode [CORNER, CORNERS, CENTER]
|
601
|
-
#
|
602
|
-
# @return [nil] nil
|
603
|
-
#
|
604
|
-
def imageMode (mode)
|
605
|
-
@imageMode__ = mode
|
606
|
-
end
|
695
|
+
# Height of bounding box
|
696
|
+
#
|
697
|
+
attr_reader :h
|
607
698
|
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
when CORNER then [a, b, c, d]
|
612
|
-
when CORNERS then [a, b, c - a, d - b]
|
613
|
-
when CENTER then [a - c / 2.0, b - d / 2.0, c, d]
|
614
|
-
when RADIUS then [a - c, b - d, c * 2, d * 2]
|
615
|
-
else raise ArgumentError # ToDo: refine error message
|
699
|
+
# @private
|
700
|
+
def initialize (x, y, w, h)
|
701
|
+
@x, @y, @w, @h = x, y, w, h
|
616
702
|
end
|
617
|
-
end
|
618
703
|
|
619
|
-
#
|
620
|
-
#
|
621
|
-
# @return [nil] nil
|
622
|
-
#
|
623
|
-
def loop ()
|
624
|
-
@loop__ = true
|
625
|
-
end
|
704
|
+
end# TextBounds
|
626
705
|
|
627
|
-
# Disables calling draw block on every frame.
|
628
|
-
#
|
629
|
-
# @return [nil] nil
|
630
|
-
#
|
631
|
-
def noLoop ()
|
632
|
-
@loop__ = false
|
633
|
-
end
|
634
706
|
|
635
|
-
#
|
707
|
+
# Touch object.
|
636
708
|
#
|
637
|
-
|
638
|
-
#
|
639
|
-
def redraw ()
|
640
|
-
@redraw__ = true
|
641
|
-
end
|
709
|
+
class Touch
|
642
710
|
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
# @param r [Integer] red value (0..255)
|
655
|
-
# @param g [Integer] green value (0..255)
|
656
|
-
# @param b [Integer] blue value (0..255)
|
657
|
-
# @param alpha [Integer] alpha value (0..255)
|
658
|
-
#
|
659
|
-
# @return [nil] nil
|
660
|
-
#
|
661
|
-
def background (*args)
|
662
|
-
rgba = toRGBA__ *args
|
663
|
-
if rgba[3] == 1
|
664
|
-
@painter__.background *rgba
|
665
|
-
else
|
666
|
-
@painter__.push fill: rgba, stroke: nil do |_|
|
667
|
-
@painter__.rect 0, 0, width, height
|
668
|
-
end
|
711
|
+
# Horizontal position of touch
|
712
|
+
#
|
713
|
+
attr_reader :x
|
714
|
+
|
715
|
+
# Vertical position of touch
|
716
|
+
#
|
717
|
+
attr_reader :y
|
718
|
+
|
719
|
+
# @private
|
720
|
+
def initialize (x, y)
|
721
|
+
@x, @y = x, y
|
669
722
|
end
|
670
|
-
nil
|
671
|
-
end
|
672
723
|
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
# @overload fill(rgb, alpha)
|
677
|
-
# @overload fill(gray)
|
678
|
-
# @overload fill(gray, alpha)
|
679
|
-
# @overload fill(r, g, b)
|
680
|
-
# @overload fill(r, g, b, alpha)
|
681
|
-
#
|
682
|
-
# @param rgb [String] color code like '#00AAFF'
|
683
|
-
# @param gray [Integer] gray value (0..255)
|
684
|
-
# @param r [Integer] red value (0..255)
|
685
|
-
# @param g [Integer] green value (0..255)
|
686
|
-
# @param b [Integer] blue value (0..255)
|
687
|
-
# @param alpha [Integer] alpha value (0..255)
|
688
|
-
#
|
689
|
-
# @return [nil] nil
|
690
|
-
#
|
691
|
-
def fill (*args)
|
692
|
-
@painter__.fill(*toRGBA__(*args))
|
693
|
-
nil
|
694
|
-
end
|
724
|
+
def id ()
|
725
|
+
raise NotImplementedError
|
726
|
+
end
|
695
727
|
|
696
|
-
#
|
697
|
-
#
|
698
|
-
# @overload stroke(rgb)
|
699
|
-
# @overload stroke(rgb, alpha)
|
700
|
-
# @overload stroke(gray)
|
701
|
-
# @overload stroke(gray, alpha)
|
702
|
-
# @overload stroke(r, g, b)
|
703
|
-
# @overload stroke(r, g, b, alpha)
|
704
|
-
#
|
705
|
-
# @param rgb [String] color code like '#00AAFF'
|
706
|
-
# @param gray [Integer] gray value (0..255)
|
707
|
-
# @param r [Integer] red value (0..255)
|
708
|
-
# @param g [Integer] green value (0..255)
|
709
|
-
# @param b [Integer] blue value (0..255)
|
710
|
-
# @param alpha [Integer] alpha value (0..255)
|
711
|
-
#
|
712
|
-
# @return [nil] nil
|
713
|
-
#
|
714
|
-
def stroke (*args)
|
715
|
-
@painter__.stroke(*toRGBA__(*args))
|
716
|
-
nil
|
717
|
-
end
|
728
|
+
end# Touch
|
718
729
|
|
719
|
-
# Sets stroke weight.
|
720
|
-
#
|
721
|
-
# @param weight [Numeric] width of stroke
|
722
|
-
#
|
723
|
-
# @return [nil] nil
|
724
|
-
#
|
725
|
-
def strokeWeight (weight)
|
726
|
-
@painter__.stroke_width weight
|
727
|
-
nil
|
728
|
-
end
|
729
730
|
|
730
|
-
#
|
731
|
+
# Drawing context
|
731
732
|
#
|
732
|
-
|
733
|
-
#
|
734
|
-
# @return [nil] nil
|
735
|
-
#
|
736
|
-
def strokeCap (cap)
|
737
|
-
@painter__.stroke_cap cap
|
738
|
-
nil
|
739
|
-
end
|
733
|
+
module GraphicsContext
|
740
734
|
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
#
|
745
|
-
# @return [nil] nil
|
746
|
-
#
|
747
|
-
def strokeJoin (join)
|
748
|
-
@painter__.stroke_join join
|
749
|
-
nil
|
750
|
-
end
|
735
|
+
# PI / 2
|
736
|
+
#
|
737
|
+
HALF_PI = Math::PI / 2
|
751
738
|
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
#
|
756
|
-
def noFill ()
|
757
|
-
@painter__.fill nil
|
758
|
-
nil
|
759
|
-
end
|
739
|
+
# PI / 4
|
740
|
+
#
|
741
|
+
QUARTER_PI = Math::PI / 4
|
760
742
|
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
#
|
765
|
-
def noStroke ()
|
766
|
-
@painter__.stroke nil
|
767
|
-
nil
|
768
|
-
end
|
743
|
+
# PI * 2
|
744
|
+
#
|
745
|
+
TWO_PI = Math::PI * 2
|
769
746
|
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
# @param size [Numeric] font size
|
774
|
-
#
|
775
|
-
# @return [Font] current font
|
776
|
-
#
|
777
|
-
def textFont (name = nil, size = nil)
|
778
|
-
@painter__.font name, size if name || size
|
779
|
-
Font.new @painter__.font
|
780
|
-
end
|
747
|
+
# PI * 2
|
748
|
+
#
|
749
|
+
TAU = Math::PI * 2
|
781
750
|
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
#
|
786
|
-
# @return [nil] nil
|
787
|
-
#
|
788
|
-
def textSize (size)
|
789
|
-
@painter__.font @painter__.font.name, size
|
790
|
-
nil
|
791
|
-
end
|
751
|
+
# RGB mode for colorMode().
|
752
|
+
#
|
753
|
+
RGB = :RGB
|
792
754
|
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
# @param y [Numeric] vertical position
|
797
|
-
#
|
798
|
-
# @return [nil] nil
|
799
|
-
#
|
800
|
-
def point (x, y)
|
801
|
-
w = @painter__.stroke_width
|
802
|
-
w = 1 if w == 0
|
803
|
-
@painter__.ellipse x - (w / 2.0), y - (w / 2.0), w, w
|
804
|
-
nil
|
805
|
-
end
|
806
|
-
|
807
|
-
# Draws a line.
|
808
|
-
#
|
809
|
-
# @param x1 [Numeric] horizontal position of first point
|
810
|
-
# @param y1 [Numeric] vertical position of first point
|
811
|
-
# @param x2 [Numeric] horizontal position of second point
|
812
|
-
# @param y2 [Numeric] vertical position of second point
|
813
|
-
#
|
814
|
-
# @return [nil] nil
|
815
|
-
#
|
816
|
-
def line (x1, y1, x2, y2)
|
817
|
-
@painter__.line x1, y1, x2, y2
|
818
|
-
nil
|
819
|
-
end
|
755
|
+
# HSB mode for colorMode().
|
756
|
+
#
|
757
|
+
HSB = :HSB
|
820
758
|
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
# @overload rect(a, b, c, d, r)
|
825
|
-
# @overload rect(a, b, c, d, tl, tr, br, bl)
|
826
|
-
#
|
827
|
-
# @param a [Numeric] horizontal position of the shape by default
|
828
|
-
# @param b [Numeric] vertical position of the shape by default
|
829
|
-
# @param c [Numeric] width of the shape by default
|
830
|
-
# @param d [Numeric] height of the shape by default
|
831
|
-
# @param r [Numeric] radius for all corners
|
832
|
-
# @param tl [Numeric] radius for top-left corner
|
833
|
-
# @param tr [Numeric] radius for top-right corner
|
834
|
-
# @param br [Numeric] radius for bottom-right corner
|
835
|
-
# @param bl [Numeric] radius for bottom-left corner
|
836
|
-
#
|
837
|
-
# @return [nil] nil
|
838
|
-
#
|
839
|
-
def rect (a, b, c, d, *args)
|
840
|
-
x, y, w, h = toXYWH__ @rectMode__, a, b, c, d
|
841
|
-
case args.size
|
842
|
-
when 0 then @painter__.rect x, y, w, h
|
843
|
-
when 1 then @painter__.rect x, y, w, h, round: args[0]
|
844
|
-
when 4 then @painter__.rect x, y, w, h, lt: args[0], rt: args[1], rb: args[2], lb: args[3]
|
845
|
-
else raise ArgumentError # ToDo: refine error message
|
846
|
-
end
|
847
|
-
nil
|
848
|
-
end
|
759
|
+
# Radian mode for angleMode().
|
760
|
+
#
|
761
|
+
RADIANS = :RADIANS
|
849
762
|
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
# @param b [Numeric] vertical position of the shape
|
854
|
-
# @param c [Numeric] width of the shape
|
855
|
-
# @param d [Numeric] height of the shape
|
856
|
-
#
|
857
|
-
# @return [nil] nil
|
858
|
-
#
|
859
|
-
def ellipse (a, b, c, d)
|
860
|
-
x, y, w, h = toXYWH__ @ellipseMode__, a, b, c, d
|
861
|
-
@painter__.ellipse x, y, w, h
|
862
|
-
nil
|
863
|
-
end
|
763
|
+
# Degree mode for angleMode().
|
764
|
+
#
|
765
|
+
DEGREES = :DEGREES
|
864
766
|
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
# @param y [Numeric] vertical position of the shape
|
869
|
-
# @param extent [Numeric] width and height of the shape
|
870
|
-
#
|
871
|
-
# @return [nil] nil
|
872
|
-
#
|
873
|
-
def circle (x, y, extent)
|
874
|
-
ellipse x, y, extent, extent
|
875
|
-
end
|
767
|
+
# Mode for rectMode(), ellipseMode() and imageMode().
|
768
|
+
#
|
769
|
+
CORNER = :CORNER
|
876
770
|
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
# @param b [Numeric] vertical position of the shape
|
881
|
-
# @param c [Numeric] width of the shape
|
882
|
-
# @param d [Numeric] height of the shape
|
883
|
-
# @param start [Numeric] angle to start the arc
|
884
|
-
# @param stop [Numeric] angle to stop the arc
|
885
|
-
#
|
886
|
-
# @return [nil] nil
|
887
|
-
#
|
888
|
-
def arc (a, b, c, d, start, stop)
|
889
|
-
x, y, w, h = toXYWH__ @ellipseMode__, a, b, c, d
|
890
|
-
start = toAngle__ start
|
891
|
-
stop = toAngle__ stop
|
892
|
-
@painter__.ellipse x, y, w, h, from: start, to: stop
|
893
|
-
nil
|
894
|
-
end
|
895
|
-
|
896
|
-
# Draws a square.
|
897
|
-
#
|
898
|
-
# @param x [Numeric] horizontal position of the shape
|
899
|
-
# @param y [Numeric] vertical position of the shape
|
900
|
-
# @param extent [Numeric] width and height of the shape
|
901
|
-
#
|
902
|
-
# @return [nil] nil
|
903
|
-
#
|
904
|
-
def square (x, y, extent)
|
905
|
-
rect x, y, extent, extent
|
906
|
-
end
|
771
|
+
# Mode for rectMode(), ellipseMode() and imageMode().
|
772
|
+
#
|
773
|
+
CORNERS = :CORNERS
|
907
774
|
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
# @param y1 [Numeric] vertical position of first point
|
912
|
-
# @param x2 [Numeric] horizontal position of second point
|
913
|
-
# @param y2 [Numeric] vertical position of second point
|
914
|
-
# @param x3 [Numeric] horizontal position of third point
|
915
|
-
# @param y3 [Numeric] vertical position of third point
|
916
|
-
#
|
917
|
-
# @return [nil] nil
|
918
|
-
#
|
919
|
-
def triangle (x1, y1, x2, y2, x3, y3)
|
920
|
-
@painter__.line x1, y1, x2, y2, x3, y3, loop: true
|
921
|
-
nil
|
922
|
-
end
|
775
|
+
# Mode for rectMode(), ellipseMode(), imageMode() and textAlign().
|
776
|
+
#
|
777
|
+
CENTER = :CENTER
|
923
778
|
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
# @param y1 [Numeric] vertical position of first point
|
928
|
-
# @param x2 [Numeric] horizontal position of second point
|
929
|
-
# @param y2 [Numeric] vertical position of second point
|
930
|
-
# @param x3 [Numeric] horizontal position of third point
|
931
|
-
# @param y3 [Numeric] vertical position of third point
|
932
|
-
# @param x4 [Numeric] horizontal position of fourth point
|
933
|
-
# @param y4 [Numeric] vertical position of fourth point
|
934
|
-
#
|
935
|
-
# @return [nil] nil
|
936
|
-
#
|
937
|
-
def quad (x1, y1, x2, y2, x3, y3, x4, y4)
|
938
|
-
@painter__.line x1, y1, x2, y2, x3, y3, x4, y4, loop: true
|
939
|
-
nil
|
940
|
-
end
|
779
|
+
# Mode for rectMode() and ellipseMode().
|
780
|
+
#
|
781
|
+
RADIUS = :RADIUS
|
941
782
|
|
942
|
-
|
943
|
-
|
944
|
-
# @param cx1 [Numeric] horizontal position of beginning control point
|
945
|
-
# @param cy1 [Numeric] vertical position of beginning control point
|
946
|
-
# @param x1 [Numeric] horizontal position of first point
|
947
|
-
# @param y1 [Numeric] vertical position of first point
|
948
|
-
# @param x2 [Numeric] horizontal position of second point
|
949
|
-
# @param y2 [Numeric] vertical position of second point
|
950
|
-
# @param cx2 [Numeric] horizontal position of ending control point
|
951
|
-
# @param cy2 [Numeric] vertical position of ending control point
|
952
|
-
#
|
953
|
-
# @return [nil] nil
|
954
|
-
#
|
955
|
-
def curve (cx1, cy1, x1, y1, x2, y2, cx2, cy2)
|
956
|
-
@painter__.curve cx1, cy1, x1, y1, x2, y2, cx2, cy2
|
957
|
-
nil
|
958
|
-
end
|
783
|
+
# Mode for textAlign().
|
784
|
+
LEFT = :LEFT
|
959
785
|
|
960
|
-
|
961
|
-
|
962
|
-
# @param x1 [Numeric] horizontal position of first point
|
963
|
-
# @param y1 [Numeric] vertical position of first point
|
964
|
-
# @param cx1 [Numeric] horizontal position of first control point
|
965
|
-
# @param cy1 [Numeric] vertical position of first control point
|
966
|
-
# @param cx2 [Numeric] horizontal position of second control point
|
967
|
-
# @param cy2 [Numeric] vertical position of second control point
|
968
|
-
# @param x2 [Numeric] horizontal position of second point
|
969
|
-
# @param y2 [Numeric] vertical position of second point
|
970
|
-
#
|
971
|
-
# @return [nil] nil
|
972
|
-
#
|
973
|
-
def bezier (x1, y1, cx1, cy1, cx2, cy2, x2, y2)
|
974
|
-
@painter__.bezier x1, y1, cx1, cy1, cx2, cy2, x2, y2
|
975
|
-
nil
|
976
|
-
end
|
786
|
+
# Mode for textAlign().
|
787
|
+
RIGHT = :RIGHT
|
977
788
|
|
978
|
-
|
979
|
-
|
980
|
-
# @overload text(str)
|
981
|
-
# @overload text(str, x, y)
|
982
|
-
#
|
983
|
-
# @param str [String] text to draw
|
984
|
-
# @param x [Numeric] horizontal position of the text
|
985
|
-
# @param y [Numeric] vertical position of the text
|
986
|
-
#
|
987
|
-
# @return [nil] nil
|
988
|
-
#
|
989
|
-
def text (str, x, y)
|
990
|
-
@painter__.text str, x, y
|
991
|
-
nil
|
992
|
-
end
|
789
|
+
# Mode for textAlign().
|
790
|
+
TOP = :TOP
|
993
791
|
|
994
|
-
|
995
|
-
|
996
|
-
# @overload image(img, a, b)
|
997
|
-
# @overload image(img, a, b, c, d)
|
998
|
-
#
|
999
|
-
# @param img [Image] image to draw
|
1000
|
-
# @param a [Numeric] horizontal position of the image
|
1001
|
-
# @param b [Numeric] vertical position of the image
|
1002
|
-
# @param c [Numeric] width of the image
|
1003
|
-
# @param d [Numeric] height of the image
|
1004
|
-
#
|
1005
|
-
# @return [nil] nil
|
1006
|
-
#
|
1007
|
-
def image (img, a, b, c = nil, d = nil)
|
1008
|
-
x, y, w, h = toXYWH__ @imageMode__, a, b, c || img.width, d || img.height
|
1009
|
-
@painter__.image img.to_internal__, x, y, w, h
|
1010
|
-
nil
|
1011
|
-
end
|
792
|
+
# Mode for textAlign().
|
793
|
+
BOTTOM = :BOTTOM
|
1012
794
|
|
1013
|
-
|
1014
|
-
|
1015
|
-
# @overload copy(sx, sy, sw, sh, dx, dy, dw, dh)
|
1016
|
-
# @overload copy(img, sx, sy, sw, sh, dx, dy, dw, dh)
|
1017
|
-
#
|
1018
|
-
# @param img [Image] image for copy source
|
1019
|
-
# @param sx [Numrtic] x position of source region
|
1020
|
-
# @param sy [Numrtic] y position of source region
|
1021
|
-
# @param sw [Numrtic] width of source region
|
1022
|
-
# @param sh [Numrtic] height of source region
|
1023
|
-
# @param dx [Numrtic] x position of destination region
|
1024
|
-
# @param dy [Numrtic] y position of destination region
|
1025
|
-
# @param dw [Numrtic] width of destination region
|
1026
|
-
# @param dh [Numrtic] height of destination region
|
1027
|
-
#
|
1028
|
-
# @return [nil] nil
|
1029
|
-
#
|
1030
|
-
def copy (img = nil, sx, sy, sw, sh, dx, dy, dw, dh)
|
1031
|
-
src = img&.to_internal__ || @window__.canvas
|
1032
|
-
@painter__.image src, sx, sy, sw, sh, dx, dy, dw, dh
|
1033
|
-
end
|
795
|
+
# Mode for textAlign().
|
796
|
+
BASELINE = :BASELINE
|
1034
797
|
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
# @param y [Numeric] vertical transformation
|
1039
|
-
#
|
1040
|
-
# @return [nil] nil
|
1041
|
-
#
|
1042
|
-
def translate (x, y)
|
1043
|
-
@painter__.translate x, y
|
1044
|
-
nil
|
1045
|
-
end
|
798
|
+
# Mode for strokeCap().
|
799
|
+
#
|
800
|
+
BUTT = :butt
|
1046
801
|
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
# @overload scale(x, y)
|
1051
|
-
#
|
1052
|
-
# @param s [Numeric] horizontal and vertical scale
|
1053
|
-
# @param x [Numeric] horizontal scale
|
1054
|
-
# @param y [Numeric] vertical scale
|
1055
|
-
#
|
1056
|
-
# @return [nil] nil
|
1057
|
-
#
|
1058
|
-
def scale (x, y)
|
1059
|
-
@painter__.scale x, y
|
1060
|
-
nil
|
1061
|
-
end
|
802
|
+
# Mode for strokeJoin().
|
803
|
+
#
|
804
|
+
MITER = :miter
|
1062
805
|
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
#
|
1067
|
-
# @return [nil] nil
|
1068
|
-
#
|
1069
|
-
def rotate (angle)
|
1070
|
-
@painter__.rotate toAngle__ angle
|
1071
|
-
nil
|
1072
|
-
end
|
806
|
+
# Mode for strokeCap() and strokeJoin().
|
807
|
+
#
|
808
|
+
ROUND = :round
|
1073
809
|
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
810
|
+
# Mode for strokeCap() and strokeJoin().
|
811
|
+
#
|
812
|
+
SQUARE = :square
|
813
|
+
|
814
|
+
def setup__ (painter)
|
815
|
+
@painter__ = painter
|
816
|
+
@painter__.miter_limit = 10
|
817
|
+
|
818
|
+
@drawing = false
|
819
|
+
@hsbColor__ = false
|
820
|
+
@colorMaxes__ = [1.0] * 4
|
821
|
+
@angleScale__ = 1.0
|
822
|
+
@rectMode__ = nil
|
823
|
+
@ellipseMode__ = nil
|
824
|
+
@imageMode__ = nil
|
825
|
+
@textAlignH__ = nil
|
826
|
+
@textAlignV__ = nil
|
827
|
+
@matrixStack__ = []
|
828
|
+
@styleStack__ = []
|
829
|
+
|
830
|
+
colorMode RGB, 255
|
831
|
+
angleMode RADIANS
|
832
|
+
rectMode CORNER
|
833
|
+
ellipseMode CENTER
|
834
|
+
imageMode CORNER
|
835
|
+
textAlign LEFT
|
836
|
+
|
837
|
+
fill 255
|
838
|
+
stroke 0
|
1083
839
|
end
|
1084
|
-
nil
|
1085
|
-
end
|
1086
840
|
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
raise "matrix stack underflow" if @matrixStack__.empty?
|
1093
|
-
@painter__.matrix = @matrixStack__.pop
|
1094
|
-
nil
|
1095
|
-
end
|
841
|
+
def beginDraw ()
|
842
|
+
@matrixStack__.clear
|
843
|
+
@styleStack__.clear
|
844
|
+
@drawing = true
|
845
|
+
end
|
1096
846
|
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
#
|
1101
|
-
def resetMatrix ()
|
1102
|
-
@painter__.matrix = 1
|
1103
|
-
nil
|
1104
|
-
end
|
847
|
+
def endDraw ()
|
848
|
+
@drawing = false
|
849
|
+
end
|
1105
850
|
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
851
|
+
def width ()
|
852
|
+
@image__.width
|
853
|
+
end
|
854
|
+
|
855
|
+
def height ()
|
856
|
+
@image__.height
|
857
|
+
end
|
858
|
+
|
859
|
+
# Sets color mode and max color values.
|
860
|
+
#
|
861
|
+
# @overload colorMode(mode)
|
862
|
+
# @overload colorMode(mode, max)
|
863
|
+
# @overload colorMode(mode, max1, max2, max3)
|
864
|
+
# @overload colorMode(mode, max1, max2, max3, maxA)
|
865
|
+
#
|
866
|
+
# @param mode [RGB, HSB] RGB or HSB
|
867
|
+
# @param max [Numeric] max values for all color values
|
868
|
+
# @param max1 [Numeric] max value for red or hue
|
869
|
+
# @param max2 [Numeric] max value for green or saturation
|
870
|
+
# @param max3 [Numeric] max value for blue or brightness
|
871
|
+
# @param maxA [Numeric] max value for alpha
|
872
|
+
#
|
873
|
+
# @return [nil] nil
|
874
|
+
#
|
875
|
+
def colorMode (mode, *maxes)
|
876
|
+
mode = mode.upcase.to_sym
|
877
|
+
raise ArgumentError, "invalid color mode: #{mode}" unless [RGB, HSB].include?(mode)
|
878
|
+
raise ArgumentError unless [0, 1, 3, 4].include?(maxes.size)
|
879
|
+
|
880
|
+
@hsbColor__ = mode == HSB
|
881
|
+
case maxes.size
|
882
|
+
when 1 then @colorMaxes__ = [maxes.first.to_f] * 4
|
883
|
+
when 3, 4 then @colorMaxes__[0...maxes.size] = maxes.map &:to_f
|
884
|
+
end
|
885
|
+
nil
|
886
|
+
end
|
887
|
+
|
888
|
+
# @private
|
889
|
+
private def toRGBA__ (*args)
|
890
|
+
a, b, c, d = args
|
891
|
+
return parseColor__(a, b || alphaMax__) if a.kind_of?(String)
|
892
|
+
|
893
|
+
rgba = case args.size
|
894
|
+
when 1, 2 then [a, a, a, b || alphaMax__]
|
895
|
+
when 3, 4 then [a, b, c, d || alphaMax__]
|
896
|
+
else raise ArgumentError
|
897
|
+
end
|
898
|
+
rgba = rgba.map.with_index {|value, i| value / @colorMaxes__[i]}
|
899
|
+
color = @hsbColor__ ? Rays::Color.hsv(*rgba) : Rays::Color.new(*rgba)
|
900
|
+
color.to_a
|
901
|
+
end
|
902
|
+
|
903
|
+
# @private
|
904
|
+
private def parseColor__ (str, alpha)
|
905
|
+
result = str.match /^\s*##{'([0-9a-f]{2})' * 3}\s*$/i
|
906
|
+
raise ArgumentError, "invalid color code: '#{str}'" unless result
|
907
|
+
|
908
|
+
rgb = result[1..3].map.with_index {|hex, i| hex.to_i(16) / 255.0}
|
909
|
+
return *rgb, (alpha / alphaMax__)
|
910
|
+
end
|
911
|
+
|
912
|
+
# @private
|
913
|
+
private def alphaMax__ ()
|
914
|
+
@colorMaxes__[3]
|
915
|
+
end
|
916
|
+
|
917
|
+
# Sets angle mode.
|
918
|
+
#
|
919
|
+
# @param mode [RADIANS, DEGREES] RADIANS or DEGREES
|
920
|
+
#
|
921
|
+
# @return [nil] nil
|
922
|
+
#
|
923
|
+
def angleMode (mode)
|
924
|
+
@angleScale__ = case mode.upcase.to_sym
|
925
|
+
when RADIANS then RAD2DEG__
|
926
|
+
when DEGREES then 1.0
|
927
|
+
else raise ArgumentError, "invalid angle mode: #{mode}"
|
928
|
+
end
|
929
|
+
nil
|
930
|
+
end
|
931
|
+
|
932
|
+
# @private
|
933
|
+
protected def toAngle__ (angle)
|
934
|
+
angle * @angleScale__
|
935
|
+
end
|
936
|
+
|
937
|
+
# Sets rect mode. Default is CORNER.
|
938
|
+
#
|
939
|
+
# CORNER -> rect(left, top, width, height)
|
940
|
+
# CORNERS -> rect(left, top, right, bottom)
|
941
|
+
# CENTER -> rect(center_x, center_y, width, height)
|
942
|
+
# RADIUS -> rect(center_x, center_y, radius_h, radius_v)
|
943
|
+
#
|
944
|
+
# @param mode [CORNER, CORNERS, CENTER, RADIUS]
|
945
|
+
#
|
946
|
+
# @return [nil] nil
|
947
|
+
#
|
948
|
+
def rectMode (mode)
|
949
|
+
@rectMode__ = mode
|
950
|
+
end
|
951
|
+
|
952
|
+
# Sets ellipse mode. Default is CENTER.
|
953
|
+
#
|
954
|
+
# CORNER -> ellipse(left, top, width, height)
|
955
|
+
# CORNERS -> ellipse(left, top, right, bottom)
|
956
|
+
# CENTER -> ellipse(center_x, center_y, width, height)
|
957
|
+
# RADIUS -> ellipse(center_x, center_y, radius_h, radius_v)
|
958
|
+
#
|
959
|
+
# @param mode [CORNER, CORNERS, CENTER, RADIUS]
|
960
|
+
#
|
961
|
+
# @return [nil] nil
|
962
|
+
#
|
963
|
+
def ellipseMode (mode)
|
964
|
+
@ellipseMode__ = mode
|
965
|
+
end
|
966
|
+
|
967
|
+
# Sets image mode. Default is CORNER.
|
968
|
+
#
|
969
|
+
# CORNER -> image(img, left, top, width, height)
|
970
|
+
# CORNERS -> image(img, left, top, right, bottom)
|
971
|
+
# CENTER -> image(img, center_x, center_y, width, height)
|
972
|
+
#
|
973
|
+
# @param mode [CORNER, CORNERS, CENTER]
|
974
|
+
#
|
975
|
+
# @return [nil] nil
|
976
|
+
#
|
977
|
+
def imageMode (mode)
|
978
|
+
@imageMode__ = mode
|
979
|
+
end
|
980
|
+
|
981
|
+
# @private
|
982
|
+
private def toXYWH__ (mode, a, b, c, d)
|
983
|
+
case mode
|
984
|
+
when CORNER then [a, b, c, d]
|
985
|
+
when CORNERS then [a, b, c - a, d - b]
|
986
|
+
when CENTER then [a - c / 2.0, b - d / 2.0, c, d]
|
987
|
+
when RADIUS then [a - c, b - d, c * 2, d * 2]
|
988
|
+
else raise ArgumentError # ToDo: refine error message
|
989
|
+
end
|
990
|
+
end
|
991
|
+
|
992
|
+
# Sets fill color.
|
993
|
+
#
|
994
|
+
# @overload fill(rgb)
|
995
|
+
# @overload fill(rgb, alpha)
|
996
|
+
# @overload fill(gray)
|
997
|
+
# @overload fill(gray, alpha)
|
998
|
+
# @overload fill(r, g, b)
|
999
|
+
# @overload fill(r, g, b, alpha)
|
1000
|
+
#
|
1001
|
+
# @param rgb [String] color code like '#00AAFF'
|
1002
|
+
# @param gray [Integer] gray value (0..255)
|
1003
|
+
# @param r [Integer] red value (0..255)
|
1004
|
+
# @param g [Integer] green value (0..255)
|
1005
|
+
# @param b [Integer] blue value (0..255)
|
1006
|
+
# @param alpha [Integer] alpha value (0..255)
|
1007
|
+
#
|
1008
|
+
# @return [nil] nil
|
1009
|
+
#
|
1010
|
+
def fill (*args)
|
1011
|
+
@painter__.fill(*toRGBA__(*args))
|
1012
|
+
nil
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
# Sets stroke color.
|
1016
|
+
#
|
1017
|
+
# @overload stroke(rgb)
|
1018
|
+
# @overload stroke(rgb, alpha)
|
1019
|
+
# @overload stroke(gray)
|
1020
|
+
# @overload stroke(gray, alpha)
|
1021
|
+
# @overload stroke(r, g, b)
|
1022
|
+
# @overload stroke(r, g, b, alpha)
|
1023
|
+
#
|
1024
|
+
# @param rgb [String] color code like '#00AAFF'
|
1025
|
+
# @param gray [Integer] gray value (0..255)
|
1026
|
+
# @param r [Integer] red value (0..255)
|
1027
|
+
# @param g [Integer] green value (0..255)
|
1028
|
+
# @param b [Integer] blue value (0..255)
|
1029
|
+
# @param alpha [Integer] alpha value (0..255)
|
1030
|
+
#
|
1031
|
+
# @return [nil] nil
|
1032
|
+
#
|
1033
|
+
def stroke (*args)
|
1034
|
+
@painter__.stroke(*toRGBA__(*args))
|
1035
|
+
nil
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
# Sets stroke weight.
|
1039
|
+
#
|
1040
|
+
# @param weight [Numeric] width of stroke
|
1041
|
+
#
|
1042
|
+
# @return [nil] nil
|
1043
|
+
#
|
1044
|
+
def strokeWeight (weight)
|
1045
|
+
@painter__.stroke_width weight
|
1046
|
+
nil
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
# Sets stroke cap mode.
|
1050
|
+
#
|
1051
|
+
# @param cap [BUTT, ROUND, SQUARE]
|
1052
|
+
#
|
1053
|
+
# @return [nil] nil
|
1054
|
+
#
|
1055
|
+
def strokeCap (cap)
|
1056
|
+
@painter__.stroke_cap cap
|
1057
|
+
nil
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
# Sets stroke join mode.
|
1061
|
+
#
|
1062
|
+
# @param join [MITER, ROUND, SQUARE]
|
1063
|
+
#
|
1064
|
+
# @return [nil] nil
|
1065
|
+
#
|
1066
|
+
def strokeJoin (join)
|
1067
|
+
@painter__.stroke_join join
|
1068
|
+
nil
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
# Disables filling.
|
1072
|
+
#
|
1073
|
+
# @return [nil] nil
|
1074
|
+
#
|
1075
|
+
def noFill ()
|
1076
|
+
@painter__.fill nil
|
1077
|
+
nil
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
# Disables drawing stroke.
|
1081
|
+
#
|
1082
|
+
# @return [nil] nil
|
1083
|
+
#
|
1084
|
+
def noStroke ()
|
1085
|
+
@painter__.stroke nil
|
1086
|
+
nil
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
# Sets font.
|
1090
|
+
#
|
1091
|
+
# @param name [String] font name
|
1092
|
+
# @param size [Numeric] font size (max 256)
|
1093
|
+
#
|
1094
|
+
# @return [Font] current font
|
1095
|
+
#
|
1096
|
+
def textFont (name = nil, size = nil)
|
1097
|
+
setFont__ name, size if name || size
|
1098
|
+
Font.new @painter__.font
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
# Sets text size.
|
1102
|
+
#
|
1103
|
+
# @param size [Numeric] font size (max 256)
|
1104
|
+
#
|
1105
|
+
# @return [nil] nil
|
1106
|
+
#
|
1107
|
+
def textSize (size)
|
1108
|
+
setFont__ @painter__.font.name, size
|
1109
|
+
nil
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
def textWidth (str)
|
1113
|
+
@painter__.font.width str
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
def textAscent ()
|
1117
|
+
@painter__.font.ascent
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
def textDescent ()
|
1121
|
+
@painter__.font.descent
|
1122
|
+
end
|
1123
|
+
|
1124
|
+
def textAlign (horizontal, vertical = BASELINE)
|
1125
|
+
@textAlignH__ = horizontal
|
1126
|
+
@textAlignV__ = vertical
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
# @private
|
1130
|
+
def setFont__ (name, size)
|
1131
|
+
size = 256 if size && size > 256
|
1132
|
+
@painter__.font name, size
|
1133
|
+
end
|
1134
|
+
|
1135
|
+
# Clears screen.
|
1136
|
+
#
|
1137
|
+
# @overload background(str)
|
1138
|
+
# @overload background(str, alpha)
|
1139
|
+
# @overload background(gray)
|
1140
|
+
# @overload background(gray, alpha)
|
1141
|
+
# @overload background(r, g, b)
|
1142
|
+
# @overload background(r, g, b, alpha)
|
1143
|
+
#
|
1144
|
+
# @param str [String] color code like '#00AAFF'
|
1145
|
+
# @param gray [Integer] gray value (0..255)
|
1146
|
+
# @param r [Integer] red value (0..255)
|
1147
|
+
# @param g [Integer] green value (0..255)
|
1148
|
+
# @param b [Integer] blue value (0..255)
|
1149
|
+
# @param alpha [Integer] alpha value (0..255)
|
1150
|
+
#
|
1151
|
+
# @return [nil] nil
|
1152
|
+
#
|
1153
|
+
def background (*args)
|
1154
|
+
assertDrawing__
|
1155
|
+
rgba = toRGBA__ *args
|
1156
|
+
if rgba[3] == 1
|
1157
|
+
@painter__.background *rgba
|
1158
|
+
else
|
1159
|
+
@painter__.push fill: rgba, stroke: nil do |_|
|
1160
|
+
@painter__.rect 0, 0, width, height
|
1161
|
+
end
|
1162
|
+
end
|
1163
|
+
nil
|
1164
|
+
end
|
1165
|
+
|
1166
|
+
# Draws a point.
|
1167
|
+
#
|
1168
|
+
# @param x [Numeric] horizontal position
|
1169
|
+
# @param y [Numeric] vertical position
|
1170
|
+
#
|
1171
|
+
# @return [nil] nil
|
1172
|
+
#
|
1173
|
+
def point (x, y)
|
1174
|
+
assertDrawing__
|
1175
|
+
w = @painter__.stroke_width
|
1176
|
+
w = 1 if w == 0
|
1177
|
+
@painter__.ellipse x - (w / 2.0), y - (w / 2.0), w, w
|
1178
|
+
nil
|
1179
|
+
end
|
1180
|
+
|
1181
|
+
# Draws a line.
|
1182
|
+
#
|
1183
|
+
# @param x1 [Numeric] horizontal position of first point
|
1184
|
+
# @param y1 [Numeric] vertical position of first point
|
1185
|
+
# @param x2 [Numeric] horizontal position of second point
|
1186
|
+
# @param y2 [Numeric] vertical position of second point
|
1187
|
+
#
|
1188
|
+
# @return [nil] nil
|
1189
|
+
#
|
1190
|
+
def line (x1, y1, x2, y2)
|
1191
|
+
assertDrawing__
|
1192
|
+
@painter__.line x1, y1, x2, y2
|
1193
|
+
nil
|
1194
|
+
end
|
1195
|
+
|
1196
|
+
# Draws a rectangle.
|
1197
|
+
#
|
1198
|
+
# @overload rect(a, b, c, d)
|
1199
|
+
# @overload rect(a, b, c, d, r)
|
1200
|
+
# @overload rect(a, b, c, d, tl, tr, br, bl)
|
1201
|
+
#
|
1202
|
+
# @param a [Numeric] horizontal position of the shape by default
|
1203
|
+
# @param b [Numeric] vertical position of the shape by default
|
1204
|
+
# @param c [Numeric] width of the shape by default
|
1205
|
+
# @param d [Numeric] height of the shape by default
|
1206
|
+
# @param r [Numeric] radius for all corners
|
1207
|
+
# @param tl [Numeric] radius for top-left corner
|
1208
|
+
# @param tr [Numeric] radius for top-right corner
|
1209
|
+
# @param br [Numeric] radius for bottom-right corner
|
1210
|
+
# @param bl [Numeric] radius for bottom-left corner
|
1211
|
+
#
|
1212
|
+
# @return [nil] nil
|
1213
|
+
#
|
1214
|
+
def rect (a, b, c, d, *args)
|
1215
|
+
assertDrawing__
|
1216
|
+
x, y, w, h = toXYWH__ @rectMode__, a, b, c, d
|
1217
|
+
case args.size
|
1218
|
+
when 0 then @painter__.rect x, y, w, h
|
1219
|
+
when 1 then @painter__.rect x, y, w, h, round: args[0]
|
1220
|
+
when 4 then @painter__.rect x, y, w, h, lt: args[0], rt: args[1], rb: args[2], lb: args[3]
|
1221
|
+
else raise ArgumentError # ToDo: refine error message
|
1222
|
+
end
|
1223
|
+
nil
|
1224
|
+
end
|
1225
|
+
|
1226
|
+
# Draws an ellipse.
|
1227
|
+
#
|
1228
|
+
# @param a [Numeric] horizontal position of the shape
|
1229
|
+
# @param b [Numeric] vertical position of the shape
|
1230
|
+
# @param c [Numeric] width of the shape
|
1231
|
+
# @param d [Numeric] height of the shape
|
1232
|
+
#
|
1233
|
+
# @return [nil] nil
|
1234
|
+
#
|
1235
|
+
def ellipse (a, b, c, d)
|
1236
|
+
assertDrawing__
|
1237
|
+
x, y, w, h = toXYWH__ @ellipseMode__, a, b, c, d
|
1238
|
+
@painter__.ellipse x, y, w, h
|
1239
|
+
nil
|
1240
|
+
end
|
1241
|
+
|
1242
|
+
# Draws a circle.
|
1243
|
+
#
|
1244
|
+
# @param x [Numeric] horizontal position of the shape
|
1245
|
+
# @param y [Numeric] vertical position of the shape
|
1246
|
+
# @param extent [Numeric] width and height of the shape
|
1247
|
+
#
|
1248
|
+
# @return [nil] nil
|
1249
|
+
#
|
1250
|
+
def circle (x, y, extent)
|
1251
|
+
ellipse x, y, extent, extent
|
1252
|
+
end
|
1253
|
+
|
1254
|
+
# Draws an arc.
|
1255
|
+
#
|
1256
|
+
# @param a [Numeric] horizontal position of the shape
|
1257
|
+
# @param b [Numeric] vertical position of the shape
|
1258
|
+
# @param c [Numeric] width of the shape
|
1259
|
+
# @param d [Numeric] height of the shape
|
1260
|
+
# @param start [Numeric] angle to start the arc
|
1261
|
+
# @param stop [Numeric] angle to stop the arc
|
1262
|
+
#
|
1263
|
+
# @return [nil] nil
|
1264
|
+
#
|
1265
|
+
def arc (a, b, c, d, start, stop)
|
1266
|
+
assertDrawing__
|
1267
|
+
x, y, w, h = toXYWH__ @ellipseMode__, a, b, c, d
|
1268
|
+
start = toAngle__ start
|
1269
|
+
stop = toAngle__ stop
|
1270
|
+
@painter__.ellipse x, y, w, h, from: start, to: stop
|
1271
|
+
nil
|
1272
|
+
end
|
1273
|
+
|
1274
|
+
# Draws a square.
|
1275
|
+
#
|
1276
|
+
# @param x [Numeric] horizontal position of the shape
|
1277
|
+
# @param y [Numeric] vertical position of the shape
|
1278
|
+
# @param extent [Numeric] width and height of the shape
|
1279
|
+
#
|
1280
|
+
# @return [nil] nil
|
1281
|
+
#
|
1282
|
+
def square (x, y, extent)
|
1283
|
+
rect x, y, extent, extent
|
1284
|
+
end
|
1285
|
+
|
1286
|
+
# Draws a triangle.
|
1287
|
+
#
|
1288
|
+
# @param x1 [Numeric] horizontal position of first point
|
1289
|
+
# @param y1 [Numeric] vertical position of first point
|
1290
|
+
# @param x2 [Numeric] horizontal position of second point
|
1291
|
+
# @param y2 [Numeric] vertical position of second point
|
1292
|
+
# @param x3 [Numeric] horizontal position of third point
|
1293
|
+
# @param y3 [Numeric] vertical position of third point
|
1294
|
+
#
|
1295
|
+
# @return [nil] nil
|
1296
|
+
#
|
1297
|
+
def triangle (x1, y1, x2, y2, x3, y3)
|
1298
|
+
assertDrawing__
|
1299
|
+
@painter__.line x1, y1, x2, y2, x3, y3, loop: true
|
1300
|
+
nil
|
1301
|
+
end
|
1302
|
+
|
1303
|
+
# Draws a quad.
|
1304
|
+
#
|
1305
|
+
# @param x1 [Numeric] horizontal position of first point
|
1306
|
+
# @param y1 [Numeric] vertical position of first point
|
1307
|
+
# @param x2 [Numeric] horizontal position of second point
|
1308
|
+
# @param y2 [Numeric] vertical position of second point
|
1309
|
+
# @param x3 [Numeric] horizontal position of third point
|
1310
|
+
# @param y3 [Numeric] vertical position of third point
|
1311
|
+
# @param x4 [Numeric] horizontal position of fourth point
|
1312
|
+
# @param y4 [Numeric] vertical position of fourth point
|
1313
|
+
#
|
1314
|
+
# @return [nil] nil
|
1315
|
+
#
|
1316
|
+
def quad (x1, y1, x2, y2, x3, y3, x4, y4)
|
1317
|
+
assertDrawing__
|
1318
|
+
@painter__.line x1, y1, x2, y2, x3, y3, x4, y4, loop: true
|
1319
|
+
nil
|
1320
|
+
end
|
1321
|
+
|
1322
|
+
# Draws a Catmull-Rom spline curve.
|
1323
|
+
#
|
1324
|
+
# @param cx1 [Numeric] horizontal position of beginning control point
|
1325
|
+
# @param cy1 [Numeric] vertical position of beginning control point
|
1326
|
+
# @param x1 [Numeric] horizontal position of first point
|
1327
|
+
# @param y1 [Numeric] vertical position of first point
|
1328
|
+
# @param x2 [Numeric] horizontal position of second point
|
1329
|
+
# @param y2 [Numeric] vertical position of second point
|
1330
|
+
# @param cx2 [Numeric] horizontal position of ending control point
|
1331
|
+
# @param cy2 [Numeric] vertical position of ending control point
|
1332
|
+
#
|
1333
|
+
# @return [nil] nil
|
1334
|
+
#
|
1335
|
+
def curve (cx1, cy1, x1, y1, x2, y2, cx2, cy2)
|
1336
|
+
assertDrawing__
|
1337
|
+
@painter__.curve cx1, cy1, x1, y1, x2, y2, cx2, cy2
|
1338
|
+
nil
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
# Draws a Bezier spline curve.
|
1342
|
+
#
|
1343
|
+
# @param x1 [Numeric] horizontal position of first point
|
1344
|
+
# @param y1 [Numeric] vertical position of first point
|
1345
|
+
# @param cx1 [Numeric] horizontal position of first control point
|
1346
|
+
# @param cy1 [Numeric] vertical position of first control point
|
1347
|
+
# @param cx2 [Numeric] horizontal position of second control point
|
1348
|
+
# @param cy2 [Numeric] vertical position of second control point
|
1349
|
+
# @param x2 [Numeric] horizontal position of second point
|
1350
|
+
# @param y2 [Numeric] vertical position of second point
|
1351
|
+
#
|
1352
|
+
# @return [nil] nil
|
1353
|
+
#
|
1354
|
+
def bezier (x1, y1, cx1, cy1, cx2, cy2, x2, y2)
|
1355
|
+
assertDrawing__
|
1356
|
+
@painter__.bezier x1, y1, cx1, cy1, cx2, cy2, x2, y2
|
1357
|
+
nil
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
# Draws a text.
|
1361
|
+
#
|
1362
|
+
# @overload text(str)
|
1363
|
+
# @overload text(str, x, y)
|
1364
|
+
# @overload text(str, a, b, c, d)
|
1365
|
+
#
|
1366
|
+
# @param str [String] text to draw
|
1367
|
+
# @param x [Numeric] horizontal position of the text
|
1368
|
+
# @param y [Numeric] vertical position of the text
|
1369
|
+
# @param a [Numeric] equivalent to parameters of the rect(), see rectMode()
|
1370
|
+
# @param b [Numeric] equivalent to parameters of the rect(), see rectMode()
|
1371
|
+
# @param c [Numeric] equivalent to parameters of the rect(), see rectMode()
|
1372
|
+
# @param d [Numeric] equivalent to parameters of the rect(), see rectMode()
|
1373
|
+
#
|
1374
|
+
# @return [nil] nil
|
1375
|
+
#
|
1376
|
+
def text (str, x, y, x2 = nil, y2 = nil)
|
1377
|
+
assertDrawing__
|
1378
|
+
if x2
|
1379
|
+
raise ArgumentError, "missing y2 parameter" unless y2
|
1380
|
+
x, y, w, h = toXYWH__ @rectMode__, x, y, x2, y2
|
1381
|
+
case @textAlignH__
|
1382
|
+
when RIGHT then x += w - @painter__.font.width(str)
|
1383
|
+
when CENTER then x += (w - @painter__.font.width(str)) / 2
|
1384
|
+
end
|
1385
|
+
case @textAlignV__
|
1386
|
+
when BOTTOM then y += h - @painter__.font.height
|
1387
|
+
when CENTER then y += (h - @painter__.font.height) / 2
|
1388
|
+
else
|
1389
|
+
end
|
1390
|
+
else
|
1391
|
+
y -= @painter__.font.ascent
|
1392
|
+
end
|
1393
|
+
@painter__.text str, x, y
|
1394
|
+
nil
|
1395
|
+
end
|
1396
|
+
|
1397
|
+
# Draws an image.
|
1398
|
+
#
|
1399
|
+
# @overload image(img, a, b)
|
1400
|
+
# @overload image(img, a, b, c, d)
|
1401
|
+
#
|
1402
|
+
# @param img [Image] image to draw
|
1403
|
+
# @param a [Numeric] horizontal position of the image
|
1404
|
+
# @param b [Numeric] vertical position of the image
|
1405
|
+
# @param c [Numeric] width of the image
|
1406
|
+
# @param d [Numeric] height of the image
|
1407
|
+
#
|
1408
|
+
# @return [nil] nil
|
1409
|
+
#
|
1410
|
+
def image (img, a, b, c = nil, d = nil)
|
1411
|
+
assertDrawing__
|
1412
|
+
x, y, w, h = toXYWH__ @imageMode__, a, b, c || img.width, d || img.height
|
1413
|
+
@painter__.image img.getInternal__, x, y, w, h
|
1414
|
+
nil
|
1415
|
+
end
|
1416
|
+
|
1417
|
+
# Copies image.
|
1418
|
+
#
|
1419
|
+
# @overload copy(sx, sy, sw, sh, dx, dy, dw, dh)
|
1420
|
+
# @overload copy(img, sx, sy, sw, sh, dx, dy, dw, dh)
|
1421
|
+
#
|
1422
|
+
# @param img [Image] image for copy source
|
1423
|
+
# @param sx [Numrtic] x position of source region
|
1424
|
+
# @param sy [Numrtic] y position of source region
|
1425
|
+
# @param sw [Numrtic] width of source region
|
1426
|
+
# @param sh [Numrtic] height of source region
|
1427
|
+
# @param dx [Numrtic] x position of destination region
|
1428
|
+
# @param dy [Numrtic] y position of destination region
|
1429
|
+
# @param dw [Numrtic] width of destination region
|
1430
|
+
# @param dh [Numrtic] height of destination region
|
1431
|
+
#
|
1432
|
+
# @return [nil] nil
|
1433
|
+
#
|
1434
|
+
def copy (img = nil, sx, sy, sw, sh, dx, dy, dw, dh)
|
1435
|
+
assertDrawing__
|
1436
|
+
src = img&.getInternal__ || @window__.canvas
|
1437
|
+
@painter__.image src, sx, sy, sw, sh, dx, dy, dw, dh
|
1438
|
+
end
|
1439
|
+
|
1440
|
+
# Applies translation matrix to current transformation matrix.
|
1441
|
+
#
|
1442
|
+
# @param x [Numeric] horizontal transformation
|
1443
|
+
# @param y [Numeric] vertical transformation
|
1444
|
+
#
|
1445
|
+
# @return [nil] nil
|
1446
|
+
#
|
1447
|
+
def translate (x, y)
|
1448
|
+
assertDrawing__
|
1449
|
+
@painter__.translate x, y
|
1450
|
+
nil
|
1451
|
+
end
|
1452
|
+
|
1453
|
+
# Applies scale matrix to current transformation matrix.
|
1454
|
+
#
|
1455
|
+
# @overload scale(s)
|
1456
|
+
# @overload scale(x, y)
|
1457
|
+
#
|
1458
|
+
# @param s [Numeric] horizontal and vertical scale
|
1459
|
+
# @param x [Numeric] horizontal scale
|
1460
|
+
# @param y [Numeric] vertical scale
|
1461
|
+
#
|
1462
|
+
# @return [nil] nil
|
1463
|
+
#
|
1464
|
+
def scale (x, y)
|
1465
|
+
assertDrawing__
|
1466
|
+
@painter__.scale x, y
|
1467
|
+
nil
|
1468
|
+
end
|
1469
|
+
|
1470
|
+
# Applies rotation matrix to current transformation matrix.
|
1471
|
+
#
|
1472
|
+
# @param angle [Numeric] angle for rotation
|
1473
|
+
#
|
1474
|
+
# @return [nil] nil
|
1475
|
+
#
|
1476
|
+
def rotate (angle)
|
1477
|
+
assertDrawing__
|
1478
|
+
@painter__.rotate toAngle__ angle
|
1479
|
+
nil
|
1480
|
+
end
|
1481
|
+
|
1482
|
+
# Pushes the current transformation matrix to stack.
|
1483
|
+
#
|
1484
|
+
# @return [nil] nil
|
1485
|
+
#
|
1486
|
+
def pushMatrix (&block)
|
1487
|
+
assertDrawing__
|
1488
|
+
@matrixStack__.push @painter__.matrix
|
1489
|
+
if block
|
1490
|
+
block.call
|
1491
|
+
popMatrix
|
1492
|
+
end
|
1493
|
+
nil
|
1494
|
+
end
|
1495
|
+
|
1496
|
+
# Pops the current transformation matrix from stack.
|
1497
|
+
#
|
1498
|
+
# @return [nil] nil
|
1499
|
+
#
|
1500
|
+
def popMatrix ()
|
1501
|
+
assertDrawing__
|
1502
|
+
raise "matrix stack underflow" if @matrixStack__.empty?
|
1503
|
+
@painter__.matrix = @matrixStack__.pop
|
1504
|
+
nil
|
1505
|
+
end
|
1506
|
+
|
1507
|
+
# Reset current transformation matrix with identity matrix.
|
1508
|
+
#
|
1509
|
+
# @return [nil] nil
|
1510
|
+
#
|
1511
|
+
def resetMatrix ()
|
1512
|
+
assertDrawing__
|
1513
|
+
@painter__.matrix = 1
|
1514
|
+
nil
|
1515
|
+
end
|
1516
|
+
|
1517
|
+
# Save current style values to the style stack.
|
1518
|
+
#
|
1519
|
+
# @return [nil] nil
|
1520
|
+
#
|
1521
|
+
def pushStyle (&block)
|
1522
|
+
assertDrawing__
|
1523
|
+
@styleStack__.push [
|
1524
|
+
@painter__.fill,
|
1525
|
+
@painter__.stroke,
|
1526
|
+
@painter__.stroke_width,
|
1527
|
+
@painter__.stroke_cap,
|
1528
|
+
@painter__.stroke_join,
|
1529
|
+
@painter__.font,
|
1530
|
+
@hsbColor__,
|
1531
|
+
@colorMaxes__,
|
1532
|
+
@angleScale__,
|
1533
|
+
@rectMode__,
|
1534
|
+
@ellipseMode__,
|
1535
|
+
@imageMode__
|
1536
|
+
]
|
1537
|
+
if block
|
1538
|
+
block.call
|
1539
|
+
popStyle
|
1540
|
+
end
|
1541
|
+
nil
|
1542
|
+
end
|
1543
|
+
|
1544
|
+
# Restore style values from the style stack.
|
1545
|
+
#
|
1546
|
+
# @return [nil] nil
|
1547
|
+
#
|
1548
|
+
def popStyle ()
|
1549
|
+
assertDrawing__
|
1550
|
+
raise "style stack underflow" if @styleStack__.empty?
|
1112
1551
|
@painter__.fill,
|
1113
1552
|
@painter__.stroke,
|
1114
1553
|
@painter__.stroke_width,
|
@@ -1120,246 +1559,608 @@ module RubySketch
|
|
1120
1559
|
@angleScale__,
|
1121
1560
|
@rectMode__,
|
1122
1561
|
@ellipseMode__,
|
1123
|
-
@imageMode__
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1562
|
+
@imageMode__ = @styleStack__.pop
|
1563
|
+
nil
|
1564
|
+
end
|
1565
|
+
|
1566
|
+
# Save current styles and transformations to stack.
|
1567
|
+
#
|
1568
|
+
# @return [nil] nil
|
1569
|
+
#
|
1570
|
+
def push (&block)
|
1571
|
+
pushMatrix
|
1572
|
+
pushStyle
|
1573
|
+
if block
|
1574
|
+
block.call
|
1575
|
+
pop
|
1576
|
+
end
|
1577
|
+
end
|
1578
|
+
|
1579
|
+
# Restore styles and transformations from stack.
|
1580
|
+
#
|
1581
|
+
# @return [nil] nil
|
1582
|
+
#
|
1583
|
+
def pop ()
|
1584
|
+
popMatrix
|
1127
1585
|
popStyle
|
1128
1586
|
end
|
1129
|
-
nil
|
1130
|
-
end
|
1131
1587
|
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
@angleScale__,
|
1147
|
-
@rectMode__,
|
1148
|
-
@ellipseMode__,
|
1149
|
-
@imageMode__ = @styleStack__.pop
|
1150
|
-
nil
|
1151
|
-
end
|
1152
|
-
|
1153
|
-
# Save current styles and transformations to stack.
|
1154
|
-
#
|
1155
|
-
# @return [nil] nil
|
1588
|
+
# @private
|
1589
|
+
private def getInternal__ ()
|
1590
|
+
@image__
|
1591
|
+
end
|
1592
|
+
|
1593
|
+
# @private
|
1594
|
+
private def assertDrawing__ ()
|
1595
|
+
raise "call beginDraw() before drawing" unless @drawing
|
1596
|
+
end
|
1597
|
+
|
1598
|
+
end# GraphicsContext
|
1599
|
+
|
1600
|
+
|
1601
|
+
# Draws graphics into an offscreen buffer
|
1156
1602
|
#
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1603
|
+
class Graphics
|
1604
|
+
|
1605
|
+
include GraphicsContext
|
1606
|
+
|
1607
|
+
def initialize (width, height)
|
1608
|
+
@image__ = Rays::Image.new width, height
|
1609
|
+
setup__ @image__.painter
|
1610
|
+
end
|
1611
|
+
|
1612
|
+
def beginDraw ()
|
1613
|
+
@painter__.__send__ :begin_paint
|
1614
|
+
super
|
1615
|
+
push
|
1616
|
+
end
|
1617
|
+
|
1618
|
+
def endDraw ()
|
1162
1619
|
pop
|
1620
|
+
super
|
1621
|
+
@painter__.__send__ :end_paint
|
1163
1622
|
end
|
1164
|
-
end
|
1165
1623
|
|
1166
|
-
#
|
1167
|
-
#
|
1168
|
-
# @return [nil] nil
|
1169
|
-
#
|
1170
|
-
def pop ()
|
1171
|
-
popMatrix
|
1172
|
-
popStyle
|
1173
|
-
end
|
1624
|
+
end# Graphics
|
1174
1625
|
|
1175
|
-
# Returns the perlin noise value.
|
1176
|
-
#
|
1177
|
-
# @overload noise(x)
|
1178
|
-
# @overload noise(x, y)
|
1179
|
-
# @overload noise(x, y, z)
|
1180
|
-
#
|
1181
|
-
# @param x [Numeric] horizontal point in noise space
|
1182
|
-
# @param y [Numeric] vertical point in noise space
|
1183
|
-
# @param z [Numeric] depth point in noise space
|
1184
|
-
#
|
1185
|
-
# @return [Numeric] noise value (0.0..1.0)
|
1186
|
-
#
|
1187
|
-
def noise (x, y = 0, z = 0)
|
1188
|
-
Rays.perlin(x, y, z) / 2.0 + 0.5
|
1189
|
-
end
|
1190
1626
|
|
1191
|
-
#
|
1627
|
+
# Processing context
|
1192
1628
|
#
|
1193
|
-
|
1194
|
-
# @param extension [String] type of image to load (ex. 'png')
|
1195
|
-
#
|
1196
|
-
# @return [Image] loaded image object
|
1197
|
-
#
|
1198
|
-
def loadImage (filename, extension = nil)
|
1199
|
-
filename = getImage__ filename, extension if filename =~ %r|^https?://|
|
1200
|
-
Image.new Rays::Image.load filename
|
1201
|
-
end
|
1629
|
+
module Context
|
1202
1630
|
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1631
|
+
include GraphicsContext, Math
|
1632
|
+
|
1633
|
+
@@context__ = nil
|
1634
|
+
|
1635
|
+
def self.context__ ()
|
1636
|
+
@@context__
|
1637
|
+
end
|
1638
|
+
|
1639
|
+
# @private
|
1640
|
+
def setup__ (window)
|
1641
|
+
@@context__ = self
|
1642
|
+
|
1643
|
+
@window__ = window
|
1644
|
+
@image__ = @window__.canvas
|
1645
|
+
super @window__.canvas_painter.paint {background 0.8}
|
1646
|
+
|
1647
|
+
@loop__ = true
|
1648
|
+
@redraw__ = false
|
1649
|
+
@frameCount__ = 0
|
1650
|
+
@mousePos__ =
|
1651
|
+
@mousePrevPos__ = Rays::Point.new 0
|
1652
|
+
@mousePressed__ = false
|
1653
|
+
@touches__ = []
|
1654
|
+
|
1655
|
+
@window__.before_draw = proc {beginDraw}
|
1656
|
+
@window__.after_draw = proc {endDraw}
|
1657
|
+
|
1658
|
+
drawFrame = -> {
|
1659
|
+
@image__ = @window__.canvas
|
1660
|
+
@painter__ = @window__.canvas_painter
|
1661
|
+
begin
|
1662
|
+
push
|
1663
|
+
@drawBlock__.call if @drawBlock__
|
1664
|
+
ensure
|
1665
|
+
pop
|
1666
|
+
@frameCount__ += 1
|
1667
|
+
end
|
1668
|
+
}
|
1669
|
+
|
1670
|
+
@window__.draw = proc do |e|
|
1671
|
+
if @loop__ || @redraw__
|
1672
|
+
@redraw__ = false
|
1673
|
+
drawFrame.call
|
1219
1674
|
end
|
1675
|
+
@mousePrevPos__ = @mousePos__
|
1676
|
+
end
|
1677
|
+
|
1678
|
+
updatePointerStates = -> event, pressed = nil {
|
1679
|
+
@mousePos__ = event.pos
|
1680
|
+
@mousePressed__ = pressed if pressed != nil
|
1681
|
+
@touches__ = event.positions.map {|pos| Touch.new pos.x, pos.y}
|
1682
|
+
}
|
1683
|
+
|
1684
|
+
@window__.pointer_down = proc do |e|
|
1685
|
+
updatePointerStates.call e, true
|
1686
|
+
(@touchStartedBlock__ || @mousePressedBlock__)&.call
|
1687
|
+
end
|
1688
|
+
|
1689
|
+
@window__.pointer_up = proc do |e|
|
1690
|
+
updatePointerStates.call e, false
|
1691
|
+
(@touchEndedBlock__ || @mouseReleasedBlock__)&.call
|
1692
|
+
end
|
1693
|
+
|
1694
|
+
@window__.pointer_move = proc do |e|
|
1695
|
+
updatePointerStates.call e
|
1696
|
+
(@touchMovedBlock__ || @mouseMovedBlock__)&.call
|
1697
|
+
end
|
1698
|
+
|
1699
|
+
@window__.pointer_drag = proc do |e|
|
1700
|
+
updatePointerStates.call e
|
1701
|
+
(@touchMovedBlock__ || @mouseDraggedBlock__)&.call
|
1220
1702
|
end
|
1221
1703
|
end
|
1222
|
-
path.to_s
|
1223
|
-
end
|
1224
1704
|
|
1225
|
-
|
1705
|
+
# Define setup block.
|
1706
|
+
#
|
1707
|
+
def setup (&block)
|
1708
|
+
@window__.setup = block
|
1709
|
+
nil
|
1710
|
+
end
|
1226
1711
|
|
1712
|
+
# Define draw block.
|
1713
|
+
#
|
1714
|
+
def draw (&block)
|
1715
|
+
@drawBlock__ = block if block
|
1716
|
+
nil
|
1717
|
+
end
|
1227
1718
|
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1719
|
+
def key (&block)
|
1720
|
+
@window__.key = block
|
1721
|
+
nil
|
1722
|
+
end
|
1231
1723
|
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1724
|
+
def mousePressed (&block)
|
1725
|
+
@mousePressedBlock__ = block if block
|
1726
|
+
@mousePressed__
|
1727
|
+
end
|
1236
1728
|
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
def width ()
|
1242
|
-
@image.width
|
1243
|
-
end
|
1729
|
+
def mouseReleased (&block)
|
1730
|
+
@mouseReleasedBlock__ = block if block
|
1731
|
+
nil
|
1732
|
+
end
|
1244
1733
|
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
def height ()
|
1250
|
-
@image.height
|
1251
|
-
end
|
1734
|
+
def mouseMoved (&block)
|
1735
|
+
@mouseMovedBlock__ = block if block
|
1736
|
+
nil
|
1737
|
+
end
|
1252
1738
|
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
# @param height [Numeric] height for resized image
|
1257
|
-
#
|
1258
|
-
# @return [nil] nil
|
1259
|
-
#
|
1260
|
-
def resize (width, height)
|
1261
|
-
@image = Rays::Image.new(width, height).paint do |painter|
|
1262
|
-
painter.image @image, 0, 0, width, height
|
1739
|
+
def mouseDragged (&block)
|
1740
|
+
@mouseDraggedBlock__ = block if block
|
1741
|
+
nil
|
1263
1742
|
end
|
1264
|
-
nil
|
1265
|
-
end
|
1266
1743
|
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
# @overload copy(img, sx, sy, sw, sh, dx, dy, dw, dh)
|
1271
|
-
#
|
1272
|
-
# @param img [Image] image for copy source
|
1273
|
-
# @param sx [Numrtic] x position of source region
|
1274
|
-
# @param sy [Numrtic] y position of source region
|
1275
|
-
# @param sw [Numrtic] width of source region
|
1276
|
-
# @param sh [Numrtic] height of source region
|
1277
|
-
# @param dx [Numrtic] x position of destination region
|
1278
|
-
# @param dy [Numrtic] y position of destination region
|
1279
|
-
# @param dw [Numrtic] width of destination region
|
1280
|
-
# @param dh [Numrtic] height of destination region
|
1281
|
-
#
|
1282
|
-
# @return [nil] nil
|
1283
|
-
#
|
1284
|
-
def copy (img = nil, sx, sy, sw, sh, dx, dy, dw, dh)
|
1285
|
-
img ||= self
|
1286
|
-
@image.paint do |painter|
|
1287
|
-
painter.image img.to_internal__, sx, sy, sw, sh, dx, dy, dw, dh
|
1744
|
+
def touchStarted (&block)
|
1745
|
+
@touchStartedBlock__ = block if block
|
1746
|
+
nil
|
1288
1747
|
end
|
1289
|
-
end
|
1290
1748
|
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
def save (filename)
|
1296
|
-
@image.save filename
|
1297
|
-
end
|
1749
|
+
def touchEnded (&block)
|
1750
|
+
@touchEndedBlock__ = block if block
|
1751
|
+
nil
|
1752
|
+
end
|
1298
1753
|
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1754
|
+
def touchMoved (&block)
|
1755
|
+
@touchMovedBlock__ = block if block
|
1756
|
+
nil
|
1757
|
+
end
|
1303
1758
|
|
1304
|
-
|
1759
|
+
# @private
|
1760
|
+
private def size__ (width, height)
|
1761
|
+
raise 'size() must be called on startup or setup block' if @started__
|
1305
1762
|
|
1763
|
+
@painter__.__send__ :end_paint
|
1764
|
+
@window__.__send__ :reset_canvas, width, height
|
1765
|
+
@painter__.__send__ :begin_paint
|
1306
1766
|
|
1307
|
-
|
1308
|
-
|
1309
|
-
class Processing::Font
|
1767
|
+
@auto_resize__ = false
|
1768
|
+
end
|
1310
1769
|
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
end
|
1770
|
+
def windowWidth ()
|
1771
|
+
@window__.width
|
1772
|
+
end
|
1315
1773
|
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
# @overload textBounds(str, x, y)
|
1320
|
-
# @overload textBounds(str, x, y, fontSize)
|
1321
|
-
#
|
1322
|
-
# @param str [String] text to calculate bounding box
|
1323
|
-
# @param x [Numeric] horizontal position of bounding box
|
1324
|
-
# @param y [Numeric] vertical position of bounding box
|
1325
|
-
# @param fontSize [Numeric] font size
|
1326
|
-
#
|
1327
|
-
# @return [TextBounds] bounding box for text
|
1328
|
-
#
|
1329
|
-
def textBounds (str, x = 0, y = 0, fontSize = nil)
|
1330
|
-
f = fontSize ? Rays::Font.new(@font.name, fontSize) : @font
|
1331
|
-
TextBounds.new x, y, x + f.width(str), y + f.height
|
1332
|
-
end
|
1774
|
+
def windowHeight ()
|
1775
|
+
@window__.height
|
1776
|
+
end
|
1333
1777
|
|
1334
|
-
|
1778
|
+
# Returns number of frames since program started.
|
1779
|
+
#
|
1780
|
+
# @return [Integer] total number of frames
|
1781
|
+
#
|
1782
|
+
def frameCount ()
|
1783
|
+
@frameCount__
|
1784
|
+
end
|
1335
1785
|
|
1786
|
+
# Returns number of frames per second.
|
1787
|
+
#
|
1788
|
+
# @return [Float] frames per second
|
1789
|
+
#
|
1790
|
+
def frameRate ()
|
1791
|
+
@window__.event.fps
|
1792
|
+
end
|
1336
1793
|
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1794
|
+
# Returns pixel density
|
1795
|
+
#
|
1796
|
+
# @return [Numeric] pixel density
|
1797
|
+
#
|
1798
|
+
def displayDensity ()
|
1799
|
+
@painter__.pixel_density
|
1800
|
+
end
|
1340
1801
|
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1802
|
+
# Returns mouse x position
|
1803
|
+
#
|
1804
|
+
# @return [Numeric] horizontal position of mouse
|
1805
|
+
#
|
1806
|
+
def mouseX ()
|
1807
|
+
@mousePos__.x
|
1808
|
+
end
|
1344
1809
|
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1810
|
+
# Returns mouse y position
|
1811
|
+
#
|
1812
|
+
# @return [Numeric] vertical position of mouse
|
1813
|
+
#
|
1814
|
+
def mouseY ()
|
1815
|
+
@mousePos__.y
|
1816
|
+
end
|
1348
1817
|
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1818
|
+
# Returns mouse x position in previous frame
|
1819
|
+
#
|
1820
|
+
# @return [Numeric] horizontal position of mouse
|
1821
|
+
#
|
1822
|
+
def pmouseX ()
|
1823
|
+
@mousePrevPos__.x
|
1824
|
+
end
|
1352
1825
|
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1826
|
+
# Returns mouse y position in previous frame
|
1827
|
+
#
|
1828
|
+
# @return [Numeric] vertical position of mouse
|
1829
|
+
#
|
1830
|
+
def pmouseY ()
|
1831
|
+
@mousePrevPos__.y
|
1832
|
+
end
|
1356
1833
|
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1834
|
+
# Returns array of touches
|
1835
|
+
#
|
1836
|
+
# @return [Array] Touch objects
|
1837
|
+
#
|
1838
|
+
def touches ()
|
1839
|
+
@touches__
|
1840
|
+
end
|
1841
|
+
|
1842
|
+
# Enables calling draw block on every frame.
|
1843
|
+
#
|
1844
|
+
# @return [nil] nil
|
1845
|
+
#
|
1846
|
+
def loop ()
|
1847
|
+
@loop__ = true
|
1848
|
+
end
|
1849
|
+
|
1850
|
+
# Disables calling draw block on every frame.
|
1851
|
+
#
|
1852
|
+
# @return [nil] nil
|
1853
|
+
#
|
1854
|
+
def noLoop ()
|
1855
|
+
@loop__ = false
|
1856
|
+
end
|
1857
|
+
|
1858
|
+
# Calls draw block to redraw frame.
|
1859
|
+
#
|
1860
|
+
# @return [nil] nil
|
1861
|
+
#
|
1862
|
+
def redraw ()
|
1863
|
+
@redraw__ = true
|
1864
|
+
end
|
1865
|
+
|
1866
|
+
#
|
1867
|
+
# Utility functions
|
1868
|
+
#
|
1869
|
+
|
1870
|
+
# Converts degree to radian.
|
1871
|
+
#
|
1872
|
+
# @param degree [Numeric] degree to convert
|
1873
|
+
#
|
1874
|
+
# @return [Numeric] radian
|
1875
|
+
#
|
1876
|
+
def radians (degree)
|
1877
|
+
degree * DEG2RAD__
|
1878
|
+
end
|
1879
|
+
|
1880
|
+
# Converts radian to degree.
|
1881
|
+
#
|
1882
|
+
# @param radian [Numeric] radian to convert
|
1883
|
+
#
|
1884
|
+
# @return [Numeric] degree
|
1885
|
+
#
|
1886
|
+
def degrees (radian)
|
1887
|
+
radian * RAD2DEG__
|
1888
|
+
end
|
1889
|
+
|
1890
|
+
# Returns the absolute number of the value.
|
1891
|
+
#
|
1892
|
+
# @param value [Numeric] number
|
1893
|
+
#
|
1894
|
+
# @return [Numeric] absolute number
|
1895
|
+
#
|
1896
|
+
def abs (value)
|
1897
|
+
value.abs
|
1898
|
+
end
|
1899
|
+
|
1900
|
+
# Returns the closest integer number greater than or equal to the value.
|
1901
|
+
#
|
1902
|
+
# @param value [Numeric] number
|
1903
|
+
#
|
1904
|
+
# @return [Numeric] rounded up number
|
1905
|
+
#
|
1906
|
+
def ceil (value)
|
1907
|
+
value.ceil
|
1908
|
+
end
|
1909
|
+
|
1910
|
+
# Returns the closest integer number less than or equal to the value.
|
1911
|
+
#
|
1912
|
+
# @param value [Numeric] number
|
1913
|
+
#
|
1914
|
+
# @return [Numeric] rounded down number
|
1915
|
+
#
|
1916
|
+
def floor (value)
|
1917
|
+
value.floor
|
1918
|
+
end
|
1919
|
+
|
1920
|
+
# Returns the closest integer number.
|
1921
|
+
#
|
1922
|
+
# @param value [Numeric] number
|
1923
|
+
#
|
1924
|
+
# @return [Numeric] rounded number
|
1925
|
+
#
|
1926
|
+
def round (value)
|
1927
|
+
value.round
|
1928
|
+
end
|
1929
|
+
|
1930
|
+
# Returns value raised to the power of exponent.
|
1931
|
+
#
|
1932
|
+
# @param value [Numeric] base number
|
1933
|
+
# @param exponent [Numeric] exponent number
|
1934
|
+
#
|
1935
|
+
# @return [Numeric] value ** exponent
|
1936
|
+
#
|
1937
|
+
def pow (value, exponent)
|
1938
|
+
value ** exponent
|
1939
|
+
end
|
1940
|
+
|
1941
|
+
# Returns squared value.
|
1942
|
+
#
|
1943
|
+
# @param value [Numeric] number
|
1944
|
+
#
|
1945
|
+
# @return [Numeric] squared value
|
1946
|
+
#
|
1947
|
+
def sq (value)
|
1948
|
+
value * value
|
1949
|
+
end
|
1950
|
+
|
1951
|
+
# Returns the magnitude (or length) of a vector.
|
1952
|
+
#
|
1953
|
+
# @overload mag(x, y)
|
1954
|
+
# @overload mag(x, y, z)
|
1955
|
+
#
|
1956
|
+
# @param x [Numeric] x of point
|
1957
|
+
# @param y [Numeric] y of point
|
1958
|
+
# @param z [Numeric] z of point
|
1959
|
+
#
|
1960
|
+
# @return [Numeric] magnitude
|
1961
|
+
#
|
1962
|
+
def mag (*args)
|
1963
|
+
x, y, z = *args
|
1964
|
+
case args.size
|
1965
|
+
when 2 then Math.sqrt x * x + y * y
|
1966
|
+
when 3 then Math.sqrt x * x + y * y + z * z
|
1967
|
+
else raise ArgumentError
|
1968
|
+
end
|
1969
|
+
end
|
1970
|
+
|
1971
|
+
# Returns distance between 2 points.
|
1972
|
+
#
|
1973
|
+
# @overload dist(x1, y1, x2, y2)
|
1974
|
+
# @overload dist(x1, y1, z1, x2, y2, z2)
|
1975
|
+
#
|
1976
|
+
# @param x1 [Numeric] x of first point
|
1977
|
+
# @param y1 [Numeric] y of first point
|
1978
|
+
# @param z1 [Numeric] z of first point
|
1979
|
+
# @param x2 [Numeric] x of second point
|
1980
|
+
# @param y2 [Numeric] y of second point
|
1981
|
+
# @param z2 [Numeric] z of second point
|
1982
|
+
#
|
1983
|
+
# @return [Numeric] distance between 2 points
|
1984
|
+
#
|
1985
|
+
def dist (*args)
|
1986
|
+
case args.size
|
1987
|
+
when 4
|
1988
|
+
x1, y1, x2, y2 = *args
|
1989
|
+
xx, yy = x2 - x1, y2 - y1
|
1990
|
+
Math.sqrt xx * xx + yy * yy
|
1991
|
+
when 3
|
1992
|
+
x1, y1, z1, x2, y2, z2 = *args
|
1993
|
+
xx, yy, zz = x2 - x1, y2 - y1, z2 - z1
|
1994
|
+
Math.sqrt xx * xx + yy * yy + zz * zz
|
1995
|
+
else raise ArgumentError
|
1996
|
+
end
|
1997
|
+
end
|
1998
|
+
|
1999
|
+
# Normalize the value from range start..stop into 0..1.
|
2000
|
+
#
|
2001
|
+
# @param value [Numeric] number to be normalized
|
2002
|
+
# @param start [Numeric] lower bound of the range
|
2003
|
+
# @param stop [Numeric] upper bound of the range
|
2004
|
+
#
|
2005
|
+
# @return [Numeric] normalized value between 0..1
|
2006
|
+
#
|
2007
|
+
def norm (value, start, stop)
|
2008
|
+
(value.to_f - start.to_f) / (stop.to_f - start.to_f)
|
2009
|
+
end
|
2010
|
+
|
2011
|
+
# Returns the interpolated number between range start..stop.
|
2012
|
+
#
|
2013
|
+
# @param start [Numeric] lower bound of the range
|
2014
|
+
# @param stop [Numeric] upper bound of the range
|
2015
|
+
# @param amount [Numeric] amount to interpolate
|
2016
|
+
#
|
2017
|
+
# @return [Numeric] interporated number
|
2018
|
+
#
|
2019
|
+
def lerp (start, stop, amount)
|
2020
|
+
start + (stop - start) * amount
|
2021
|
+
end
|
1361
2022
|
|
1362
|
-
|
2023
|
+
# Maps a number from range start1..stop1 to range start2..stop2.
|
2024
|
+
#
|
2025
|
+
# @param value [Numeric] number to be mapped
|
2026
|
+
# @param start1 [Numeric] lower bound of the range1
|
2027
|
+
# @param stop1 [Numeric] upper bound of the range1
|
2028
|
+
# @param start2 [Numeric] lower bound of the range2
|
2029
|
+
# @param stop2 [Numeric] upper bound of the range2
|
2030
|
+
#
|
2031
|
+
# @return [Numeric] mapped number
|
2032
|
+
#
|
2033
|
+
def map (value, start1, stop1, start2, stop2)
|
2034
|
+
lerp start2, stop2, norm(value, start1, stop1)
|
2035
|
+
end
|
2036
|
+
|
2037
|
+
# Returns minimum value.
|
2038
|
+
#
|
2039
|
+
# @overload min(a, b)
|
2040
|
+
# @overload min(a, b, c)
|
2041
|
+
# @overload min(array)
|
2042
|
+
#
|
2043
|
+
# @param a [Numeric] value to compare
|
2044
|
+
# @param b [Numeric] value to compare
|
2045
|
+
# @param c [Numeric] value to compare
|
2046
|
+
# @param array [Numeric] values to compare
|
2047
|
+
#
|
2048
|
+
# @return [Numeric] minimum value
|
2049
|
+
#
|
2050
|
+
def min (*args)
|
2051
|
+
args.flatten.min
|
2052
|
+
end
|
2053
|
+
|
2054
|
+
# Returns maximum value.
|
2055
|
+
#
|
2056
|
+
# @overload max(a, b)
|
2057
|
+
# @overload max(a, b, c)
|
2058
|
+
# @overload max(array)
|
2059
|
+
#
|
2060
|
+
# @param a [Numeric] value to compare
|
2061
|
+
# @param b [Numeric] value to compare
|
2062
|
+
# @param c [Numeric] value to compare
|
2063
|
+
# @param array [Numeric] values to compare
|
2064
|
+
#
|
2065
|
+
# @return [Numeric] maximum value
|
2066
|
+
#
|
2067
|
+
def max (*args)
|
2068
|
+
args.flatten.max
|
2069
|
+
end
|
2070
|
+
|
2071
|
+
# Constrains the number between min..max.
|
2072
|
+
#
|
2073
|
+
# @param value [Numeric] number to be constrained
|
2074
|
+
# @param min [Numeric] lower bound of the range
|
2075
|
+
# @param max [Numeric] upper bound of the range
|
2076
|
+
#
|
2077
|
+
# @return [Numeric] constrained number
|
2078
|
+
#
|
2079
|
+
def constrain (value, min, max)
|
2080
|
+
value < min ? min : (value > max ? max : value)
|
2081
|
+
end
|
2082
|
+
|
2083
|
+
# Returns the perlin noise value.
|
2084
|
+
#
|
2085
|
+
# @overload noise(x)
|
2086
|
+
# @overload noise(x, y)
|
2087
|
+
# @overload noise(x, y, z)
|
2088
|
+
#
|
2089
|
+
# @param x [Numeric] horizontal point in noise space
|
2090
|
+
# @param y [Numeric] vertical point in noise space
|
2091
|
+
# @param z [Numeric] depth point in noise space
|
2092
|
+
#
|
2093
|
+
# @return [Numeric] noise value (0.0..1.0)
|
2094
|
+
#
|
2095
|
+
def noise (x, y = 0, z = 0)
|
2096
|
+
Rays.perlin(x, y, z) / 2.0 + 0.5
|
2097
|
+
end
|
2098
|
+
|
2099
|
+
# Creates a new vector.
|
2100
|
+
#
|
2101
|
+
# @overload createVector()
|
2102
|
+
# @overload createVector(x, y)
|
2103
|
+
# @overload createVector(x, y, z)
|
2104
|
+
#
|
2105
|
+
# @param x [Numeric] x of new vector
|
2106
|
+
# @param y [Numeric] y of new vector
|
2107
|
+
# @param z [Numeric] z of new vector
|
2108
|
+
#
|
2109
|
+
# @return [Vector] new vector
|
2110
|
+
#
|
2111
|
+
def createVector (*args)
|
2112
|
+
Vector.new *args
|
2113
|
+
end
|
2114
|
+
|
2115
|
+
# Creates a new off-screen graphics context object.
|
2116
|
+
#
|
2117
|
+
# @param width [Numeric] width of graphics image
|
2118
|
+
# @param height [Numeric] height of graphics image
|
2119
|
+
#
|
2120
|
+
# @return [Graphics] graphics object
|
2121
|
+
#
|
2122
|
+
def createGraphics (width, height)
|
2123
|
+
Graphics.new width, height
|
2124
|
+
end
|
2125
|
+
|
2126
|
+
# Loads image.
|
2127
|
+
#
|
2128
|
+
# @param filename [String] file name to load image
|
2129
|
+
# @param extension [String] type of image to load (ex. 'png')
|
2130
|
+
#
|
2131
|
+
# @return [Image] loaded image object
|
2132
|
+
#
|
2133
|
+
def loadImage (filename, extension = nil)
|
2134
|
+
filename = getImage__ filename, extension if filename =~ %r|^https?://|
|
2135
|
+
Image.new Rays::Image.load filename
|
2136
|
+
end
|
2137
|
+
|
2138
|
+
# @private
|
2139
|
+
private def getImage__ (uri, ext)
|
2140
|
+
ext ||= File.extname uri
|
2141
|
+
raise "unsupported image type -- #{ext}" unless ext =~ /^\.?(png)$/i
|
2142
|
+
|
2143
|
+
tmpdir = Pathname(Dir.tmpdir) + Digest::SHA1.hexdigest(self.class.name)
|
2144
|
+
path = tmpdir + Digest::SHA1.hexdigest(uri)
|
2145
|
+
path = path.sub_ext ext
|
2146
|
+
|
2147
|
+
unless path.file?
|
2148
|
+
URI.open uri do |input|
|
2149
|
+
tmpdir.mkdir unless tmpdir.directory?
|
2150
|
+
path.open('w') do |output|
|
2151
|
+
while buf = input.read(2 ** 16)
|
2152
|
+
output.write buf
|
2153
|
+
end
|
2154
|
+
end
|
2155
|
+
end
|
2156
|
+
end
|
2157
|
+
path.to_s
|
2158
|
+
end
|
2159
|
+
|
2160
|
+
end# Context
|
2161
|
+
|
2162
|
+
|
2163
|
+
end# Processing
|
1363
2164
|
|
1364
2165
|
|
1365
2166
|
end# RubySketch
|