picrate 1.2.3-java → 2.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile +3 -1
  4. data/README.md +8 -9
  5. data/Rakefile +10 -9
  6. data/bin/picrate +3 -1
  7. data/docs/_config.yml +1 -1
  8. data/docs/_editors/geany.md +1 -0
  9. data/docs/_gems/gems/gems.md +1 -1
  10. data/docs/_posts/2018-05-06-getting_started.md +4 -4
  11. data/docs/_posts/2018-05-06-install_jruby.md +5 -11
  12. data/docs/_posts/2018-05-11-arch-linux-arm.md +1 -11
  13. data/docs/_posts/2018-11-18-building-gem.md +2 -2
  14. data/docs/_posts/2018-11-27-getting_started_geany.md +4 -4
  15. data/docs/_posts/2019-11-11-getting_started_buster.md +4 -7
  16. data/docs/_posts/2020-03-09-auto_install_picrate.md +34 -0
  17. data/docs/_posts/2020-05-11-getting_started_manjaro.md +94 -0
  18. data/docs/about.md +1 -1
  19. data/lib/picrate.rb +1 -1
  20. data/lib/picrate/app.rb +11 -3
  21. data/lib/picrate/creators/parameters.rb +8 -8
  22. data/lib/picrate/creators/sketch_factory.rb +5 -3
  23. data/lib/picrate/helper_methods.rb +21 -21
  24. data/lib/picrate/helpers/numeric.rb +2 -0
  25. data/lib/picrate/library.rb +5 -1
  26. data/lib/picrate/library_loader.rb +2 -0
  27. data/lib/picrate/native_folder.rb +2 -1
  28. data/lib/picrate/native_loader.rb +3 -0
  29. data/lib/picrate/runner.rb +5 -2
  30. data/lib/picrate/version.rb +1 -1
  31. data/library/boids/boids.rb +17 -8
  32. data/library/chooser/chooser.rb +10 -9
  33. data/library/color_group/color_group.rb +2 -0
  34. data/library/control_panel/control_panel.rb +7 -4
  35. data/library/dxf/dxf.rb +2 -0
  36. data/library/library_proxy/library_proxy.rb +2 -0
  37. data/library/net/net.rb +2 -0
  38. data/library/slider/slider.rb +24 -23
  39. data/library/vector_utils/vector_utils.rb +4 -0
  40. data/library/video_event/video_event.rb +2 -0
  41. data/picrate.gemspec +13 -14
  42. data/pom.rb +28 -26
  43. data/pom.xml +18 -6
  44. data/src/main/java/monkstone/ColorUtil.java +1 -1
  45. data/src/main/java/monkstone/MathToolModule.java +1 -1
  46. data/src/main/java/monkstone/PicrateLibrary.java +8 -8
  47. data/src/main/java/monkstone/fastmath/Deglut.java +16 -16
  48. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  49. data/src/main/java/monkstone/noise/SimplexNoise.java +3 -3
  50. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  51. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  52. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +12 -12
  53. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  54. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  55. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  56. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  57. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  58. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  59. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
  60. data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
  61. data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
  62. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  63. data/src/main/java/processing/awt/PGraphicsJava2D.java +33 -36
  64. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  65. data/src/main/java/processing/awt/PSurfaceAWT.java +0 -20
  66. data/src/main/java/processing/awt/ShimAWT.java +545 -0
  67. data/src/main/java/processing/core/PApplet.java +699 -1523
  68. data/src/main/java/processing/core/PConstants.java +180 -180
  69. data/src/main/java/processing/core/PFont.java +2 -2
  70. data/src/main/java/processing/core/PGraphics.java +190 -176
  71. data/src/main/java/processing/core/PImage.java +1536 -1721
  72. data/src/main/java/processing/core/PMatrix.java +39 -39
  73. data/src/main/java/processing/core/PSurface.java +69 -103
  74. data/src/main/java/processing/core/PSurfaceNone.java +29 -0
  75. data/src/main/java/processing/core/PVector.java +2 -2
  76. data/src/main/java/processing/data/FloatDict.java +251 -284
  77. data/src/main/java/processing/data/TableRow.java +32 -32
  78. data/src/main/java/processing/dxf/RawDXF.java +3 -3
  79. data/src/main/java/processing/net/Client.java +1 -1
  80. data/src/main/java/processing/opengl/PGL.java +1016 -4132
  81. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +223 -184
  82. data/src/main/java/processing/opengl/PJOGL.java +374 -1526
  83. data/src/main/java/processing/opengl/PShapeOpenGL.java +5 -6
  84. data/src/main/java/processing/opengl/PSurfaceJOGL.java +262 -147
  85. data/test/color_group_test.rb +4 -4
  86. data/test/deglut_spec_test.rb +2 -0
  87. data/test/helper_methods_test.rb +41 -13
  88. data/test/math_tool_test.rb +46 -37
  89. data/test/respond_to_test.rb +5 -3
  90. data/test/sketches/key_event.rb +2 -2
  91. data/test/sketches/library/my_library/my_library.rb +3 -0
  92. data/test/test_helper.rb +2 -0
  93. data/test/vecmath_spec_test.rb +30 -19
  94. data/vendors/Rakefile +13 -7
  95. data/vendors/{picrate_sketches.geany → geany.rb} +32 -7
  96. metadata +26 -47
  97. data/docs/_posts/2018-06-26-auto_install_picrate.md +0 -30
  98. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  99. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  100. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  101. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: false
2
+
3
+ require 'jruby'
2
4
  require_relative 'helper_methods'
3
5
  require_relative 'library_loader'
4
6
  # A wrapper module for the processing App
@@ -49,7 +51,10 @@ module Processing
49
51
 
50
52
  # All sketches extend this class
51
53
  class App < PApplet
52
- include Math, MathTool, HelperMethods, Render
54
+ include Render
55
+ include HelperMethods
56
+ include MathTool
57
+ include Math
53
58
  # Alias some methods for familiarity for Shoes coders.
54
59
  alias oval ellipse
55
60
  alias stroke_width stroke_weight
@@ -101,6 +106,7 @@ module Processing
101
106
  # Processing call them by their expected Java names.
102
107
  def method_added(method_name) #:nodoc:
103
108
  return unless METHODS_TO_ALIAS.key?(method_name)
109
+
104
110
  alias_method METHODS_TO_ALIAS[method_name], method_name
105
111
  end
106
112
  end
@@ -113,6 +119,7 @@ module Processing
113
119
  # Guard against invalid input.
114
120
  proxy_java_fields
115
121
  raise TypeError unless options.is_a?(Hash) && arguments.is_a?(Array)
122
+
116
123
  # Set up the sketch.
117
124
  super()
118
125
  post_initialize(options)
@@ -132,8 +139,7 @@ module Processing
132
139
  super(*args)
133
140
  end
134
141
 
135
- def post_initialize(_args)
136
- end
142
+ def post_initialize(_args); end
137
143
 
138
144
  def data_path(dat)
139
145
  dat_root = File.join(SKETCH_ROOT, 'data')
@@ -162,6 +168,7 @@ module Processing
162
168
  # Processing call them by their expected Java names.
163
169
  def method_added(method_name) #:nodoc:
164
170
  return unless METHODS_TO_ALIAS.key?(method_name)
171
+
165
172
  alias_method METHODS_TO_ALIAS[method_name], method_name
166
173
  end
167
174
  end
@@ -179,6 +186,7 @@ module Processing
179
186
 
180
187
  def method_missing(name, *args, &block)
181
188
  return Processing.app.send(name, *args) if Processing.app.respond_to? name
189
+
182
190
  super
183
191
  end
184
192
  end # Processing::Proxy
@@ -11,13 +11,13 @@ module Parameters
11
11
  PARAM = { 'sketch' =>
12
12
  { 'width' => 640, 'height' => 480, 'mode' => 'P2D' } }.freeze
13
13
 
14
- def self.write
15
- FileUtils.mkdir_p PATH
16
- File.write(FILE, PARAM.to_yaml)
17
- end
14
+ def self.write
15
+ FileUtils.mkdir_p PATH
16
+ File.write(FILE, PARAM.to_yaml)
17
+ end
18
18
 
19
- def self.read
20
- write unless File.exist?(FILE)
21
- YAML.load_file(FILE)
22
- end
19
+ def self.read
20
+ write unless File.exist?(FILE)
21
+ YAML.load_file(FILE)
23
22
  end
23
+ end
@@ -1,8 +1,10 @@
1
- require_relative 'sketch_writer'
1
+ # frozen_string_literal: true
2
2
 
3
+ require_relative 'sketch_writer'
4
+ # Sketch Factory
3
5
  class SketchFactory
4
- NAMES = %w[One Two Three]
5
- def initialize(argc)
6
+ NAMES = %w[One Two Three].freeze
7
+ def initialize(_argc)
6
8
  NAMES.each do |name|
7
9
  SketchWriter.new(File.basename(name, '.rb')).write
8
10
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: false
2
+
2
3
  # processing module wrapper
3
4
  require_relative 'helpers/numeric'
4
5
  module Processing
@@ -52,6 +53,7 @@ module Processing
52
53
 
53
54
  def color(*args)
54
55
  return super(*args) unless args.length == 1
56
+
55
57
  super(hex_color(args[0]))
56
58
  end
57
59
 
@@ -66,11 +68,8 @@ module Processing
66
68
  # Overrides Processing convenience function thread, which takes a String
67
69
  # arg (for a function) to more rubylike version, takes a block...
68
70
  def thread(&block)
69
- if block_given?
70
- Thread.new(&block)
71
- else
72
- raise ArgumentError, 'thread must be called with a block', caller
73
- end
71
+ warn 'you must provide a block' unless block_given?
72
+ Java::JavaLang::Thread.new(&block).start
74
73
  end
75
74
 
76
75
  # explicitly provide 'processing.org' min instance method
@@ -94,9 +93,9 @@ module Processing
94
93
  def dist(*args)
95
94
  case args.length
96
95
  when 4
97
- return dist2d(*args)
96
+ dist2d(*args)
98
97
  when 6
99
- return dist3d(*args)
98
+ dist3d(*args)
100
99
  else
101
100
  raise ArgumentError, 'takes 4 or 6 parameters'
102
101
  end
@@ -111,13 +110,13 @@ module Processing
111
110
  # Here's a convenient way to look for them.
112
111
  def find_method(method_name)
113
112
  reg = Regexp.new(method_name.to_s, true)
114
- methods.sort.select { |meth| reg.match(meth) }
113
+ methods.sort.select { |meth| reg.match?(meth) }
115
114
  end
116
115
 
117
116
  # Proxy over a list of Java declared fields that have the same name as
118
117
  # some methods. Add to this list as needed.
119
118
  def proxy_java_fields
120
- fields = %w(key frameRate mousePressed keyPressed)
119
+ fields = %w[key frameRate mousePressed keyPressed]
121
120
  methods = fields.map { |field| java_class.declared_field(field) }
122
121
  @declared_fields = Hash[fields.zip(methods)]
123
122
  end
@@ -163,6 +162,7 @@ module Processing
163
162
  # frame_rate needs to support reading and writing
164
163
  def frame_rate(fps = nil)
165
164
  return @declared_fields['frameRate'].value(java_self) unless fps
165
+
166
166
  super(fps)
167
167
  end
168
168
 
@@ -178,19 +178,17 @@ module Processing
178
178
 
179
179
  private
180
180
 
181
- INTEGER_COL = -> (x) { x.is_a?(Integer) }
182
- STRING_COL = -> (x) { x.is_a?(String) }
183
- FLOAT_COL = -> (x) { x.is_a?(Float) }
184
181
  # parse single argument color int/double/String
185
- def hex_color(a)
186
- case a
187
- when INTEGER_COL
188
- Java::Monkstone::ColorUtil.colorLong(a)
189
- when STRING_COL
190
- return Java::Monkstone::ColorUtil.colorString(a) if a =~ /#\h+/
191
- raise StandardError, 'Dodgy Hexstring'
192
- when FLOAT_COL
193
- Java::Monkstone::ColorUtil.colorDouble(a)
182
+ def hex_color(arg)
183
+ case arg
184
+ when Integer
185
+ Java::Monkstone::ColorUtil.colorLong(arg)
186
+ when String
187
+ raise StandardError, 'Dodgy Hexstring' unless arg.match(/#\h{6}$/)
188
+
189
+ Java::Monkstone::ColorUtil.colorString(arg)
190
+ when Float
191
+ Java::Monkstone::ColorUtil.colorDouble(arg)
194
192
  else
195
193
  raise StandardError, 'Dodgy Color Conversion'
196
194
  end
@@ -200,6 +198,7 @@ module Processing
200
198
  dx = args[0] - args[2]
201
199
  dy = args[1] - args[3]
202
200
  return 0 if dx.abs < EPSILON && dy.abs < EPSILON
201
+
203
202
  Math.hypot(dx, dy)
204
203
  end
205
204
 
@@ -208,6 +207,7 @@ module Processing
208
207
  dy = args[1] - args[4]
209
208
  dz = args[2] - args[5]
210
209
  return 0 if dx.abs < EPSILON && dy.abs < EPSILON && dz.abs < EPSILON
210
+
211
211
  Math.sqrt(dx * dx + dy * dy + dz * dz)
212
212
  end
213
213
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Numeric #:nodoc:
2
4
  def degrees
3
5
  self * 57.29577951308232
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'native_folder'
2
4
  require_relative 'native_loader'
3
5
  require 'pathname'
@@ -18,6 +20,7 @@ class Library
18
20
  return if (@path = Pathname.new(
19
21
  File.join(PICRATE_ROOT, 'library', name, "#{name}.rb")
20
22
  )).exist?
23
+
21
24
  locate_java
22
25
  end
23
26
 
@@ -46,10 +49,11 @@ class Library
46
49
  end
47
50
 
48
51
  def load_jars
49
- Dir.glob("#{dir}/*.jar").each do |jar|
52
+ Dir.glob("#{dir}/*.jar").sort.each do |jar|
50
53
  require jar
51
54
  end
52
55
  return true unless native_binaries?
56
+
53
57
  add_binaries_to_classpath
54
58
  end
55
59
 
@@ -33,10 +33,12 @@ module Processing
33
33
 
34
34
  def loader(name)
35
35
  return true if @loaded_libraries.include?(name)
36
+
36
37
  fname = name.to_s
37
38
  library = Library.new(fname)
38
39
  library.locate
39
40
  return require_library(library, name) if library.ruby?
41
+
40
42
  warn("Not found library: #{fname}") unless library.exist?
41
43
  load_jars(library, name)
42
44
  end
@@ -7,7 +7,7 @@ class NativeFolder
7
7
 
8
8
  LINUX_FORMAT = 'linux%s'.freeze
9
9
  ARM32 = '-armv6hf'.freeze
10
- # ARM64 = '-aarch64'.freeze
10
+ ARM64 = '-aarch64'.freeze
11
11
 
12
12
  def initialize
13
13
  @os = RbConfig::CONFIG['host_os'].downcase
@@ -18,6 +18,7 @@ class NativeFolder
18
18
  if /linux/.match?(os)
19
19
  return format(LINUX_FORMAT, '64') if /amd64/.match?(bit)
20
20
  return format(LINUX_FORMAT, ARM32) if /arm/.match?(bit)
21
+ return format(LINUX_FORMAT, ARM64) if /aarch/.match?(bit)
21
22
  end
22
23
  raise RuntimeError, "Unsupported Architecture"
23
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class knows how to dynamically set the 'java' native library path
2
4
  # It might not work with java 9?
3
5
  class NativeLoader
@@ -21,6 +23,7 @@ class NativeLoader
21
23
  field = JC::Class.for_name('java.lang.ClassLoader')
22
24
  .get_declared_field('sys_paths')
23
25
  return unless field
26
+
24
27
  field.accessible = true # some jruby magic
25
28
  field.set(JC::Class.for_name('java.lang.System').get_class_loader, nil)
26
29
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: false
2
+
2
3
  require 'optparse'
3
4
  require_relative 'version'
4
5
 
@@ -40,7 +41,7 @@ module Processing
40
41
  end
41
42
 
42
43
  options[:install] = false
43
- message = '<Samples><GLVideo><Video><Sound> Install samples or library'
44
+ message = '<Samples><Video> Install samples or library'
44
45
  opts.on('-i', '--install', message) do
45
46
  options[:install] = true
46
47
  end
@@ -80,7 +81,9 @@ module Processing
80
81
  library ||= 'new'
81
82
  choice = library.downcase
82
83
  case choice
83
- when /samples|sound|video/
84
+ when /sound/
85
+ warn 'The sound library is broken, try minim instead'
86
+ when /samples|video/
84
87
  system "cd #{PICRATE_ROOT}/vendors && rake install_#{choice}"
85
88
  when /new/
86
89
  # install samples and config geany
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PiCrate
4
- VERSION = '1.2.3'
4
+ VERSION = '2.1.0'
5
5
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Boids -- after Tom de Smedt.
3
4
  # See his Python version: http://nodebox.net/code/index.php/Boids
4
5
  # This is an example of how a pure-Ruby library can work. Original for
@@ -8,7 +9,8 @@ class Boid
8
9
  attr_reader :boids
9
10
  attr_accessor :vel, :pos, :is_perching, :perch_time
10
11
  def initialize(boids, pos)
11
- @boids, @flock = boids, boids
12
+ @boids = boids
13
+ @flock = boids
12
14
  @pos = pos
13
15
  @vel = Vec2D.new
14
16
  @is_perching = false
@@ -54,6 +56,7 @@ class Boid
54
56
  # Tweet, Tweet! The boid police will bust you for breaking the speed limit.
55
57
  most = [vel.x.abs, vel.y.abs].max
56
58
  return if most < max
59
+
57
60
  scale = max / most.to_f
58
61
  @vel *= scale
59
62
  end
@@ -76,7 +79,7 @@ class Boids
76
79
  extend Forwardable
77
80
  def_delegators(:@boids, :reject, :<<, :each, :shuffle!, :length, :next)
78
81
 
79
- attr_reader :has_goal, :perch, :perch_tm, :perch_y
82
+ attr_reader :has_goal, :perchance, :perch_tm, :perch_y
80
83
 
81
84
  def initialize
82
85
  @boids = []
@@ -89,15 +92,19 @@ class Boids
89
92
 
90
93
  def setup(n, x, y, w, h)
91
94
  n.times do
92
- dx, dy = rand(w), rand(h)
95
+ dx = rand(w)
96
+ dy = rand(h)
93
97
  self << Boid.new(self, Vec2D.new(x + dx, y + dy))
94
98
  end
95
- @x, @y, @w, @h = x, y, w, h
99
+ @x = x
100
+ @y = y
101
+ @w = w
102
+ @h = h
96
103
  @scattered = false
97
104
  @scatter = 0.005
98
105
  @scatter_time = 50.0
99
106
  @scatter_i = 0.0
100
- @perch = 1.0 # Lower this number to divebomb.
107
+ @perchance = 1.0 # Lower this number to divebomb.
101
108
  @perch_y = h
102
109
  @perch_tm = -> { 25.0 + rand(50.0) }
103
110
  @has_goal = false
@@ -118,11 +125,11 @@ class Boids
118
125
  def perch(ground = nil, chance = 1.0, frames = nil)
119
126
  @perch_tm = frames.nil? ? -> { 25.0 + rand(50.0) } : frames
120
127
  @perch_y = ground.nil? ? @h : ground
121
- @perch = chance
128
+ @perchance = chance
122
129
  end
123
130
 
124
131
  def no_perch
125
- @perch = 0.0
132
+ @perchance= 0.0
126
133
  end
127
134
 
128
135
  def reset_goal(target)
@@ -145,13 +152,15 @@ class Boids
145
152
 
146
153
  def constrain
147
154
  # Put them boids in a cage.
148
- dx, dy = @w * 0.1, @h * 0.1
155
+ dx = @w * 0.1
156
+ dy = @h * 0.1
149
157
  each do |b|
150
158
  b.vel.x += rand(dx) if b.pos.x < @x - dx
151
159
  b.vel.y += rand(dy) if b.pos.y < @y - dy
152
160
  b.vel.x -= rand(dx) if b.pos.x > @x + @w + dx
153
161
  b.vel.y -= rand(dy) if b.pos.y > @y + @h + dy
154
162
  next unless b.pos.y > perch_y && rand < perch
163
+
155
164
  b.pos.y = perch_y
156
165
  b.vel.y = b.vel.y.abs * -0.2
157
166
  b.is_perching = true
@@ -1,18 +1,19 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Usage:
3
4
  # load_library :chooser
4
- #
5
+ #
5
6
  # def setup
6
- # java_signature 'void selectInput(String, String)'
7
- # selectInput('Select a file to process:', 'fileSelected')
7
+ # java_signature 'void selectInput(String, String)'
8
+ # selectInput('Select a file to process:', 'fileSelected')
8
9
  # end
9
- #
10
+ #
10
11
  # def fileSelected(selection)
11
- # if selection.nil?
12
- # puts 'Window was closed or the user hit cancel.'
13
- # else
14
- # puts format('User selected %s', selection.get_absolute_path)
15
- # end
12
+ # if selection.nil?
13
+ # puts 'Window was closed or the user hit cancel.'
14
+ # else
15
+ # puts format('User selected %s', selection.get_absolute_path)
16
+ # end
16
17
  # end
17
18
  class Processing::App
18
19
  include Java::MonkstoneFilechooser::Chooser
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  java_import Java::Monkstone::ColorUtil
2
4
 
3
5
  # class wraps a java color array (of signed int), supports shuffle!, last and
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Here's a little library for quickly hooking up controls to sketches.
2
4
  # For messing with the parameters and such.
3
5
  # These controls will set instance variables on the sketches.
@@ -25,7 +27,7 @@ module ControlPanel
25
27
  add_change_listener do
26
28
  update_label(label, name, value)
27
29
  ControlPanel.app_value(name, value)
28
- proc.call(value) if proc
30
+ proc&.call(value)
29
31
  end
30
32
  ControlPanel.app_value(name, val)
31
33
  end
@@ -49,7 +51,7 @@ module ControlPanel
49
51
  control_panel.add_element(self, name)
50
52
  add_action_listener do
51
53
  ControlPanel.app_value(name, value) unless value.nil?
52
- proc.call(value) if proc
54
+ proc&.call(value)
53
55
  end
54
56
  set_selected_index(initial_value ? elements.index(initial_value) : 0)
55
57
  end
@@ -69,7 +71,7 @@ module ControlPanel
69
71
  control_panel.add_element(self, name, false)
70
72
  add_action_listener do
71
73
  ControlPanel.app_value(name, value)
72
- proc.call(value) if proc
74
+ proc&.call(value)
73
75
  end
74
76
  end
75
77
 
@@ -87,7 +89,7 @@ module ControlPanel
87
89
  control_panel.add_element(self, name, false, true)
88
90
  add_action_listener do
89
91
  Processing.app.send(name)
90
- proc.call(value) if proc
92
+ proc&.call(value)
91
93
  end
92
94
  end
93
95
  end
@@ -171,6 +173,7 @@ module ControlPanel
171
173
  def control_panel
172
174
  @control_panel ||= ControlPanel::Panel.new
173
175
  return @control_panel unless block_given?
176
+
174
177
  yield(@control_panel)
175
178
  @control_panel.display
176
179
  @control_panel.set_visible true