rubyonacid 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +74 -6
- data/VERSION +1 -1
- data/examples/ascii.rb +45 -0
- data/examples/midi.rb +0 -2
- data/examples/quality_render.rb +46 -0
- data/examples/random_yaml.rb +51 -0
- data/examples/raw_audio.rb +0 -2
- data/examples/rinda_agent.rb +101 -38
- data/examples/wxruby.rb +158 -0
- data/generators.png +0 -0
- data/lib/rubyonacid/factories/combination.rb +66 -0
- data/lib/rubyonacid/factories/increment.rb +3 -2
- data/lib/rubyonacid/factories/loop.rb +1 -0
- data/lib/rubyonacid/factories/rinda.rb +9 -2
- data/lib/rubyonacid/factory.rb +9 -0
- data/spec/factories/combination_spec.rb +101 -0
- data/spec/{generators → factories}/constant_spec.rb +0 -1
- data/spec/{generators → factories}/flash_spec.rb +0 -0
- data/spec/{generators → factories}/increment_spec.rb +0 -1
- data/spec/{generators → factories}/loop_spec.rb +0 -1
- data/spec/{generators → factories}/meta_spec.rb +0 -0
- data/spec/{generators → factories}/random_spec.rb +0 -0
- data/spec/{generators → factories}/repeat_spec.rb +0 -0
- data/spec/{generators → factories}/rinda_spec.rb +8 -1
- data/spec/{generators → factories}/sine_spec.rb +0 -1
- data/spec/{generators → factories}/skip_spec.rb +0 -1
- data/spec/factory_spec.rb +59 -0
- data/spec/spec_helper.rb +3 -0
- metadata +35 -31
- data/examples/rmagick.rb +0 -59
- data/examples/test.rb +0 -95
- data/examples/test2.rb +0 -85
- data/examples/test3.rb +0 -108
- data/lib/rubyonacid/factories/modulo.rb +0 -25
- data/spec/generators/modulo_spec.rb +0 -33
data/README.textile
CHANGED
@@ -1,21 +1,89 @@
|
|
1
1
|
!http://github.com/jaymcgavren/rubyonacid/raw/master/generators.png!
|
2
2
|
|
3
|
+
|
3
4
|
h1. Ruby On Acid
|
4
5
|
|
5
|
-
A Ruby library for making trippy visuals.
|
6
|
+
A Ruby library for making trippy visuals and sounds. Need to pick locations and colors to draw in? Let one of Ruby On Acid's "factories" do it for you. Then swap out one factory for another without changing your code. Need to pick a note from a scale or a tempo? Ruby On Acid factories can do that too. And if none of the bundled factories does what you need, it's easy to write your own.
|
7
|
+
|
8
|
+
|
9
|
+
h1. Installation
|
6
10
|
|
11
|
+
<pre>
|
12
|
+
sudo gem install rubyonacid
|
13
|
+
</pre>
|
7
14
|
|
8
|
-
|
15
|
+
|
16
|
+
h1. Using Factories
|
9
17
|
|
10
18
|
The factory is the core concept of Ruby On Acid. You create a factory of a particular type, and then anywhere in your code that you need a value within a certain range, you get it from the factory. For example, if you need x and y coordinates for drawing on a 800 x 600 window, you would tell a factory that you need a value for :x from 0 to 800, and a value for :y from 0 to 600. If you later wanted to change drawing patterns, you could simply swap out factories.
|
11
19
|
|
20
|
+
<pre>
|
21
|
+
def draw(factory)
|
22
|
+
window.draw_circle(
|
23
|
+
factory.get(:x, :max => 800),
|
24
|
+
factory.get(:y, :max => 600),
|
25
|
+
factory.get(:radius, :max => 100)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
current_factory = RubyOnAcid::RandomFactory.new
|
30
|
+
10.times {draw(current_factory)}
|
31
|
+
current_factory = RubyOnAcid::LoopFactory.new
|
32
|
+
10.times {draw(current_factory)}
|
33
|
+
</pre>
|
34
|
+
|
35
|
+
See the examples directory for usage of the various factories.
|
36
|
+
|
37
|
+
|
38
|
+
h1. Writing Your Own Factories
|
39
|
+
|
40
|
+
Making new factories is easy - simply make a subclass of RubyOnAcid::Factory. Then write a get_unit() method that takes a key and returns a value between 0 and 1.
|
41
|
+
|
42
|
+
For example, here's the entire code for the bundled RandomFactory class:
|
43
|
+
|
44
|
+
<pre>
|
45
|
+
class RandomFactory < RubyOnAcid::Factory
|
46
|
+
def get_unit(key)
|
47
|
+
return rand
|
48
|
+
end
|
49
|
+
end
|
50
|
+
</pre>
|
51
|
+
|
52
|
+
Of course, when the values you're generating are random, you don't need to know what they'll be used for. For situations where you do care, you can use the "key" parameter, which is an indication from the factory user of the kind of value they need. This class tracks the previously returned value for a key and increments the next one:
|
53
|
+
|
54
|
+
<pre>
|
55
|
+
class CumulativeFactory < RubyOnAcid::Factory
|
56
|
+
def initialize
|
57
|
+
super #Be sure to call Factory's constructor if you override it!
|
58
|
+
@counters = Hash.new {|h, k| h[k] = 0.0}
|
59
|
+
end
|
60
|
+
def get_unit(key)
|
61
|
+
@counters[key] = (@counters[key] + 0.1) % 1.0
|
62
|
+
return @counters[key]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
factory = CumulativeFactory.new
|
67
|
+
puts factory.get(:x) # => 0.1
|
68
|
+
puts factory.get(:y) # => 0.1
|
69
|
+
puts factory.get(:x) # => 0.2
|
70
|
+
puts factory.get(:z) # => 0.1
|
71
|
+
</pre>
|
72
|
+
|
73
|
+
Start by looking at the code for the bundled factories in the lib/rubyonacid/factories directory; it should give you some ideas of what's possible.
|
74
|
+
|
75
|
+
|
76
|
+
h1. Resources
|
77
|
+
|
78
|
+
The project page on GitHub lets you browse the latest code, or clone or fork the source repo for yourself.
|
79
|
+
|
80
|
+
"GitHub project":http://www.github.com/jaymcgavren/rubyonacid
|
12
81
|
|
13
|
-
|
82
|
+
The discussion list is the place for questions, problems, bug reports, feature requests, etc. And since working with Ruby On Acid is usually a creative endeavor, be sure to share your ideas and learn from others, too!
|
14
83
|
|
15
|
-
|
16
|
-
* Skip Factory: Add probability matrix [0.5, 0.9, 0.1...] that causes get_unit() to return true every time rand() is > given value. Also add mask value (0.1, 0.9), etc, that is added to random value to increase likelihood of returning true.
|
84
|
+
"Discussion list":http://groups.google.com/group/rubyonacid
|
17
85
|
|
18
86
|
|
19
87
|
h1. Copyright
|
20
88
|
|
21
|
-
Copyright (c) 2009 Jay McGavren. See LICENSE for details.
|
89
|
+
Copyright (c) 2009 Jay McGavren. Released under the MIT license. See the LICENSE file for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/examples/ascii.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#This method takes any Factory and uses it to determine the length of lines to print.
|
2
|
+
def make_lines(factory)
|
3
|
+
#Show what factory we're working with.
|
4
|
+
puts factory.class.name
|
5
|
+
10.times do
|
6
|
+
#Get the length of the line.
|
7
|
+
#The :max option scales the returned length to be between 0 and 79.
|
8
|
+
line_length = factory.get(:length, :max => 79)
|
9
|
+
puts "|" * line_length
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
#Random factories generate a random number between 0 and 1.
|
14
|
+
require 'rubyonacid/factories/random'
|
15
|
+
make_lines RubyOnAcid::RandomFactory.new
|
16
|
+
|
17
|
+
#Loop factories loop from 0 to 1 (or 1 to 0 if the increment value is negative).
|
18
|
+
require 'rubyonacid/factories/loop'
|
19
|
+
make_lines RubyOnAcid::LoopFactory.new(0.2)
|
20
|
+
make_lines RubyOnAcid::LoopFactory.new(-0.2)
|
21
|
+
|
22
|
+
#Constant factories always return the same value,
|
23
|
+
require 'rubyonacid/factories/constant'
|
24
|
+
make_lines RubyOnAcid::ConstantFactory.new(0.5)
|
25
|
+
|
26
|
+
#This flash factory returns 0 twice, then 1 twice, then 0 twice, etc.
|
27
|
+
require 'rubyonacid/factories/flash'
|
28
|
+
make_lines RubyOnAcid::FlashFactory.new(2)
|
29
|
+
|
30
|
+
#Sine factories produce a "wave" pattern.
|
31
|
+
require 'rubyonacid/factories/sine'
|
32
|
+
make_lines RubyOnAcid::SineFactory.new(0.3)
|
33
|
+
|
34
|
+
#A RepeatFactory wraps another factory, queries it, and repeats the same value a certain number of times.
|
35
|
+
require 'rubyonacid/factories/repeat'
|
36
|
+
factory_to_repeat = RubyOnAcid::LoopFactory.new(0.3)
|
37
|
+
make_lines RubyOnAcid::RepeatFactory.new(factory_to_repeat, 2)
|
38
|
+
|
39
|
+
#A CombinationFactory combines the values of two or more other factories.
|
40
|
+
require 'rubyonacid/factories/combination'
|
41
|
+
factories_to_combine = [
|
42
|
+
RubyOnAcid::SineFactory.new(0.1),
|
43
|
+
RubyOnAcid::SineFactory.new(-0.2)
|
44
|
+
]
|
45
|
+
make_lines RubyOnAcid::CombinationFactory.new(:source_factories => factories_to_combine)
|
data/examples/midi.rb
CHANGED
@@ -3,7 +3,6 @@ require 'rubyonacid/factories/meta'
|
|
3
3
|
require 'rubyonacid/factories/constant'
|
4
4
|
require 'rubyonacid/factories/flash'
|
5
5
|
require 'rubyonacid/factories/loop'
|
6
|
-
require 'rubyonacid/factories/modulo'
|
7
6
|
require 'rubyonacid/factories/random'
|
8
7
|
require 'rubyonacid/factories/repeat'
|
9
8
|
require 'rubyonacid/factories/sine'
|
@@ -35,7 +34,6 @@ factory.factory_pool << RubyOnAcid::RepeatFactory.new(
|
|
35
34
|
RubyOnAcid::SineFactory.new(random_factory.within(:increment, -0.1, 0.1)),
|
36
35
|
random_factory.within(:interval, 2, 100)
|
37
36
|
)
|
38
|
-
factory.factory_pool << RubyOnAcid::ModuloFactory.new(RubyOnAcid::LoopFactory.new(0.00001))
|
39
37
|
|
40
38
|
#A skip factory, in charge of randomly resetting the meta factory.
|
41
39
|
@resetter = RubyOnAcid::SkipFactory.new(0.999)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'wxruby.rb')
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
class MyApp
|
6
|
+
|
7
|
+
WIDTH = 1920
|
8
|
+
HEIGHT = 1080
|
9
|
+
|
10
|
+
def on_init
|
11
|
+
|
12
|
+
ARGV.each do |file_name|
|
13
|
+
|
14
|
+
puts "Processing #{file_name}"
|
15
|
+
|
16
|
+
@f = YAML.load_file(file_name)
|
17
|
+
|
18
|
+
frame = Wx::Frame.new(nil, :size => [WIDTH, HEIGHT])
|
19
|
+
|
20
|
+
|
21
|
+
#Displays drawing.
|
22
|
+
bitmap = Wx::Bitmap.new(WIDTH, HEIGHT)
|
23
|
+
bitmap.draw do |surface|
|
24
|
+
surface.brush = Wx::BLACK_BRUSH
|
25
|
+
surface.draw_rectangle(0, 0, WIDTH, HEIGHT)
|
26
|
+
end
|
27
|
+
10000.times do
|
28
|
+
bitmap.draw {|surface| render(surface)}
|
29
|
+
end
|
30
|
+
bitmap.draw do |surface|
|
31
|
+
surface.text_foreground = Wx::Colour.new(255, 255, 255, 255)
|
32
|
+
surface.draw_text("©2009 Jay McGavren. Licensed under a Creative Commons Attribution-Share Alike 3.0 United States License: http://creativecommons.org/licenses/by-sa/3.0/us/", 10, HEIGHT - 20)
|
33
|
+
end
|
34
|
+
|
35
|
+
bitmap.save_file(file_name + ".png", Wx::BITMAP_TYPE_PNG)
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
exit
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
app = MyApp.new
|
46
|
+
app.main_loop
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'wxruby.rb')
|
2
|
+
|
3
|
+
|
4
|
+
class MyApp
|
5
|
+
|
6
|
+
WIDTH = 320
|
7
|
+
HEIGHT = 320
|
8
|
+
|
9
|
+
def on_init
|
10
|
+
|
11
|
+
(1..1000).each do |file_number|
|
12
|
+
|
13
|
+
file_name = sprintf("%05d_random.jpg", file_number)
|
14
|
+
|
15
|
+
@f = create_factory
|
16
|
+
|
17
|
+
frame = Wx::Frame.new(nil, :size => [WIDTH, HEIGHT])
|
18
|
+
|
19
|
+
bitmap = Wx::Bitmap.new(WIDTH, HEIGHT)
|
20
|
+
bitmap.draw do |surface|
|
21
|
+
surface.brush = Wx::BLACK_BRUSH
|
22
|
+
surface.draw_rectangle(0, 0, WIDTH, HEIGHT)
|
23
|
+
end
|
24
|
+
10000.times do
|
25
|
+
bitmap.draw {|surface| render(surface)}
|
26
|
+
end
|
27
|
+
bitmap.draw do |surface|
|
28
|
+
surface.text_foreground = Wx::Colour.new(255, 255, 255, 255)
|
29
|
+
y = 0
|
30
|
+
@f.to_yaml.split("\n").each do |line|
|
31
|
+
surface.draw_text(line, 0, y)
|
32
|
+
y += 10
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
File.open(file_name + ".yml", "w") do |file|
|
37
|
+
YAML.dump(@f, file)
|
38
|
+
end
|
39
|
+
|
40
|
+
bitmap.save_file(file_name, Wx::BITMAP_TYPE_JPEG)
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
exit
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
app = MyApp.new
|
51
|
+
app.main_loop
|
data/examples/raw_audio.rb
CHANGED
@@ -3,7 +3,6 @@ require 'rubyonacid/factories/meta'
|
|
3
3
|
require 'rubyonacid/factories/constant'
|
4
4
|
require 'rubyonacid/factories/flash'
|
5
5
|
require 'rubyonacid/factories/loop'
|
6
|
-
require 'rubyonacid/factories/modulo'
|
7
6
|
require 'rubyonacid/factories/random'
|
8
7
|
require 'rubyonacid/factories/repeat'
|
9
8
|
require 'rubyonacid/factories/sine'
|
@@ -31,7 +30,6 @@ def generate_factories
|
|
31
30
|
RubyOnAcid::SineFactory.new(random_factory.within(:increment, -0.1, 0.1)),
|
32
31
|
random_factory.within(:interval, 2, 100)
|
33
32
|
)
|
34
|
-
factory_pool << RubyOnAcid::ModuloFactory.new(RubyOnAcid::LoopFactory.new(0.00001))
|
35
33
|
factory_pool
|
36
34
|
end
|
37
35
|
|
data/examples/rinda_agent.rb
CHANGED
@@ -3,9 +3,9 @@ require 'wx'
|
|
3
3
|
require 'rubyonacid/factories/meta'
|
4
4
|
require 'rubyonacid/factories/constant'
|
5
5
|
require 'rubyonacid/factories/flash'
|
6
|
-
require 'rubyonacid/factories/increment'
|
7
6
|
require 'rubyonacid/factories/loop'
|
8
7
|
require 'rubyonacid/factories/random'
|
8
|
+
require 'rubyonacid/factories/repeat'
|
9
9
|
require 'rubyonacid/factories/rinda'
|
10
10
|
require 'rubyonacid/factories/sine'
|
11
11
|
require 'rubyonacid/factories/skip'
|
@@ -19,23 +19,9 @@ class MyApp < Wx::App
|
|
19
19
|
|
20
20
|
def on_init
|
21
21
|
|
22
|
-
|
23
|
-
@f =
|
24
|
-
|
25
|
-
@f.factory_pool << RubyOnAcid::LoopFactory.new(0.01)
|
26
|
-
@f.factory_pool << RubyOnAcid::LoopFactory.new(-0.01)
|
27
|
-
#Random factories generate random values.
|
28
|
-
# @f.factory_pool << RubyOnAcid::RandomFactory.new
|
29
|
-
#Constant factories always return the same value,
|
30
|
-
@f.factory_pool << RubyOnAcid::ConstantFactory.new(rand)
|
31
|
-
#Sine factories produce a "wave" pattern.
|
32
|
-
@f.factory_pool << RubyOnAcid::SineFactory.new(0.1)
|
33
|
-
@f.factory_pool << RubyOnAcid::SineFactory.new(-0.1)
|
34
|
-
|
35
|
-
rinda_factory = RubyOnAcid::RindaFactory.new(ARGV[0])
|
36
|
-
rinda_factory.start_service
|
37
|
-
@f.assign_factory(:x, rinda_factory)
|
38
|
-
@f.assign_factory(:y, rinda_factory)
|
22
|
+
@f = RubyOnAcid::RindaFactory.new(ARGV[0])
|
23
|
+
@f.default_factory = create_factory
|
24
|
+
@f.start_service
|
39
25
|
|
40
26
|
#A skip factory, in charge of randomly resetting the meta factory.
|
41
27
|
@resetter = RubyOnAcid::SkipFactory.new(0.999)
|
@@ -49,32 +35,109 @@ class MyApp < Wx::App
|
|
49
35
|
|
50
36
|
#Animate periodically.
|
51
37
|
t = Wx::Timer.new(self, 55)
|
52
|
-
evt_timer(55)
|
38
|
+
evt_timer(55) do
|
39
|
+
window.paint{|surface| render(surface)}
|
40
|
+
@f.default_factory.reset_assignments if @resetter.boolean(:reset)
|
41
|
+
end
|
53
42
|
t.start(33)
|
54
43
|
|
55
44
|
end
|
56
45
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
46
|
+
def create_factory
|
47
|
+
random_factory = RubyOnAcid::RandomFactory.new
|
48
|
+
|
49
|
+
#The MetaFactory assigns factories to requested value types.
|
50
|
+
meta_factory = RubyOnAcid::MetaFactory.new
|
51
|
+
#Loop factories loop from 0.0 to 1.0 (or 1.0 to 0.0 if the increment value is negative).
|
52
|
+
meta_factory.factory_pool << RubyOnAcid::LoopFactory.new(0.01)
|
53
|
+
meta_factory.factory_pool << RubyOnAcid::LoopFactory.new(-0.01)
|
54
|
+
meta_factory.factory_pool << RubyOnAcid::LoopFactory.new(0.001)
|
55
|
+
meta_factory.factory_pool << RubyOnAcid::LoopFactory.new(-0.001)
|
56
|
+
#Constant factories always return the same value,
|
57
|
+
meta_factory.factory_pool << RubyOnAcid::ConstantFactory.new(rand)
|
58
|
+
meta_factory.factory_pool << RubyOnAcid::ConstantFactory.new(rand)
|
59
|
+
meta_factory.factory_pool << RubyOnAcid::FlashFactory.new(rand(100))
|
60
|
+
#Sine factories produce a "wave" pattern.
|
61
|
+
meta_factory.factory_pool << RubyOnAcid::SineFactory.new(0.1)
|
62
|
+
meta_factory.factory_pool << RubyOnAcid::SineFactory.new(-0.1)
|
63
|
+
meta_factory.factory_pool << RubyOnAcid::SineFactory.new(0.01)
|
64
|
+
meta_factory.factory_pool << RubyOnAcid::SineFactory.new(-0.01)
|
65
|
+
meta_factory.factory_pool << RubyOnAcid::RepeatFactory.new(
|
66
|
+
RubyOnAcid::LoopFactory.new(random_factory.within(:increment, -0.1, 0.1)),
|
67
|
+
random_factory.within(:interval, 2, 100)
|
68
|
+
)
|
69
|
+
meta_factory.factory_pool << RubyOnAcid::RepeatFactory.new(
|
70
|
+
RubyOnAcid::SineFactory.new(random_factory.within(:increment, -0.1, 0.1)),
|
71
|
+
random_factory.within(:interval, 2, 100)
|
72
|
+
)
|
73
|
+
|
74
|
+
meta_factory
|
76
75
|
end
|
77
76
|
|
77
|
+
def render(surface)
|
78
|
+
color = Wx::Colour.new(
|
79
|
+
@f.get(:red, :max => 255).to_i,
|
80
|
+
@f.get(:green, :max => 255).to_i,
|
81
|
+
@f.get(:blue, :max => 255).to_i,
|
82
|
+
@f.get(:alpha, :min => 50, :max => 200).to_i
|
83
|
+
)
|
84
|
+
surface.pen = Wx::Pen.new(color, @f.within(:width, 1, 5).to_i)
|
85
|
+
surface.brush = Wx::Brush.new(color, Wx::SOLID)
|
86
|
+
case @f.choose(:shape,
|
87
|
+
:arc,
|
88
|
+
:polygon,
|
89
|
+
:line,
|
90
|
+
# :rectangle,
|
91
|
+
:circle,
|
92
|
+
:spline
|
93
|
+
)
|
94
|
+
when :line
|
95
|
+
surface.draw_line(
|
96
|
+
@f.get(:x0, :max => WIDTH).to_i,
|
97
|
+
@f.get(:y0, :max => HEIGHT).to_i,
|
98
|
+
@f.get(:x1, :max => WIDTH).to_i,
|
99
|
+
@f.get(:y1, :max => HEIGHT).to_i
|
100
|
+
)
|
101
|
+
when :rectangle
|
102
|
+
surface.draw_rectangle(
|
103
|
+
@f.get(:x0, :max => WIDTH).to_i,
|
104
|
+
@f.get(:y0, :max => HEIGHT).to_i,
|
105
|
+
@f.get(:x1, :max => WIDTH).to_i,
|
106
|
+
@f.get(:y1, :max => HEIGHT).to_i
|
107
|
+
)
|
108
|
+
when :circle
|
109
|
+
surface.draw_circle(
|
110
|
+
@f.get(:x0, :max => WIDTH).to_i,
|
111
|
+
@f.get(:y0, :max => HEIGHT).to_i,
|
112
|
+
@f.get(:width, :max => WIDTH).to_i
|
113
|
+
)
|
114
|
+
when :arc
|
115
|
+
surface.draw_elliptic_arc(
|
116
|
+
@f.get(:x0, :max => WIDTH).to_i,
|
117
|
+
@f.get(:y0, :max => HEIGHT).to_i,
|
118
|
+
@f.get(:width, :max => WIDTH).to_i,
|
119
|
+
@f.get(:height, :max => HEIGHT).to_i,
|
120
|
+
@f.get(:arc_start, :max => 360).to_i,
|
121
|
+
@f.get(:arc_end, :max => 360).to_i
|
122
|
+
)
|
123
|
+
when :polygon
|
124
|
+
surface.draw_polygon(make_point_array)
|
125
|
+
when :spline
|
126
|
+
surface.draw_spline(make_point_array)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def make_point_array
|
131
|
+
points = []
|
132
|
+
@f.get(:points, :min => 3, :max => 6).to_i.times do |i|
|
133
|
+
points << Wx::Point.new(
|
134
|
+
@f.get("x#{i}".to_sym, :max => WIDTH).to_i,
|
135
|
+
@f.get("y#{i}".to_sym, :max => HEIGHT).to_i
|
136
|
+
)
|
137
|
+
end
|
138
|
+
points
|
139
|
+
end
|
140
|
+
|
78
141
|
end
|
79
142
|
|
80
143
|
app = MyApp.new
|
data/examples/wxruby.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'wx'
|
3
|
+
require 'rubyonacid/factories/meta'
|
4
|
+
require 'rubyonacid/factories/combination'
|
5
|
+
require 'rubyonacid/factories/constant'
|
6
|
+
require 'rubyonacid/factories/flash'
|
7
|
+
require 'rubyonacid/factories/loop'
|
8
|
+
require 'rubyonacid/factories/random'
|
9
|
+
require 'rubyonacid/factories/repeat'
|
10
|
+
require 'rubyonacid/factories/sine'
|
11
|
+
require 'rubyonacid/factories/skip'
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
class MyApp < Wx::App
|
16
|
+
|
17
|
+
WIDTH = 480
|
18
|
+
HEIGHT = 480
|
19
|
+
|
20
|
+
def on_init
|
21
|
+
|
22
|
+
@f = create_factory
|
23
|
+
|
24
|
+
#A skip factory, in charge of randomly resetting the meta factory.
|
25
|
+
@resetter = RubyOnAcid::SkipFactory.new(0.999)
|
26
|
+
|
27
|
+
#Containing frame.
|
28
|
+
frame = Wx::Frame.new(nil, :size => [WIDTH, HEIGHT])
|
29
|
+
frame.show
|
30
|
+
|
31
|
+
#Displays drawing.
|
32
|
+
window = Wx::Window.new(frame, :size => [WIDTH, HEIGHT])
|
33
|
+
|
34
|
+
#Animate periodically.
|
35
|
+
t = Wx::Timer.new(self, 55)
|
36
|
+
evt_timer(55) do
|
37
|
+
window.paint{|surface| render(surface)}
|
38
|
+
@f.reset_assignments if @resetter.boolean(:reset)
|
39
|
+
end
|
40
|
+
t.start(33)
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def create_factory
|
46
|
+
|
47
|
+
random_factory = RubyOnAcid::RandomFactory.new
|
48
|
+
|
49
|
+
source_factories = []
|
50
|
+
#Loop factories loop from 0.0 to 1.0 (or 1.0 to 0.0 if the increment value is negative).
|
51
|
+
source_factories << RubyOnAcid::LoopFactory.new(0.01)
|
52
|
+
source_factories << RubyOnAcid::LoopFactory.new(-0.01)
|
53
|
+
source_factories << RubyOnAcid::LoopFactory.new(0.001)
|
54
|
+
source_factories << RubyOnAcid::LoopFactory.new(-0.001)
|
55
|
+
#Constant factories always return the same value,
|
56
|
+
source_factories << RubyOnAcid::ConstantFactory.new(rand)
|
57
|
+
source_factories << RubyOnAcid::ConstantFactory.new(rand)
|
58
|
+
source_factories << RubyOnAcid::FlashFactory.new(rand(100))
|
59
|
+
#Sine factories produce a "wave" pattern.
|
60
|
+
source_factories << RubyOnAcid::SineFactory.new(0.1)
|
61
|
+
source_factories << RubyOnAcid::SineFactory.new(-0.1)
|
62
|
+
source_factories << RubyOnAcid::SineFactory.new(0.01)
|
63
|
+
source_factories << RubyOnAcid::SineFactory.new(-0.01)
|
64
|
+
#A RepeatFactory wraps another factory, queries it, and repeats the same value a certain number of times.
|
65
|
+
source_factories << RubyOnAcid::RepeatFactory.new(
|
66
|
+
RubyOnAcid::LoopFactory.new(random_factory.within(:increment, -0.1, 0.1)),
|
67
|
+
random_factory.get(:interval, :min => 2, :max => 100)
|
68
|
+
)
|
69
|
+
source_factories << RubyOnAcid::RepeatFactory.new(
|
70
|
+
RubyOnAcid::SineFactory.new(random_factory.within(:increment, -0.1, 0.1)),
|
71
|
+
random_factory.get(:interval, :min => 2, :max => 100)
|
72
|
+
)
|
73
|
+
#A CombinationFactory combines the values of two or more other factories.
|
74
|
+
combination_factory = RubyOnAcid::CombinationFactory.new
|
75
|
+
2.times do
|
76
|
+
combination_factory.source_factories << source_factories[rand(source_factories.length)]
|
77
|
+
end
|
78
|
+
source_factories << combination_factory
|
79
|
+
|
80
|
+
#The MetaFactory pulls requested value types from the other factories.
|
81
|
+
meta_factory = RubyOnAcid::MetaFactory.new
|
82
|
+
meta_factory.factory_pool = source_factories
|
83
|
+
|
84
|
+
meta_factory
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
def render(surface)
|
90
|
+
color = Wx::Colour.new(
|
91
|
+
@f.get(:red, :max => 255).to_i,
|
92
|
+
@f.get(:green, :max => 255).to_i,
|
93
|
+
@f.get(:blue, :max => 255).to_i,
|
94
|
+
@f.get(:alpha, :min => 50, :max => 200).to_i
|
95
|
+
)
|
96
|
+
surface.pen = Wx::Pen.new(color, @f.within(:width, 1, 5).to_i)
|
97
|
+
surface.brush = Wx::Brush.new(color, Wx::SOLID)
|
98
|
+
case @f.choose(:shape,
|
99
|
+
:arc,
|
100
|
+
:polygon,
|
101
|
+
:line,
|
102
|
+
:rectangle,
|
103
|
+
:circle,
|
104
|
+
:spline
|
105
|
+
)
|
106
|
+
when :line
|
107
|
+
surface.draw_line(
|
108
|
+
@f.get(:x0, :max => WIDTH).to_i,
|
109
|
+
@f.get(:y0, :max => HEIGHT).to_i,
|
110
|
+
@f.get(:x1, :max => WIDTH).to_i,
|
111
|
+
@f.get(:y1, :max => HEIGHT).to_i
|
112
|
+
)
|
113
|
+
when :rectangle
|
114
|
+
surface.draw_rectangle(
|
115
|
+
@f.get(:x0, :max => WIDTH).to_i,
|
116
|
+
@f.get(:y0, :max => HEIGHT).to_i,
|
117
|
+
@f.get(:x1, :max => WIDTH).to_i,
|
118
|
+
@f.get(:y1, :max => HEIGHT).to_i
|
119
|
+
)
|
120
|
+
when :circle
|
121
|
+
surface.draw_circle(
|
122
|
+
@f.get(:x0, :max => WIDTH).to_i,
|
123
|
+
@f.get(:y0, :max => HEIGHT).to_i,
|
124
|
+
@f.get(:width, :max => 100).to_i
|
125
|
+
)
|
126
|
+
when :arc
|
127
|
+
surface.draw_elliptic_arc(
|
128
|
+
@f.get(:x0, :max => WIDTH).to_i,
|
129
|
+
@f.get(:y0, :max => HEIGHT).to_i,
|
130
|
+
@f.get(:width, :max => 100).to_i,
|
131
|
+
@f.get(:height, :max => 100).to_i,
|
132
|
+
@f.get(:arc_start, :max => 360).to_i,
|
133
|
+
@f.get(:arc_end, :max => 360).to_i
|
134
|
+
)
|
135
|
+
when :polygon
|
136
|
+
surface.draw_polygon(make_point_array)
|
137
|
+
when :spline
|
138
|
+
surface.draw_spline(make_point_array)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def make_point_array
|
144
|
+
points = []
|
145
|
+
3.times do |i|
|
146
|
+
points << Wx::Point.new(
|
147
|
+
@f.get("x#{i}".to_sym, :max => WIDTH).to_i,
|
148
|
+
@f.get("y#{i}".to_sym, :max => HEIGHT).to_i
|
149
|
+
)
|
150
|
+
end
|
151
|
+
points
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
app = MyApp.new
|
158
|
+
app.main_loop
|
data/generators.png
ADDED
Binary file
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'rubyonacid/factory'
|
2
|
+
|
3
|
+
module RubyOnAcid
|
4
|
+
|
5
|
+
class CombinationFactory < Factory
|
6
|
+
|
7
|
+
ADD = :add
|
8
|
+
SUBTRACT = :subtract
|
9
|
+
MULTIPLY = :multiply
|
10
|
+
DIVIDE = :divide
|
11
|
+
CONSTRAIN = :constrain
|
12
|
+
WRAP = :wrap
|
13
|
+
|
14
|
+
attr_accessor :source_factories
|
15
|
+
attr_accessor :operation
|
16
|
+
attr_accessor :constrain_mode
|
17
|
+
|
18
|
+
def initialize(options = {})
|
19
|
+
super
|
20
|
+
@source_factories = options[:source_factories] || []
|
21
|
+
@operation = options[:operation] || ADD
|
22
|
+
@constrain_mode = options[:constrain_mode] || WRAP
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_unit(key)
|
26
|
+
combined_value = combine(key)
|
27
|
+
constrain(combined_value)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def combine(key)
|
33
|
+
initial_value = @source_factories.first.get_unit(key)
|
34
|
+
additional_values = @source_factories.slice(1, @source_factories.length - 1).map {|f| f.get_unit(key)}
|
35
|
+
case @operation
|
36
|
+
when ADD
|
37
|
+
return additional_values.inject(initial_value) {|sum, value| sum + value}
|
38
|
+
when SUBTRACT
|
39
|
+
return additional_values.inject(initial_value) {|sum, value| sum - value}
|
40
|
+
when MULTIPLY
|
41
|
+
return additional_values.inject(initial_value) {|product, value| product * value}
|
42
|
+
when DIVIDE
|
43
|
+
return additional_values.inject(initial_value) {|product, value| product / value}
|
44
|
+
else
|
45
|
+
raise "invalid operation - must be ADD, MULTIPLY, SUBTRACT, or DIVIDE"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def constrain(value)
|
50
|
+
case @constrain_mode
|
51
|
+
when CONSTRAIN
|
52
|
+
if value > 1.0
|
53
|
+
return 1.0
|
54
|
+
elsif value < 0.0
|
55
|
+
return 0.0
|
56
|
+
else
|
57
|
+
return value
|
58
|
+
end
|
59
|
+
when WRAP
|
60
|
+
return value % 1.0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -3,7 +3,8 @@ require 'rubyonacid/factory'
|
|
3
3
|
module RubyOnAcid
|
4
4
|
|
5
5
|
class IncrementFactory < Factory
|
6
|
-
|
6
|
+
|
7
|
+
#The amount to increment counters by.
|
7
8
|
attr_accessor :interval
|
8
9
|
def interval=(value)
|
9
10
|
@interval = value
|
@@ -18,7 +19,7 @@ class IncrementFactory < Factory
|
|
18
19
|
@interval = interval
|
19
20
|
end
|
20
21
|
|
21
|
-
#Increment counter for key and
|
22
|
+
#Increment counter for given key and return it. Constrain between 0 and 1.
|
22
23
|
def get_unit(key)
|
23
24
|
@counters[key] ||= @start_value
|
24
25
|
@counters[key] += @interval
|