picrate 0.0.2-java → 0.0.3-java
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/README.md +5 -4
- data/Rakefile +1 -1
- data/docs/_classes/aabb/aabb.md +28 -0
- data/docs/_classes/app/app.md +38 -0
- data/docs/_classes/app_render/app_render.md +93 -0
- data/docs/_classes/arc_ball/arc_ball.md +33 -0
- data/docs/_classes/chooser/chooser.md +56 -0
- data/docs/_classes/deglut/deglut.md +20 -0
- data/docs/_classes/library_proxy/library_proxy.md +76 -0
- data/docs/_classes/vec2d/vec2d.md +53 -0
- data/docs/_classes/vec3d/vec3d.md +53 -0
- data/docs/_config.yml +36 -7
- data/docs/_editors/vim.md +63 -0
- data/docs/_gems/gems/gems.md +29 -0
- data/docs/_gems/other_gems/other_gems.md +198 -0
- data/docs/_layouts/post.html +6 -6
- data/docs/_libraries/control_panel.md +137 -0
- data/docs/_libraries/custom.md +126 -0
- data/docs/_libraries/custom_java.md +162 -0
- data/docs/_libraries/gems.md +57 -0
- data/docs/_libraries/library_proxy.md +9 -0
- data/docs/_libraries/picrate.md +511 -0
- data/docs/_libraries/processing.md +126 -0
- data/docs/_libraries/vector_utils.md +126 -0
- data/docs/_magic/java.md +30 -0
- data/docs/_magic/jruby.md +105 -0
- data/docs/_magic/processing.md +297 -0
- data/docs/_magic/ruby.md +31 -0
- data/docs/_methods/alternative_methods.md +66 -0
- data/docs/_methods/color.md +109 -0
- data/docs/_methods/data_path.md +109 -0
- data/docs/_methods/draw.md +20 -0
- data/docs/_methods/key_pressed.md +27 -0
- data/docs/_methods/library_loader.md +49 -0
- data/docs/_methods/map1d.md +77 -0
- data/docs/_methods/methods_summary.md +103 -0
- data/docs/_methods/mouse_pressed.md +25 -0
- data/docs/_methods/post_initialize.md +9 -0
- data/docs/_methods/processing_api.md +46 -0
- data/docs/_methods/settings.md +48 -0
- data/docs/_methods/setup.md +36 -0
- data/docs/_methods/sketch_title.md +24 -0
- data/docs/_modules/custom.md +61 -0
- data/docs/_modules/helper_methods.md +10 -0
- data/docs/_modules/interface.md +66 -0
- data/docs/_modules/processing.md +7 -0
- data/docs/_modules/processing_proxy.md +28 -0
- data/docs/_objects/class/class.md +7 -0
- data/docs/_objects/global/global.md +7 -0
- data/docs/_objects/instance/instance.md +74 -0
- data/docs/_objects/numeric/numeric.md +37 -0
- data/docs/_posts/2018-05-06-getting_started.md +60 -0
- data/docs/_posts/2018-05-06-processing-api.md +68 -0
- data/docs/_posts/2018-05-11-arch-linux-arm.md +17 -0
- data/docs/about.md +7 -1
- data/docs/classes.md +10 -0
- data/docs/editors.md +10 -0
- data/docs/gems.md +11 -0
- data/docs/libraries.md +20 -0
- data/docs/magic.md +11 -0
- data/docs/methods.md +10 -0
- data/docs/modules.md +12 -0
- data/docs/objects.md +9 -0
- data/lib/picrate/version.rb +1 -1
- data/lib/picrate-0.0.3.jar +0 -0
- data/picrate.gemspec +2 -2
- data/pom.rb +1 -1
- data/pom.xml +7 -7
- data/src/main/java/monkstone/MathToolModule.java +2 -2
- data/src/main/java/monkstone/videoevent/VideoInterface.java +1 -1
- data/src/main/java/processing/core/PApplet.java +3 -3
- data/src/main/java/processing/javafx/PGraphicsFX2D.java +1 -1
- data/test/respond_to_test.rb +4 -4
- data/test/sketches/key_event.rb +3 -3
- data/vendors/Rakefile +1 -1
- metadata +61 -4
- data/lib/picrate-0.0.2.jar +0 -0
@@ -0,0 +1,126 @@
|
|
1
|
+
---
|
2
|
+
layout: post
|
3
|
+
title: "vector_utils<sup>2</sup>"
|
4
|
+
keywords: processing, vector, library
|
5
|
+
permalink: libraries/vector_utils.html
|
6
|
+
---
|
7
|
+
We have created a `vector_utils` library that implements a number of vector methods see sample usage:-
|
8
|
+
|
9
|
+
### Vec2D examples
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
#!/usr/bin/env jruby -v -W2
|
13
|
+
# frozen_string_literal: true
|
14
|
+
require 'picrate'
|
15
|
+
class VogelLayout < Processing::App
|
16
|
+
|
17
|
+
load_library :vector_utils
|
18
|
+
|
19
|
+
attr_reader :points
|
20
|
+
|
21
|
+
def settings
|
22
|
+
size 600, 600
|
23
|
+
smooth 4
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup
|
27
|
+
sketch_title 'Vogel Layout'
|
28
|
+
@points = VectorUtil.vogel_layout(number: 200, node_size: 10.0)
|
29
|
+
end
|
30
|
+
|
31
|
+
def draw
|
32
|
+
background 0
|
33
|
+
fill 200, 130, 100
|
34
|
+
translate width / 2, height / 2
|
35
|
+
points.each do |vec|
|
36
|
+
ellipse vec.x, vec.y, 10, 10
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
VogelLayout.new
|
42
|
+
```
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
#!/usr/bin/env jruby -v -W2
|
46
|
+
# frozen_string_literal: true
|
47
|
+
require 'picrate'
|
48
|
+
|
49
|
+
class SpiralLayout < Processing::App
|
50
|
+
load_library :vector_utils
|
51
|
+
|
52
|
+
attr_reader :points
|
53
|
+
|
54
|
+
def settings
|
55
|
+
size 600, 600
|
56
|
+
smooth 4
|
57
|
+
end
|
58
|
+
|
59
|
+
def setup
|
60
|
+
sketch_title 'Spiral Layout'
|
61
|
+
@points = VectorUtil.spiral_layout(
|
62
|
+
number: 300,
|
63
|
+
radius: 200,
|
64
|
+
resolution: 0.3,
|
65
|
+
spacing: 0.01,
|
66
|
+
inc: 1.15
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def draw
|
71
|
+
background 0
|
72
|
+
fill 200, 130, 100
|
73
|
+
translate width / 2, height / 2
|
74
|
+
points.each do |vec|
|
75
|
+
ellipse vec.x, vec.y, 10, 10
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
SpiralLayout.new
|
81
|
+
```
|
82
|
+
|
83
|
+
### Vec3D example
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
#!/usr/bin/env jruby -v -W2
|
87
|
+
# frozen_string_literal: true
|
88
|
+
require 'picrate'
|
89
|
+
require 'arcball'
|
90
|
+
|
91
|
+
class FibonacciLayout < Processing::App
|
92
|
+
|
93
|
+
load_library :vector_utils
|
94
|
+
|
95
|
+
attr_reader :points
|
96
|
+
|
97
|
+
def settings
|
98
|
+
size 600, 600, P3D
|
99
|
+
smooth 4
|
100
|
+
end
|
101
|
+
|
102
|
+
def setup
|
103
|
+
sketch_title 'Fibonacci Layout'
|
104
|
+
Processing::ArcBall.init self
|
105
|
+
@points = VectorUtil.fibonacci_sphere(number: 500, radius: 300.0)
|
106
|
+
end
|
107
|
+
|
108
|
+
def draw
|
109
|
+
background 0
|
110
|
+
fill 200, 130, 100
|
111
|
+
lights
|
112
|
+
directional_light 200, 200, 200, -1, 1, 0
|
113
|
+
points.each do |vec|
|
114
|
+
push_matrix
|
115
|
+
translate vec.x, vec.y, vec.z
|
116
|
+
polar = VectorUtil.cartesian_to_polar(vec: vec)
|
117
|
+
box 10
|
118
|
+
rotate_y vec.y
|
119
|
+
rotate_z vec.z
|
120
|
+
pop_matrix
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
FibonacciLayout.new
|
126
|
+
```
|
data/docs/_magic/java.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
---
|
2
|
+
layout: post
|
3
|
+
title: "Java"
|
4
|
+
keywords: ruby, java, jruby
|
5
|
+
permalink: magic/java.html
|
6
|
+
---
|
7
|
+
Here is some information about java [inner][inner] classes and [reflection][reflection]. Also see how the pre-processing of the [pde][pde] sketches to valid java creates [java inner classes][pde]. This is all magic stuff that gets hidden from the average user.
|
8
|
+
|
9
|
+
### Inner Classes ###
|
10
|
+
|
11
|
+
_Stolen from http://www.programmerinterview.com/_
|
12
|
+
|
13
|
+
What’s so special about inner classes?
|
14
|
+
|
15
|
+
So, what exactly is special about inner classes? Well, the main thing that you must remember about inner classes is that an instance of an inner class has access to all of the members of the outer class, even those that are marked “private”. So, when an instance of the inner class is created, there are no issues with having the inner class access the instance variables of the outer class.
|
16
|
+
|
17
|
+
### Reflection ###
|
18
|
+
|
19
|
+
_Stolen from stack exchange_
|
20
|
+
|
21
|
+
* Reflection is much slower than just calling methods by their name, because it has to inspect the metadata in the bytecode instead of just using precompiled addresses and constants.
|
22
|
+
* Reflection is also more powerful: you can retrieve the definition of a protected or final member, remove the protection and manipulate it as if it had been declared mutable!
|
23
|
+
* Obviously this subverts many of the guarantees the language normally makes for your programs and that can be extremely dangerous.
|
24
|
+
And this pretty much explains when you would use it. Ordinarily, don't. If you want to call a method, just call it. If you want to mutate a member, just declare it mutable instead of going behind the compiler's back.
|
25
|
+
|
26
|
+
One useful real-world use of reflection is when writing a framework that has to interoperate with user-defined classes, where the framework author doesn't know what the members (or even the classes) will be. Reflection allows them to deal with any class without knowing it in advance. For instance, I don't think it would be possible to write a complex aspect-oriented library without reflection.
|
27
|
+
|
28
|
+
[reflection]:https://docs.oracle.com/javase/tutorial/reflect/
|
29
|
+
[inner]:https://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html
|
30
|
+
[pde]:{{site.github.url}}/magic/processing.html
|
@@ -0,0 +1,105 @@
|
|
1
|
+
---
|
2
|
+
layout: post
|
3
|
+
title: "JRuby"
|
4
|
+
keywords: ruby, java, jruby
|
5
|
+
permalink: magic/jruby.html
|
6
|
+
---
|
7
|
+
### java interfaces ###
|
8
|
+
JRuby classes can mixin Java interfaces as modules in order to implement them.
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
class SomeFlexibleClass
|
12
|
+
include java.lang.Runnable
|
13
|
+
include java.lang.Comparable
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
JRuby does a wonderful thing with Ruby’s blocks, where a block can be converted to the appropriate Java interface. It works by converting the block to a Proc, and then decorating it with a proxy object that runs the block for any method called on the interface. Runnable is the prime example here. You should try this yourself, also see using callbacks [hype][hype] library examples for more sophisticated stuff.
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
button = javax.swing.JButton.new "Press me!"
|
21
|
+
button.add_action_listener { |event| event.source.text = "I done been pressed." }
|
22
|
+
```
|
23
|
+
Read more about [java interface][wip] etc. Otherwise see [wiki][wiki]
|
24
|
+
|
25
|
+
### java reflection ###
|
26
|
+
|
27
|
+
In vanilla processing, you can [create libraries][library] in java that can access the sketch `pre`, `draw`, `post`, `mouseEvent` and `keyEvent` methods by java reflection, but you must `register` these methods with the `PApplet`. We can also register custom methods (but sadly only those without parameters, which is why we found another way of dealing with `selectInput` see [chooser][chooser], `movieEvent` see [video_event][video_event]).
|
28
|
+
|
29
|
+
Here we show you how to `registerMethods` in a ruby class by java reflection in JRuby (requires the `!become_java` method).
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
#!/usr/bin/env jruby
|
33
|
+
require 'picrate'
|
34
|
+
require_relative 'register_send'
|
35
|
+
|
36
|
+
class ReflectionVoodoo < Processing::App
|
37
|
+
def settings
|
38
|
+
size 300, 200
|
39
|
+
# pixel_density(2) # for HiDpi screens
|
40
|
+
# smooth # see https://processing.org/reference/smooth_.html
|
41
|
+
end
|
42
|
+
|
43
|
+
def setup
|
44
|
+
sketch_title 'Reflection Voodoo'
|
45
|
+
RegisterSend.new self
|
46
|
+
no_loop
|
47
|
+
end
|
48
|
+
|
49
|
+
def draw
|
50
|
+
fill 0, 0, 200
|
51
|
+
ellipse(170, 115, 70, 100)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
ReflectionVoodoo.new
|
56
|
+
```
|
57
|
+
|
58
|
+
Here is the class that does the reflection (it needs to become java so that self gets recognized as a java object)
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
require 'jruby/core_ext' # required to add become_java! method
|
62
|
+
|
63
|
+
# This class demonstrates how to use 'reflection' methods in ruby-processing
|
64
|
+
# NB: the class must become a java object to get registered. This is an
|
65
|
+
# advanced feature in vanilla processing, mainly used by libraries.
|
66
|
+
class RegisterSend
|
67
|
+
attr_reader :parent
|
68
|
+
|
69
|
+
def initialize(parent)
|
70
|
+
@parent = parent
|
71
|
+
parent.java_send :registerMethod, [java.lang.String, java.lang.Object], :draw, self
|
72
|
+
parent.java_send :registerMethod, [java.lang.String, java.lang.Object], :pre, self
|
73
|
+
end
|
74
|
+
|
75
|
+
def pre
|
76
|
+
puts 'before draw'
|
77
|
+
parent.background(100)
|
78
|
+
end
|
79
|
+
|
80
|
+
def draw
|
81
|
+
puts 'at begin draw...'
|
82
|
+
parent.fill(200, 100)
|
83
|
+
parent.ellipse(150, 100, 200, 60)
|
84
|
+
end
|
85
|
+
# putting become_java! here works OK
|
86
|
+
become_java!
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+

|
91
|
+
|
92
|
+
__Note__ how the transparent ellipse is placed on top of the solid ellipse, so the reflection element must get drawn after the original sketch element.
|
93
|
+
|
94
|
+
## Java Extensions for JRuby ###
|
95
|
+
|
96
|
+
JRuby is a 100% Java implementation of the Ruby programming language. It is Ruby for the JVM. So it is quite possible to write your own ruby code in java, you might do this to better integrate jruby with java or to write your own ruby classes (modules etc) in java see [Method Signatures and Annotations in JRuby extensions][signatures] and [jruby-examples][jruby-examples].
|
97
|
+
|
98
|
+
[library]:https://github.com/processing/processing/wiki/Library-Basics
|
99
|
+
[wip]:http://kares.org/jruby-ji-doc/
|
100
|
+
[wiki]:https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
|
101
|
+
[hype]:{{ site.github.url }}/libraries/hype
|
102
|
+
[signatures]:https://github.com/jruby/jruby/wiki/Method-Signatures-and-Annotations-in-JRuby-extensions
|
103
|
+
[jruby-examples]:https://github.com/jruby/jruby-examples/tree/master/extensions/basic
|
104
|
+
[chooser]:{{ site.github.url }}/libraries/chooser
|
105
|
+
[video_event]:{{ site.github.url }}/libraries/video_event
|
@@ -0,0 +1,297 @@
|
|
1
|
+
---
|
2
|
+
layout: post
|
3
|
+
title: "Processing"
|
4
|
+
keywords: pde, java, processing
|
5
|
+
permalink: magic/processing.html
|
6
|
+
---
|
7
|
+
## __pde__ sketches get pre-processed to __java__ ##
|
8
|
+
------
|
9
|
+
Part of the attraction of processing is that it hides a lot of java boilerplate stuff from the user. In vanilla processing all sketches get pre-processed to java prior to compilation:-
|
10
|
+
|
11
|
+
So sketch_161005a.pde (an auto-named sketch in the processing ide), gets transformed as follows.
|
12
|
+
|
13
|
+
```java
|
14
|
+
MyClass var;
|
15
|
+
|
16
|
+
void setup(){
|
17
|
+
size(200, 200);
|
18
|
+
var = new MyClass(23);
|
19
|
+
}
|
20
|
+
|
21
|
+
void draw(){
|
22
|
+
background(255, 0, 0);
|
23
|
+
fill(0, 0, 200);
|
24
|
+
ellipse(100, 100, 90, 120);
|
25
|
+
|
26
|
+
}
|
27
|
+
|
28
|
+
class MyClass{
|
29
|
+
float var;
|
30
|
+
MyClass(float var){
|
31
|
+
this.var = var;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
```
|
35
|
+
|
36
|
+
See the generated java code below, __note__ all those `imports`, the `class wrapper`, and that `MyClass` becomes a java [inner class][inner]. Also __note__ that `size` has moved to settings (_the processing guys decided not make this change from processing-2.0 to processing-3.0 explicit, in propane and propane we do expect size to be in settings_).
|
37
|
+
|
38
|
+
```java
|
39
|
+
import processing.core.*;
|
40
|
+
import processing.data.*;
|
41
|
+
import processing.event.*;
|
42
|
+
import processing.opengl.*;
|
43
|
+
|
44
|
+
import java.util.HashMap;
|
45
|
+
import java.util.ArrayList;
|
46
|
+
import java.io.File;
|
47
|
+
import java.io.BufferedReader;
|
48
|
+
import java.io.PrintWriter;
|
49
|
+
import java.io.InputStream;
|
50
|
+
import java.io.OutputStream;
|
51
|
+
import java.io.IOException;
|
52
|
+
|
53
|
+
public class sketch_161005a extends PApplet {
|
54
|
+
|
55
|
+
MyClass var;
|
56
|
+
|
57
|
+
public void setup(){
|
58
|
+
|
59
|
+
var = new MyClass(23);
|
60
|
+
}
|
61
|
+
|
62
|
+
public void draw(){
|
63
|
+
background(255, 0, 0);
|
64
|
+
fill(0, 0, 200);
|
65
|
+
ellipse(100, 100, 90, 120);
|
66
|
+
|
67
|
+
}
|
68
|
+
|
69
|
+
class MyClass{
|
70
|
+
float var;
|
71
|
+
MyClass(float var){
|
72
|
+
this.var = var;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
public void settings() { size(200, 200); }
|
76
|
+
static public void main(String[] passedArgs) {
|
77
|
+
String[] appletArgs = new String[] { "sketch_161005a" };
|
78
|
+
if (passedArgs != null) {
|
79
|
+
PApplet.main(concat(appletArgs, passedArgs));
|
80
|
+
} else {
|
81
|
+
PApplet.main(appletArgs);
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
```
|
86
|
+
|
87
|
+
## java reflection gets used a lot in processing ##
|
88
|
+
------
|
89
|
+
|
90
|
+
It is an unfortunate truth that [java reflection methods][reflection] are popular with both processing developers and some developers of supporting libraries. It is unfortunate because we have to go through hoops to use these methods in propane (and ruby-processing). The `captureEvent` and `videoEvent` are examples of reflection methods from the processing video developers. But we have made these readily available to propane users as a [simple library][library] load `load_library :video_event`. This is what you would do (if we had not created the `video_event` library):-
|
91
|
+
|
92
|
+
- create a java class `VideoInterface`
|
93
|
+
- compile the java class (including classpath)
|
94
|
+
- create a jar (and place it in the same folder as your sketch)
|
95
|
+
- modify the sketch to both `require` the `jar` and to `include` the interface.
|
96
|
+
|
97
|
+
### VideoInterface.java ###
|
98
|
+
|
99
|
+
See [javadoc here][video]
|
100
|
+
```java
|
101
|
+
package monkstone.videoevent;
|
102
|
+
import processing.video.Movie;
|
103
|
+
import processing.video.Capture;
|
104
|
+
/**
|
105
|
+
* This interface makes it easier/possible to use the reflection methods
|
106
|
+
* from Movie and Capture classes in Processing::App in propane
|
107
|
+
* @author Martin Prout
|
108
|
+
*/
|
109
|
+
public interface VideoInterface {
|
110
|
+
/**
|
111
|
+
* Used to implement reflection method in PApplet
|
112
|
+
* @see processing.video.Movie
|
113
|
+
* @param movie Movie
|
114
|
+
*/
|
115
|
+
public void movieEvent(Movie movie);
|
116
|
+
/**
|
117
|
+
* Used to implement reflection method in PApplet
|
118
|
+
* @see processing.video.Capture
|
119
|
+
* @param capture Capture
|
120
|
+
*/
|
121
|
+
public void captureEvent(Capture capture);
|
122
|
+
}
|
123
|
+
```
|
124
|
+
|
125
|
+
To match packaging the java file needs to be nested in `monkstone/videoevent` folders (it is unwise not to have a package) and compile and jar as follows, requires jdk8+.
|
126
|
+
|
127
|
+
```bash
|
128
|
+
# NB: classpath needs to be a fully qualified path to jars (not as below)
|
129
|
+
javac -cp video.jar:core.jar monkstone/videoevent/VideoInterface.java
|
130
|
+
|
131
|
+
jar -cvf video_event.jar monkstone
|
132
|
+
```
|
133
|
+
|
134
|
+
See below a sketch which using this VideoEvent interface, see the version using the propane provided `:video_event` library [here][bw]
|
135
|
+
|
136
|
+
### black_white_capture.rb ###
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
require 'picrate'
|
140
|
+
require_relative 'video_event'
|
141
|
+
|
142
|
+
class BlackAndWhiteCapture < Processing::App
|
143
|
+
load_libraries :video
|
144
|
+
include_package 'processing.video'
|
145
|
+
|
146
|
+
include Java::MonkstoneVideoevent::VideoInterface
|
147
|
+
|
148
|
+
attr_reader :cam, :my_shader
|
149
|
+
|
150
|
+
def setup
|
151
|
+
sketch_title 'Black & White Capture'
|
152
|
+
@my_shader = load_shader('bwfrag.glsl')
|
153
|
+
start_capture(width, height)
|
154
|
+
end
|
155
|
+
|
156
|
+
def start_capture(w, h)
|
157
|
+
@cam = Capture.new(self, w, h)
|
158
|
+
cam.start
|
159
|
+
end
|
160
|
+
|
161
|
+
def draw
|
162
|
+
image(cam, 0, 0)
|
163
|
+
return if mouse_pressed?
|
164
|
+
filter(my_shader)
|
165
|
+
end
|
166
|
+
|
167
|
+
# using snake case to match java reflection method
|
168
|
+
def captureEvent(c)
|
169
|
+
c.read
|
170
|
+
end
|
171
|
+
|
172
|
+
def settings
|
173
|
+
size(960, 544, P2D)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
BlackAndWhiteCapture.new
|
178
|
+
```
|
179
|
+
|
180
|
+
Now where this knowledge becomes really useful, is when you want to use another library, say the vanilla processing carnivore library whose `packetEvent` method also depends on java relection. Here is a suitable CarnivoreListener class.
|
181
|
+
|
182
|
+
### CarnivoreListener.java ###
|
183
|
+
|
184
|
+
```java
|
185
|
+
package monkstone;
|
186
|
+
|
187
|
+
/*
|
188
|
+
* Best to use a package to avoid namespace clashes, create your own
|
189
|
+
*/
|
190
|
+
public interface CarnivoreListener {
|
191
|
+
/*
|
192
|
+
* @param packet the CarnivorePacket, a reflection method
|
193
|
+
*/
|
194
|
+
public void packetEvent(org.rsg.carnivore.CarnivorePacket packet);
|
195
|
+
}
|
196
|
+
```
|
197
|
+
|
198
|
+
Which we compile as before
|
199
|
+
|
200
|
+
```bash
|
201
|
+
# NB: classpath needs to be a fully qualified path to jar (not as below)
|
202
|
+
javac -cp carnivore.jar monkstone/CarnivoreListener.java
|
203
|
+
|
204
|
+
jar -cvf carnivore_listener.jar monkstone
|
205
|
+
```
|
206
|
+
|
207
|
+
Here is an example sketch:-
|
208
|
+
|
209
|
+
### carnivore1.rb ###
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
# A Simple Carnivore Client -- print packets in Processing console
|
213
|
+
#
|
214
|
+
# Note: requires Carnivore Library for Processing (https://r-s-g.org/carnivore)
|
215
|
+
#
|
216
|
+
# + Windows: first install winpcap (https://winpcap.org)
|
217
|
+
# + Mac: first open a Terminal and execute this commmand: sudo chmod 777 /dev/bpf*
|
218
|
+
# you need to do this each time you reboot Mac
|
219
|
+
# + Linux: run with difficulty (run with sudo rights arghh!!!) also install libpcap
|
220
|
+
require 'picrate'
|
221
|
+
|
222
|
+
class CarnivoreListener < Processing::App
|
223
|
+
load_library :carnivore
|
224
|
+
include_package 'org.rsg.carnivore'
|
225
|
+
java_import 'org.rsg.lib.Log'
|
226
|
+
require_relative 'carnivore_listener'
|
227
|
+
include Java::Monkstone::CarnivoreListener
|
228
|
+
|
229
|
+
attr_reader :c
|
230
|
+
|
231
|
+
def settings
|
232
|
+
size(600, 400)
|
233
|
+
end
|
234
|
+
|
235
|
+
def setup
|
236
|
+
sketch_title 'Carnivore Example'
|
237
|
+
background(255)
|
238
|
+
@c = CarnivoreP5.new(self)
|
239
|
+
Log.setDebug(true) # comment out for quiet mode
|
240
|
+
# c.setVolumeLimit(4) #limit the output volume (optional)
|
241
|
+
# c.setShouldSkipUDP(true) #tcp packets only (optional)
|
242
|
+
end
|
243
|
+
|
244
|
+
def draw
|
245
|
+
end
|
246
|
+
|
247
|
+
# Called each time a new packet arrives
|
248
|
+
def packetEvent(p)
|
249
|
+
puts(format('(%s packet) %s > %s', p.strTransportProtocol, p.senderSocket, p.receiverSocket))
|
250
|
+
# puts(format('Payload: %s', p.ascii))
|
251
|
+
# puts("---------------------------\n")
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
CarnivoreListener.new
|
256
|
+
```
|
257
|
+
|
258
|
+
|
259
|
+
Another example of reflection usage the vanilla processing `selectInput` utility, that enable use of the native file chooser:-
|
260
|
+
|
261
|
+
### Native File Chooser ###
|
262
|
+
|
263
|
+
What a native file chooser sketch looks like in java, the `selectInput` [callback][callback] relies on java reflection under the hood. We have to explicity provide such a signature to use this feature in propane hence [FileChooser][FileChooser] library.
|
264
|
+
|
265
|
+
```java
|
266
|
+
public class chooser extends PApplet {
|
267
|
+
|
268
|
+
public void setup() {
|
269
|
+
selectInput("Select a file to process:", "fileSelected");
|
270
|
+
}
|
271
|
+
|
272
|
+
public void fileSelected(File selection) {
|
273
|
+
if (selection == null) {
|
274
|
+
println("Window was closed or the user hit cancel.");
|
275
|
+
} else {
|
276
|
+
println("User selected " + selection.getAbsolutePath());
|
277
|
+
}
|
278
|
+
}
|
279
|
+
static public void main(String[] passedArgs) {
|
280
|
+
String[] appletArgs = new String[] { "chooser" };
|
281
|
+
if (passedArgs != null) {
|
282
|
+
PApplet.main(concat(appletArgs, passedArgs));
|
283
|
+
} else {
|
284
|
+
PApplet.main(appletArgs);
|
285
|
+
}
|
286
|
+
}
|
287
|
+
}
|
288
|
+
```
|
289
|
+
|
290
|
+
Read more about java [reflection here][reflection].
|
291
|
+
|
292
|
+
[inner]:https://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html
|
293
|
+
[FileChooser]:{{ site.github.url }}/classes/chooser
|
294
|
+
[callback]:https://processing.org/reference/selectInput_.html
|
295
|
+
[library]:{{ site.github.url }}/libraries/video_event.html
|
296
|
+
[reflection]:https://docs.oracle.com/javase/tutorial/reflect/
|
297
|
+
[bw]:https://github.com/ruby-processing/picrate-examples/blob/master/library/video/capture/black_white_capture.rb
|
data/docs/_magic/ruby.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
---
|
2
|
+
layout: post
|
3
|
+
title: "Ruby"
|
4
|
+
keywords: ruby, java, meta
|
5
|
+
permalink: magic/custom.html
|
6
|
+
---
|
7
|
+
Here will go stuff about [meta programming][meta] etc, which is how we bring you Processing::Proxy etc see `app.rb`.
|
8
|
+
|
9
|
+
Using a Proxy module we are able create `java inner class` type access to including classes (_like vanilla processing_), we do this by creating custom method `:method_missing` and `:respond_to_missing?` methods
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
|
13
|
+
# @HACK purists may prefer 'forwardable' to the use of Proxy
|
14
|
+
# Importing PConstants here to access the processing constants
|
15
|
+
module Proxy
|
16
|
+
include Math
|
17
|
+
include HelperMethods
|
18
|
+
include Java::ProcessingCore::PConstants
|
19
|
+
|
20
|
+
def respond_to_missing?(symbol, include_private = false)
|
21
|
+
Propane.app.respond_to?(symbol, include_private) || super
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(name, *args, &block)
|
25
|
+
return Propane.app.send(name, *args) if Propane.app.respond_to? name
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end # Processing::Proxy
|
29
|
+
```
|
30
|
+
|
31
|
+
[meta]:https://www.toptal.com/ruby/ruby-metaprogramming-cooler-than-it-sounds
|
@@ -0,0 +1,66 @@
|
|
1
|
+
---
|
2
|
+
layout: post
|
3
|
+
title: "alternative ruby methods"
|
4
|
+
permalink: methods/alternative_methods.html
|
5
|
+
---
|
6
|
+
<style>
|
7
|
+
table{
|
8
|
+
border-collapse: collapse;
|
9
|
+
border-spacing: 0;
|
10
|
+
border:2px solid #0000FF;
|
11
|
+
}
|
12
|
+
|
13
|
+
th{
|
14
|
+
border:2px solid #0000FF;
|
15
|
+
}
|
16
|
+
</style>
|
17
|
+
You can use most [processing methods][processing] in propane, but where possible you should prefer these ruby alternatives (you should also prefer Vec2D and Vec3D to PVector).
|
18
|
+
Here is a list of ruby alternatives to some 'processing' convenience methods; which with the exception of `color`, `map1d`, `p5map`, `degrees` and `radians` are just regular ruby methods.
|
19
|
+
|
20
|
+
|function |processing |propane |
|
21
|
+
|---------- |------------- |------ |
|
22
|
+
|camera |`camera(args)` |`kamera(hash_args)` |
|
23
|
+
|color string |`color(#cc6600)` |`color('#cc6600')` |
|
24
|
+
|date/time | |`t = Time.now` |
|
25
|
+
| |`day` |`t.day` |
|
26
|
+
| |`hour` |`t.hour` |
|
27
|
+
| |`minute` |`t.minute` |
|
28
|
+
| |`second` |`t.second` |
|
29
|
+
| |`year` |`t.year` |
|
30
|
+
|custom math |`map(x, b0, eo, b1, e1)`|`map1d(x, (b0..e0), (b1..e1))`|
|
31
|
+
| |`map(x, b0, eo, b1, e1)`|`p5map(x, b0, e0, b1, e1)`|
|
32
|
+
| |`max(array) `|`array.max` |
|
33
|
+
| |`min(array) `|`array.min` |
|
34
|
+
|conversion |`degrees(theta)` |`theta.degrees` |
|
35
|
+
|conversion |`radians(theta)` |`theta.radians` |
|
36
|
+
|conversion |`hex(string)` |`string.hex` |
|
37
|
+
|conversion |`unhex(string)` |`string.to_i(base=16)`|
|
38
|
+
|conversion |`binary(c)` |`c.to_s(2)` |
|
39
|
+
|conversion |`unbinary(string)` |`string.to_i(base=2)`|
|
40
|
+
|math |`abs(x)` |`x.abs` |
|
41
|
+
|math |`round(x)` |`x.round` |
|
42
|
+
|math |`ceil(x)` |`x.ceil` |
|
43
|
+
|math |`random(x)` |`rand(x)` |
|
44
|
+
|math |`random(a, b)` |`rand(a..b)` |
|
45
|
+
|math power |`pow(a, b)` |`a**b` |
|
46
|
+
|square |`sq(x)` |`x * x` |
|
47
|
+
|print |`println(x)` |`puts x` |
|
48
|
+
|format |`trim(string)` |`string.strip` |
|
49
|
+
|format |`nf(float_value, 0, 2)` |`format('%.2f', float_value)`|
|
50
|
+
|format |`nf(num, digit)` |`num.to_s.rjust(digit, '0')`|
|
51
|
+
|format |`nf(nf(num, left, right)`|`see below` |
|
52
|
+
|
53
|
+
`num.to_s.rjust(left, '0').ljust(left + right, '0')`
|
54
|
+
|
55
|
+
For examples of using time in sketches see [learning JRubyArt blog][time], [timestamp][timestamp] and this [clock sketch][clock].
|
56
|
+
|
57
|
+
For example of `kamera` usage see [kamera][kamera]. To use `selectInput` see link to `File Chooser` in page header. We actually use the ruby Enumerable methods `max` and `min` methods to make `max(*array)` and `min(*methods)` available in propane, so you could use the processing form providing you splat the array, but it is simpler to use the ruby method directly further you have the option with ruby of changing the [comparator via a block][comparator].
|
58
|
+
|
59
|
+
NB: if you have any trouble with `save` or `save_frame` then use the option of providing an absolute path. You can easily do this using the `data_path` wrapper that does it for you see [data_path method][data_path].
|
60
|
+
|
61
|
+
[data_path]:{{site.github.url}}/data_path/
|
62
|
+
[time]:https://monkstone.github.io/time
|
63
|
+
[timestamp]:https://monkstone.github.io/timestamp/
|
64
|
+
[clock]:https://github.com/ruby-processing/picrate-examples/blob/master//library/fastmath/clock.rb
|
65
|
+
[kamera]:https://github.com/ruby-processing/picrate-examples/blob/master//basics/camera/kmove_eye.rb
|
66
|
+
[processing]:https://processing.org/reference/
|