rubysketch 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []