rubysketch 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a4fb1ce0ec59953e88fa85ffcacf60abf3773d01e7e628d02e6e5d273e5356af
4
+ data.tar.gz: d99ec6f101c8456241eddf75a0e9ca047afa10c4190c41ee8389e16b2b5c3f53
5
+ SHA512:
6
+ metadata.gz: 66d7c30df9e46e6c282226b1bfedc5a79f7121fcfa4525753de7a1aa2e1735a701ac3ce0caf6af298727f9074355a7f497bdec7a8baef6d00b05a2f246b2fa0f
7
+ data.tar.gz: cfb0138fb530d661d7a0a0f2f6e4b8dd9432719322967890b0117bb4f53c132d5c5e3e720ed1920defeea4f7ab075d645831505d396e2f1fb22df950882175da
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *~
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # RubySketch - Processing like Creative Coding Framework
2
+
3
+ by xordog@gmail.com
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ # -*- mode: ruby -*-
2
+
3
+
4
+ %w[../xot ../rucy ../rays ../reflex .]
5
+ .map {|s| File.expand_path "#{s}/lib", __dir__}
6
+ .each {|s| $:.unshift s if !$:.include?(s) && File.directory?(s)}
7
+
8
+ require 'rucy/rake'
9
+
10
+ require 'xot/module'
11
+ require 'rucy/module'
12
+ require 'rays/module'
13
+ require 'reflex/module'
14
+ require 'rubysketch/module'
15
+
16
+
17
+ MODULES = [Xot, Rucy, Rays, Reflex, RubySketch]
18
+
19
+ generate_documents
20
+ build_ruby_gem
21
+
22
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/examples/glsl.rb ADDED
@@ -0,0 +1,17 @@
1
+ %w[xot rays reflex rubysketch]
2
+ .map {|s| File.expand_path "../../#{s}/lib", __dir__}
3
+ .each {|s| $:.unshift s if !$:.include?(s) && File.directory?(s)}
4
+
5
+ require 'rubysketch'
6
+
7
+
8
+ RubySketch::GLSL.start <<END
9
+ varying vec4 v_TexCoord;
10
+ uniform vec2 resolution;
11
+ uniform float time;
12
+ void main ()
13
+ {
14
+ vec2 pos = v_TexCoord.xy / resolution;
15
+ gl_FragColor = vec4(pos, float(mod(time, 1.0)), 1);
16
+ }
17
+ END
data/examples/hello.rb ADDED
@@ -0,0 +1,11 @@
1
+ %w[xot rays reflex rubysketch]
2
+ .map {|s| File.expand_path "../../#{s}/lib", __dir__}
3
+ .each {|s| $:.unshift s if !$:.include?(s) && File.directory?(s)}
4
+
5
+ require 'rubysketch-processing'
6
+
7
+
8
+ draw do
9
+ textSize 50
10
+ text 'hello, world!', 10, 10
11
+ end
@@ -0,0 +1,35 @@
1
+ module RubySketch
2
+
3
+
4
+ # @private
5
+ class GLSL1
6
+
7
+ extend Starter
8
+
9
+ def initialize (glsl)
10
+ @shader = Reflex::Shader.new glsl
11
+ end
12
+
13
+ def on_start__ (window)
14
+ start = Time.now.to_f
15
+
16
+ window.draw = proc do |e, painter|
17
+ painter.paint do |p|
18
+ c = window.canvas
19
+ w = c.width
20
+ h = c.height
21
+ t = Time.now.to_f - start
22
+ p.shader @shader, resolution: [w, h], time: t if @shader
23
+ p.fill 1
24
+ p.rect 0, 0, w, h
25
+ end
26
+ end
27
+ end
28
+
29
+ end# GLSL1
30
+
31
+
32
+ GLSL = GLSL1
33
+
34
+
35
+ end# RubySketch
@@ -0,0 +1,23 @@
1
+ module RubySketch
2
+
3
+
4
+ module Module
5
+
6
+ module_function
7
+
8
+ def name ()
9
+ super.split('::')[-2]
10
+ end
11
+
12
+ def version ()
13
+ open(root_dir 'VERSION') {|f| f.readline.chomp}
14
+ end
15
+
16
+ def root_dir (path = '')
17
+ File.expand_path "../../#{path}", __dir__
18
+ end
19
+
20
+ end# Module
21
+
22
+
23
+ end# RubySketch
@@ -0,0 +1,773 @@
1
+ module RubySketch
2
+
3
+
4
+ # Processing compatible API v1
5
+ #
6
+ class Processing1
7
+
8
+ extend Starter
9
+
10
+ PI = Math::PI
11
+ HALF_PI = PI / 2
12
+ QUARTER_PI = PI / 4
13
+ TWO_PI = PI * 2
14
+ TAU = PI * 2
15
+
16
+ # RGB mode for colorMode() function.
17
+ #
18
+ RGB = :RGB
19
+
20
+ # HSB mode for colorMode() function.
21
+ #
22
+ HSB = :HSB
23
+
24
+ # Radian mode for angleMode() function.
25
+ #
26
+ RADIANS = :RADIANS
27
+
28
+ # Degree mode for angleMode() function.
29
+ #
30
+ DEGREES = :DEGREES
31
+
32
+ # @private
33
+ DEG2RAD__ = PI / 180.0
34
+
35
+ # @private
36
+ RAD2DEG__ = 180.0 / PI
37
+
38
+ # @private
39
+ def initialize ()
40
+ @frameCount__ = 0
41
+ @hsbColor__ = false
42
+ @colorMaxes__ = [1.0] * 4
43
+ @angleScale__ = 1.0
44
+ @mouseX__ =
45
+ @mouseY__ =
46
+ @mousePrevX__ =
47
+ @mousePrevY__ = 0
48
+ @mousePressed__ = false
49
+
50
+ colorMode RGB, 255
51
+ angleMode RADIANS
52
+ end
53
+
54
+ def on_start__ (window)
55
+ @window__ = window
56
+ @painter__ = window.canvas.painter
57
+
58
+ setupDrawBlock__
59
+ setupMousePressedBlock__
60
+ setupMouseReleasedBlock__
61
+ setupMouseMovedBlock__
62
+ setupMouseDraggedBlock__
63
+ end
64
+
65
+ def abs (value)
66
+ value.abs
67
+ end
68
+
69
+ def ceil (value)
70
+ value.ceil
71
+ end
72
+
73
+ def floor (value)
74
+ value.floor
75
+ end
76
+
77
+ def round (value)
78
+ value.round
79
+ end
80
+
81
+ # Returns minimum value.
82
+ #
83
+ # @overload min(a, b)
84
+ # @overload min(a, b, c)
85
+ # @overload min(array)
86
+ #
87
+ # @param a [Numeric] value to compare
88
+ # @param b [Numeric] value to compare
89
+ # @param c [Numeric] value to compare
90
+ # @param array [Numeric] values to compare
91
+ #
92
+ # @return [Numeric] minimum value
93
+ #
94
+ def min (*args)
95
+ args.flatten.min
96
+ end
97
+
98
+ # Returns maximum value.
99
+ #
100
+ # @overload max(a, b)
101
+ # @overload max(a, b, c)
102
+ # @overload max(array)
103
+ #
104
+ # @param a [Numeric] value to compare
105
+ # @param b [Numeric] value to compare
106
+ # @param c [Numeric] value to compare
107
+ # @param array [Numeric] values to compare
108
+ #
109
+ # @return [Numeric] maximum value
110
+ #
111
+ def max (*args)
112
+ args.flatten.max
113
+ end
114
+
115
+ def constrain (value, min, max)
116
+ value < min ? min : (value > max ? max : value)
117
+ end
118
+
119
+ # Converts degree to radian.
120
+ #
121
+ # @param degree [Numeric] degree to convert
122
+ #
123
+ # @return [Numeric] radian
124
+ #
125
+ def radians (degree)
126
+ degree * DEG2RAD__
127
+ end
128
+
129
+ # Converts radian to degree.
130
+ #
131
+ # @param radian [Numeric] radian to convert
132
+ #
133
+ # @return [Numeric] degree
134
+ #
135
+ def degrees (radian)
136
+ radian * RAD2DEG__
137
+ end
138
+
139
+ def setup (&block)
140
+ @window__.setup = block
141
+ nil
142
+ end
143
+
144
+ # @private
145
+ def setupDrawBlock__ ()
146
+ @window__.draw = proc do |e, painter|
147
+ @painter__ = painter
148
+ @painter__.paint {|_| @drawBlock__.call e} if @drawBlock__
149
+ @frameCount__ += 1
150
+ updateMousePrevPos__
151
+ end
152
+ end
153
+
154
+ def draw (&block)
155
+ @drawBlock__ = block if block
156
+ nil
157
+ end
158
+
159
+ def key (&block)
160
+ @window__.key = block
161
+ nil
162
+ end
163
+
164
+ # @private
165
+ def setupMousePressedBlock__ ()
166
+ @window__.pointer_down = proc do |e|
167
+ updateMouseState__ e.x, e.y, true
168
+ @mousePressedBlock__.call e if @mousePressedBlock__
169
+ end
170
+ end
171
+
172
+ def mousePressed (&block)
173
+ @mousePressedBlock__ = block if block
174
+ @mousePressed__
175
+ end
176
+
177
+ # @private
178
+ def setupMouseReleasedBlock__ ()
179
+ @window__.pointer_up = proc do |e|
180
+ updateMouseState__ e.x, e.y, false
181
+ @mouseReleasedBlock__.call e if @mouseReleasedBlock__
182
+ end
183
+ end
184
+
185
+ def mouseReleased (&block)
186
+ @mouseReleasedBlock__ = block if block
187
+ nil
188
+ end
189
+
190
+ # @private
191
+ def setupMouseMovedBlock__ ()
192
+ @window__.pointer_move = proc do |e|
193
+ updateMouseState__ e.x, e.y
194
+ @mouseMovedBlock__.call e if @mouseMovedBlock__
195
+ end
196
+ end
197
+
198
+ def mouseMoved (&block)
199
+ @mouseMovedBlock__ = block if block
200
+ nil
201
+ end
202
+
203
+ # @private
204
+ def setupMouseDraggedBlock__ ()
205
+ @window__.pointer_drag = proc do |e|
206
+ updateMouseState__ e.x, e.y
207
+ @mouseDraggedBlock__.call e if @mouseDraggedBlock__
208
+ end
209
+ end
210
+
211
+ def mouseDragged (&block)
212
+ @mouseDraggedBlock__ = block if block
213
+ nil
214
+ end
215
+
216
+ # @private
217
+ def updateMouseState__ (x, y, pressed = nil)
218
+ @mouseX__ = x
219
+ @mouseY__ = y
220
+ @mousePressed__ = pressed if pressed != nil
221
+ end
222
+
223
+ # @private
224
+ def updateMousePrevPos__ ()
225
+ @mousePrevX__ = @mouseX__
226
+ @mousePrevY__ = @mouseY__
227
+ end
228
+
229
+ def size (width, height)
230
+ raise 'size() must be called on startup or setup block' if @started__
231
+
232
+ @painter__.send :end_paint
233
+ reset_canvas width, height
234
+ @painter__.send :begin_paint
235
+
236
+ @auto_resize__ = false
237
+ end
238
+
239
+ def width ()
240
+ @window__.canvas.width
241
+ end
242
+
243
+ def height ()
244
+ @window__.canvas.height
245
+ end
246
+
247
+ def windowWidth ()
248
+ @window__.width
249
+ end
250
+
251
+ def windowHeight ()
252
+ @window__.height
253
+ end
254
+
255
+ # Returns number of frames since program started.
256
+ #
257
+ # @return [Integer] total number of frames
258
+ #
259
+ def frameCount ()
260
+ @frameCount__
261
+ end
262
+
263
+ # Returns number of frames per second.
264
+ #
265
+ # @return [Float] frames per second
266
+ #
267
+ def frameRate ()
268
+ @window__.event.fps
269
+ end
270
+
271
+ # Returns pixel density
272
+ #
273
+ # @return [Numeric] pixel density
274
+ #
275
+ def displayDensity ()
276
+ @painter__.pixel_density
277
+ end
278
+
279
+ # Returns mouse x position
280
+ #
281
+ # @return [Numeric] horizontal position of mouse
282
+ #
283
+ def mouseX ()
284
+ @mouseX__
285
+ end
286
+
287
+ # Returns mouse y position
288
+ #
289
+ # @return [Numeric] vertical position of mouse
290
+ #
291
+ def mouseY ()
292
+ @mouseY__
293
+ end
294
+
295
+ # Returns mouse x position in previous frame
296
+ #
297
+ # @return [Numeric] horizontal position of mouse
298
+ #
299
+ def pmouseX ()
300
+ @mousePrevX__
301
+ end
302
+
303
+ # Returns mouse y position in previous frame
304
+ #
305
+ # @return [Numeric] vertical position of mouse
306
+ #
307
+ def pmouseY ()
308
+ @mousePrevY__
309
+ end
310
+
311
+ # Sets color mode and max color values.
312
+ #
313
+ # @overload colorMode(mode)
314
+ # @overload colorMode(mode, max)
315
+ # @overload colorMode(mode, max1, max2, max3)
316
+ # @overload colorMode(mode, max1, max2, max3, maxA)
317
+ #
318
+ # @param mode [RGB, HSB] RGB or HSB
319
+ # @param max [Numeric] max values for all color values
320
+ # @param max1 [Numeric] max value for red or hue
321
+ # @param max2 [Numeric] max value for green or saturation
322
+ # @param max3 [Numeric] max value for blue or brightness
323
+ # @param maxA [Numeric] max value for alpha
324
+ #
325
+ # @return [nil] nil
326
+ #
327
+ def colorMode (mode, *maxes)
328
+ raise ArgumentError, "Invalid color mode: #{mode}" unless [RGB, HSB].include?(mode)
329
+ raise ArgumentError unless [0, 1, 3, 4].include?(maxes.size)
330
+
331
+ @hsbColor__ = mode.upcase == HSB
332
+ case maxes.size
333
+ when 1 then @colorMaxes__ = [maxes.first.to_f] * 4
334
+ when 3, 4 then @colorMaxes__[0...maxes.size] = maxes.map &:to_f
335
+ end
336
+ nil
337
+ end
338
+
339
+ # @private
340
+ def to_rgba__ (*args)
341
+ _0, _1, _2, _3 = args
342
+ return parse_color__(_0, _1 || alphaMax__) if _0.kind_of?(String)
343
+
344
+ rgba = case args.size
345
+ when 1, 2 then [_0, _0, _0, _1 || alphaMax__]
346
+ when 3, 4 then [_0, _1, _2, _3 || alphaMax__]
347
+ else raise ArgumentError
348
+ end
349
+ rgba = rgba.map.with_index {|value, i| value / @colorMaxes__[i]}
350
+ color = @hsbColor__ ? Rays::Color.hsv(*rgba) : Rays::Color.new(*rgba)
351
+ color.to_a
352
+ end
353
+
354
+ # @private
355
+ def parse_color__ (str, alpha)
356
+ result = str.match /^\s*##{'([0-9a-f]{2})' * 3}\s*$/i
357
+ raise ArgumentError, "Invalid color code: '#{str}'" unless result
358
+
359
+ rgb = result[1..3].map.with_index {|hex, i| hex.to_i(16) / @colorMaxes__[i]}
360
+ return *rgb, (alpha / alphaMax__)
361
+ end
362
+
363
+ # @private
364
+ def alphaMax__ ()
365
+ @colorMaxes__[3]
366
+ end
367
+
368
+ # Sets angle mode.
369
+ #
370
+ # @param mode [RADIANS, DEGREES] RADIANS or DEGREES
371
+ #
372
+ # @return [nil] nil
373
+ #
374
+ def angleMode (mode)
375
+ @angleScale__ = case mode
376
+ when RADIANS then RAD2DEG__
377
+ when DEGREES then 1.0
378
+ else raise ArgumentError, "Invalid angle mode: #{mode}"
379
+ end
380
+ end
381
+
382
+ # @private
383
+ def to_angle__ (angle)
384
+ angle * @angleScale__
385
+ end
386
+
387
+ # Clears screen.
388
+ #
389
+ # @overload background(str)
390
+ # @overload background(str, alpha)
391
+ # @overload background(gray)
392
+ # @overload background(gray, alpha)
393
+ # @overload background(r, g, b)
394
+ # @overload background(r, g, b, alpha)
395
+ #
396
+ # @param str [String] color code like '#00AAFF'
397
+ # @param gray [Integer] gray value (0..255)
398
+ # @param r [Integer] red value (0..255)
399
+ # @param g [Integer] green value (0..255)
400
+ # @param b [Integer] blue value (0..255)
401
+ # @param alpha [Integer] alpha value (0..255)
402
+ #
403
+ # @return [nil] nil
404
+ #
405
+ def background (*args)
406
+ @painter__.background(*to_rgba__(*args))
407
+ nil
408
+ end
409
+
410
+ # Sets fill color.
411
+ #
412
+ # @overload fill(rgb)
413
+ # @overload fill(rgb, alpha)
414
+ # @overload fill(gray)
415
+ # @overload fill(gray, alpha)
416
+ # @overload fill(r, g, b)
417
+ # @overload fill(r, g, b, alpha)
418
+ #
419
+ # @param rgb [String] color code like '#00AAFF'
420
+ # @param gray [Integer] gray value (0..255)
421
+ # @param r [Integer] red value (0..255)
422
+ # @param g [Integer] green value (0..255)
423
+ # @param b [Integer] blue value (0..255)
424
+ # @param alpha [Integer] alpha value (0..255)
425
+ #
426
+ # @return [nil] nil
427
+ #
428
+ def fill (*args)
429
+ @painter__.fill(*to_rgba__(*args))
430
+ nil
431
+ end
432
+
433
+ # Sets stroke color.
434
+ #
435
+ # @overload stroke(rgb)
436
+ # @overload stroke(rgb, alpha)
437
+ # @overload stroke(gray)
438
+ # @overload stroke(gray, alpha)
439
+ # @overload stroke(r, g, b)
440
+ # @overload stroke(r, g, b, alpha)
441
+ #
442
+ # @param rgb [String] color code like '#00AAFF'
443
+ # @param gray [Integer] gray value (0..255)
444
+ # @param r [Integer] red value (0..255)
445
+ # @param g [Integer] green value (0..255)
446
+ # @param b [Integer] blue value (0..255)
447
+ # @param alpha [Integer] alpha value (0..255)
448
+ #
449
+ # @return [nil] nil
450
+ #
451
+ def stroke (*args)
452
+ @painter__.stroke(*to_rgba__(*args))
453
+ nil
454
+ end
455
+
456
+ # Sets stroke weight.
457
+ #
458
+ # @param weight [Numeric] width of stroke
459
+ #
460
+ # @return [nil] nil
461
+ #
462
+ def strokeWeight (weight)
463
+ @painter__.stroke_width weight
464
+ nil
465
+ end
466
+
467
+ # Disables filling.
468
+ #
469
+ # @return [nil] nil
470
+ #
471
+ def noFill ()
472
+ @painter__.fill nil
473
+ nil
474
+ end
475
+
476
+ # Disables drawing stroke.
477
+ #
478
+ # @return [nil] nil
479
+ #
480
+ def noStroke ()
481
+ @painter__.stroke nil
482
+ nil
483
+ end
484
+
485
+ # Sets font.
486
+ #
487
+ # @param name [String] font name
488
+ # @param size [Numeric] font size
489
+ #
490
+ # @return [Font] current font
491
+ #
492
+ def textFont (name = nil, size = nil)
493
+ @painter__.font name, size if name || size
494
+ Font.new @painter__.font
495
+ end
496
+
497
+ # Sets text size.
498
+ #
499
+ # @param size [Numeric] font size
500
+ #
501
+ # @return [nil] nil
502
+ #
503
+ def textSize (size)
504
+ @painter__.font @painter__.font.name, size
505
+ nil
506
+ end
507
+
508
+ # Draws a line.
509
+ #
510
+ # @param x1 [Numeric] horizontal position for first point
511
+ # @param y1 [Numeric] vertical position for first point
512
+ # @param x2 [Numeric] horizontal position for second point
513
+ # @param y2 [Numeric] vertical position for second point
514
+ #
515
+ # @return [nil] nil
516
+ #
517
+ def line (x1, y1, x2, y2)
518
+ @painter__.line x1, y1, x2, y2
519
+ nil
520
+ end
521
+
522
+ # Draws a rectangle.
523
+ #
524
+ # @overload rect(x, y, w, h)
525
+ # @overload rect(x, y, w, h, r)
526
+ # @overload rect(x, y, w, h, tl, tr, br, bl)
527
+ #
528
+ # @param x [Numeric] horizontal position
529
+ # @param y [Numeric] vertical position
530
+ # @param w [Numeric] width of the shape
531
+ # @param h [Numeric] height of the shape
532
+ # @param r [Numeric] radius for all corners
533
+ # @param tl [Numeric] radius for top-left corner
534
+ # @param tr [Numeric] radius for top-right corner
535
+ # @param br [Numeric] radius for bottom-right corner
536
+ # @param bl [Numeric] radius for bottom-left corner
537
+ #
538
+ # @return [nil] nil
539
+ #
540
+ def rect (x, y, w, h, *args)
541
+ case args.size
542
+ when 0 then @painter__.rect x, y, w, h
543
+ when 1 then @painter__.rect x, y, w, h, round: args[0]
544
+ when 4 then @painter__.rect x, y, w, h, lt: args[0], rt: args[1], rb: args[2], lb: args[3]
545
+ else raise ArgumentError # ToDo: refine error message
546
+ end
547
+ nil
548
+ end
549
+
550
+ # Draws a ellipse.
551
+ #
552
+ # @param x [Numeric] horizontal position
553
+ # @param y [Numeric] vertical position
554
+ # @param w [Numeric] width of the shape
555
+ # @param h [Numeric] height of the shape
556
+ #
557
+ # @return [nil] nil
558
+ #
559
+ def ellipse (x, y, w, h = w)
560
+ @painter__.ellipse (x - w / 2.0), (y - h / 2.0), w, h
561
+ nil
562
+ end
563
+
564
+ # Draws a circle.
565
+ #
566
+ # @param x [Numeric] horizontal position
567
+ # @param y [Numeric] vertical position
568
+ # @param extent [Numeric] width and height of the shape
569
+ #
570
+ # @return [nil] nil
571
+ #
572
+ def circle (x, y, extent)
573
+ ellipse x, y, extent, extent
574
+ end
575
+
576
+ # Draws an arc.
577
+ #
578
+ # @param x [Numeric] horizontal position
579
+ # @param y [Numeric] vertical position
580
+ # @param w [Numeric] width of the shape
581
+ # @param h [Numeric] height of the shape
582
+ # @param start [Numeric] angle to start the arc
583
+ # @param stop [Numeric] angle to stop the arc
584
+ #
585
+ # @return [nil] nil
586
+ #
587
+ def arc (x, y, w, h, start, stop)
588
+ start = to_angle__ start
589
+ stop = to_angle__ stop
590
+ @painter__.ellipse x - w / 2, y - h / 2, w, h, from: start, to: stop
591
+ nil
592
+ end
593
+
594
+ # Draws a point.
595
+ #
596
+ # @param x [Numeric] horizontal position
597
+ # @param y [Numeric] vertical position
598
+ #
599
+ # @return [nil] nil
600
+ #
601
+ def point (x, y)
602
+ @painter__.rect x - 0.5, y - 0.5, 1, 1
603
+ nil
604
+ end
605
+
606
+ # Draws a text.
607
+ #
608
+ # @overload text(str)
609
+ # @overload text(str, x, y)
610
+ #
611
+ # @param str [String] text to draw
612
+ # @param x [Numeric] horizontal position
613
+ # @param y [Numeric] vertical position
614
+ #
615
+ # @return [nil] nil
616
+ #
617
+ def text (str, x = 0, y = 0)
618
+ @painter__.text str, x, y
619
+ nil
620
+ end
621
+
622
+ # Applies translation matrix to current transformation matrix.
623
+ #
624
+ # @param x [Numeric] horizontal transformation
625
+ # @param y [Numeric] vertical transformation
626
+ #
627
+ # @return [nil] nil
628
+ #
629
+ def translate (x, y)
630
+ @painter__.translate x, y
631
+ nil
632
+ end
633
+
634
+ # Applies scale matrix to current transformation matrix.
635
+ #
636
+ # @overload scale(s)
637
+ # @overload scale(x, y)
638
+ #
639
+ # @param s [Numeric] horizontal and vertical scale
640
+ # @param x [Numeric] horizontal scale
641
+ # @param y [Numeric] vertical scale
642
+ #
643
+ # @return [nil] nil
644
+ #
645
+ def scale (x, y)
646
+ @painter__.scale x, y
647
+ nil
648
+ end
649
+
650
+ # Applies rotation matrix to current transformation matrix.
651
+ #
652
+ # @param angle [Numeric] angle for rotation
653
+ #
654
+ # @return [nil] nil
655
+ #
656
+ def rotate (angle)
657
+ @painter__.rotate to_angle__ angle
658
+ nil
659
+ end
660
+
661
+ # Pushes the current transformation matrix to stack.
662
+ #
663
+ # @return [nil] nil
664
+ #
665
+ def pushMatrix ()
666
+ @painter__.push_matrix
667
+ nil
668
+ end
669
+
670
+ # Pops the current transformation matrix from stack.
671
+ #
672
+ # @return [nil] nil
673
+ #
674
+ def popMatrix ()
675
+ @painter__.pop_matrix
676
+ nil
677
+ end
678
+
679
+ # Reset current transformation matrix with identity matrix.
680
+ #
681
+ # @return [nil] nil
682
+ #
683
+ def resetMatrix ()
684
+ @painter__.matrix = 1
685
+ nil
686
+ end
687
+
688
+ # Returns the perlin noise value.
689
+ #
690
+ # @overload noise(x)
691
+ # @overload noise(x, y)
692
+ #
693
+ # @param x [Numeric] horizontal point in noise space
694
+ # @param y [Numeric] vertical point in noise space
695
+ #
696
+ # @return [Numeric] noise value (0.0..1.0)
697
+ #
698
+ def noise (x, y = 0)
699
+ Rays.perlin(x, y) / 2.0 + 1.0
700
+ end
701
+
702
+ # Font object.
703
+ #
704
+ class Font
705
+
706
+ # Initialize font.
707
+ #
708
+ # @private
709
+ #
710
+ def initialize (font)
711
+ @font = font
712
+ end
713
+
714
+ # Returns bounding box.
715
+ #
716
+ # @overload textBounds(str)
717
+ # @overload textBounds(str, x, y)
718
+ # @overload textBounds(str, x, y, fontSize)
719
+ #
720
+ # @param str [String] text to calculate bounding box
721
+ # @param x [Numeric] horizontal position of bounding box
722
+ # @param y [Numeric] vertical position of bounding box
723
+ # @param fontSize [Numeric] font size
724
+ #
725
+ # @return [TextBounds] bounding box for text
726
+ #
727
+ def textBounds (str, x = 0, y = 0, fontSize = nil)
728
+ f = fontSize ? Rays::Font.new(@font.name, fontSize) : @font
729
+ TextBounds.new x, y, x + f.width(str), y + f.height
730
+ end
731
+
732
+ # Bounding box for text.
733
+ #
734
+ class TextBounds
735
+
736
+ # Horizontal position
737
+ #
738
+ attr_reader :x
739
+
740
+ # Vertical position
741
+ #
742
+ attr_reader :y
743
+
744
+ # Width of bounding box
745
+ #
746
+ attr_reader :w
747
+
748
+ # Height of bounding box
749
+ #
750
+ attr_reader :h
751
+
752
+ # Initialize bouding box.
753
+ #
754
+ # @param x [Numeric] horizontal position
755
+ # @param y [Numeric] vertical position
756
+ # @param w [Numeric] width of bounding box
757
+ # @param h [Numeric] height of bounding box
758
+ #
759
+ def initialize (x, y, w, h)
760
+ @x, @y, @w, @h = x, y, w, h
761
+ end
762
+
763
+ end# TextBounds
764
+
765
+ end# Font
766
+
767
+ end# Processing1
768
+
769
+
770
+ Processing = Processing1
771
+
772
+
773
+ end# RubySketch
@@ -0,0 +1,61 @@
1
+ module RubySketch
2
+
3
+
4
+ extend module Functions
5
+
6
+ def start (context, start_at_exit: false, &block)
7
+ window = Window.new
8
+
9
+ context.on_start__ window
10
+ context.instance_eval &block if block
11
+
12
+ start = proc do
13
+ Reflex.start {window.show}
14
+ end
15
+
16
+ if start_at_exit
17
+ at_exit &start unless $!
18
+ else
19
+ start.call
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def start_on_object_at_exit (object, context)
26
+ klass = context.class
27
+ methods = klass.instance_methods(false)
28
+ .reject {|name| name =~ /__$/}
29
+ consts = klass.constants
30
+ .reject {|name| name =~ /__$/}
31
+ .each_with_object({}) {|name, h| h[name] = klass.const_get name}
32
+
33
+ object.class.class_eval do
34
+ methods.each do |name|
35
+ define_method name do |*args, &block|
36
+ context.__send__ name, *args, &block
37
+ end
38
+ end
39
+ consts.each do |(name, value)|
40
+ const_set name, value
41
+ end
42
+ end
43
+
44
+ start context, start_at_exit: true
45
+ end
46
+
47
+ self
48
+
49
+ end# Functions
50
+
51
+
52
+ module Starter
53
+
54
+ def start (*args, &block)
55
+ RubySketch.start self.new(*args), start_at_exit: true, &block
56
+ end
57
+
58
+ end# Starter
59
+
60
+
61
+ end# RubySketch
@@ -0,0 +1,93 @@
1
+ module RubySketch
2
+
3
+
4
+ class Window < Reflex::Window
5
+
6
+ attr_accessor :setup, :update, :draw, :key, :motion, :resize,
7
+ :pointer_down, :pointer_up, :pointer_move, :pointer_drag
8
+
9
+ attr_accessor :auto_resize
10
+
11
+ attr_reader :canvas
12
+
13
+ def initialize (width = 500, height = 500, *args, &block)
14
+ @canvas = nil
15
+ @events = []
16
+ @auto_resize = true
17
+ @error = nil
18
+
19
+ super *args, size: [width, height] do |_|
20
+ @canvas.painter.paint do |_|
21
+ block.call if block
22
+ on_setup
23
+ end
24
+ end
25
+ end
26
+
27
+ def event ()
28
+ @events.last
29
+ end
30
+
31
+ def on_setup ()
32
+ call_block @setup, nil
33
+ end
34
+
35
+ def on_update (e)
36
+ call_block @update, e
37
+ redraw
38
+ end
39
+
40
+ def on_draw (e)
41
+ call_block @draw, e, @canvas.painter
42
+ e.painter.image @canvas if @canvas
43
+ end
44
+
45
+ def on_key (e)
46
+ call_block @key, e
47
+ end
48
+
49
+ def on_pointer (e)
50
+ block = case e.type
51
+ when :down then @pointer_down
52
+ when :up then @pointer_up
53
+ when :move then e.drag? ? @pointer_drag : @pointer_move
54
+ end
55
+ call_block block, e if block
56
+ end
57
+
58
+ def on_motion (e)
59
+ call_block @motion, e
60
+ end
61
+
62
+ def on_resize (e)
63
+ reset_canvas e.width, e.height if @auto_resize
64
+ call_block @resize, e
65
+ end
66
+
67
+ private
68
+
69
+ def reset_canvas (width, height)
70
+ return if width * height == 0
71
+ return if width == @canvas&.width && height == @canvas&.height
72
+
73
+ old = @canvas
74
+ pd = @canvas&.pixel_density || painter.pixel_density
75
+ @canvas = Rays::Image.new width, height, Rays::ColorSpace::RGBA, pd
76
+
77
+ @canvas.paint {image old} if old
78
+ end
79
+
80
+ def call_block (block, event, *args)
81
+ @events.push event
82
+ block.call event, *args if block && !@error
83
+ rescue => e
84
+ @error = e
85
+ $stderr.puts e.full_message
86
+ ensure
87
+ @events.pop
88
+ end
89
+
90
+ end# Window
91
+
92
+
93
+ end# RubySketch
@@ -0,0 +1,4 @@
1
+ require 'rubysketch'
2
+
3
+
4
+ RubySketch.__send__ :start_on_object_at_exit, self, RubySketch::Processing.new
data/lib/rubysketch.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'reflex'
2
+ require 'rubysketch/module'
3
+ require 'rubysketch/starter'
4
+ require 'rubysketch/window'
5
+ require 'rubysketch/processing'
6
+ require 'rubysketch/glsl'
@@ -0,0 +1,44 @@
1
+ # -*- mode: ruby -*-
2
+
3
+
4
+ File.expand_path('lib', __dir__)
5
+ .tap {|s| $:.unshift s if !$:.include?(s) && File.directory?(s)}
6
+
7
+ require 'rubysketch/module'
8
+
9
+
10
+ Gem::Specification.new do |s|
11
+ glob = -> *patterns do
12
+ patterns.map {|pat| Dir.glob(pat).to_a}.flatten
13
+ end
14
+
15
+ mod = RubySketch::Module
16
+ name = mod.name.downcase
17
+ rdocs = glob.call *%w[README]
18
+
19
+ s.name = name
20
+ s.summary = 'Processing like Creative Coding Framework.'
21
+ s.description = 'Creative Coding Framework have API compatible to Processing API or p5.js.'
22
+ s.version = mod.version
23
+
24
+ s.authors = %w[xordog]
25
+ s.email = 'xordog@gmail.com'
26
+ s.homepage = "https://github.com/xord/rubysketch"
27
+
28
+ s.platform = Gem::Platform::RUBY
29
+ s.required_ruby_version = '~> 2'
30
+
31
+ s.add_runtime_dependency 'yard'
32
+ s.add_runtime_dependency 'xot', '~> 0.1'
33
+ s.add_runtime_dependency 'beeps', '~> 0.1'
34
+ s.add_runtime_dependency 'rucy', '~> 0.1'
35
+ s.add_runtime_dependency 'rays', '~> 0.1'
36
+ s.add_runtime_dependency 'reflexion', '~> 0.1'
37
+
38
+ s.files = `git ls-files`.split $/
39
+ s.test_files = s.files.grep %r{^(test|spec|features)/}
40
+ s.extra_rdoc_files = rdocs.to_a
41
+ s.has_rdoc = true
42
+
43
+ s.extensions << 'Rakefile'
44
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubysketch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - xordog
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-11-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: yard
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: xot
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: beeps
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rucy
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rays
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: reflexion
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.1'
97
+ description: Creative Coding Framework have API compatible to Processing API or p5.js.
98
+ email: xordog@gmail.com
99
+ executables: []
100
+ extensions:
101
+ - Rakefile
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - README.md
106
+ - Rakefile
107
+ - VERSION
108
+ - examples/glsl.rb
109
+ - examples/hello.rb
110
+ - lib/rubysketch-processing.rb
111
+ - lib/rubysketch.rb
112
+ - lib/rubysketch/glsl.rb
113
+ - lib/rubysketch/module.rb
114
+ - lib/rubysketch/processing.rb
115
+ - lib/rubysketch/starter.rb
116
+ - lib/rubysketch/window.rb
117
+ - rubysketch.gemspec
118
+ homepage: https://github.com/xord/rubysketch
119
+ licenses: []
120
+ metadata: {}
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '2'
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubygems_version: 3.0.3
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Processing like Creative Coding Framework.
140
+ test_files: []