summaryrefslogtreecommitdiffhomepage
path: root/docs
diff options
context:
space:
mode:
authorAmir Rajan <[email protected]>2020-11-13 01:29:16 -0600
committerAmir Rajan <[email protected]>2020-11-13 01:29:16 -0600
commit128fa1d90cea6289605a49daf56a0cbb72e2dd28 (patch)
tree5cfdb499d275e2b43075e4d6a076365fc58ff0f7 /docs
parent05cbef7fb8224332795e5685be499d81d20e7d93 (diff)
downloaddragonruby-game-toolkit-contrib-128fa1d90cea6289605a49daf56a0cbb72e2dd28.tar.gz
dragonruby-game-toolkit-contrib-128fa1d90cea6289605a49daf56a0cbb72e2dd28.zip
synced from DRGTK 1.27
Diffstat (limited to 'docs')
-rw-r--r--docs/docs.html2645
-rw-r--r--docs/docs.txt2664
-rw-r--r--docs/parse_log.txt11031
3 files changed, 15919 insertions, 421 deletions
diff --git a/docs/docs.html b/docs/docs.html
index 0b76535..8fafcb1 100644
--- a/docs/docs.html
+++ b/docs/docs.html
@@ -1,7 +1,7 @@
<html>
<head>
<title>DragonRuby Game Toolkit Documentation</title>
- <link href="docs.css?ver=1602116477" rel="stylesheet" type="text/css" media="all">
+ <link href="docs.css?ver=1605252394" rel="stylesheet" type="text/css" media="all">
</head>
<body>
<div id='toc'>
@@ -31,9 +31,9 @@
<li><a href='#--cheatsheet--using--args.state--to-store-your-game-state'>CHEATSHEET: Using <code>args.state</code> To Store Your Game State</a></li>
<li><a href='#--cheatsheet--troubleshoot-performance'>CHEATSHEET: Troubleshoot Performance</a></li>
<li><a href='#--docs---gtk--runtime-'>DOCS: <code>GTK::Runtime</code></a></li>
+<li><a href='#--docs---gtk--runtime#write_file-'>DOCS: <code>GTK::Runtime#write_file</code></a></li>
<li><a href='#--docs---gtk--runtime#reset-'>DOCS: <code>GTK::Runtime#reset</code></a></li>
<li><a href='#--docs---gtk--runtime#calcstringbox-'>DOCS: <code>GTK::Runtime#calcstringbox</code></a></li>
-<li><a href='#--docs---gtk--runtime#write_file-'>DOCS: <code>GTK::Runtime#write_file</code></a></li>
<li><a href='#--docs---array-'>DOCS: <code>Array</code></a></li>
<li><a href='#--docs---array#map-'>DOCS: <code>Array#map</code></a></li>
<li><a href='#--docs---array#each-'>DOCS: <code>Array#each</code></a></li>
@@ -46,6 +46,7 @@
<li><a href='#--docs---gtk--outputs-'>DOCS: <code>GTK::Outputs</code></a></li>
<li><a href='#--docs---gtk--outputs#solids-'>DOCS: <code>GTK::Outputs#solids</code></a></li>
<li><a href='#--docs---gtk--outputs#borders-'>DOCS: <code>GTK::Outputs#borders</code></a></li>
+<li><a href='#--docs---gtk--outputs#screenshots-'>DOCS: <code>GTK::Outputs#screenshots</code></a></li>
<li><a href='#--docs---gtk--mouse-'>DOCS: <code>GTK::Mouse</code></a></li>
<li><a href='#--docs---gtk--mousepoint-'>DOCS: <code>GTK::MousePoint</code></a></li>
<li><a href='#--docs---gtk--openentity-'>DOCS: <code>GTK::OpenEntity</code></a></li>
@@ -69,17 +70,19 @@
<li><a href='#--learn-ruby-optional---intermediate-ruby-primer---functions.txt'>Learn Ruby Optional - Intermediate Ruby Primer - functions.txt</a></li>
<li><a href='#--learn-ruby-optional---intermediate-ruby-primer---arrays.txt'>Learn Ruby Optional - Intermediate Ruby Primer - arrays.txt</a></li>
<li><a href='#--learn-ruby-optional---intermediate-ruby-primer---main.rb'>Learn Ruby Optional - Intermediate Ruby Primer - main.rb</a></li>
-<li><a href='#--learn-ruby-optional---intermediate-ruby-primer---repl.rb'>Learn Ruby Optional - Intermediate Ruby Primer - repl.rb</a></li>
<li><a href='#--rendering-basics---labels---main.rb'>Rendering Basics - Labels - main.rb</a></li>
<li><a href='#--rendering-basics---lines---main.rb'>Rendering Basics - Lines - main.rb</a></li>
<li><a href='#--rendering-basics---solids-borders---main.rb'>Rendering Basics - Solids Borders - main.rb</a></li>
<li><a href='#--rendering-basics---sprites---main.rb'>Rendering Basics - Sprites - main.rb</a></li>
<li><a href='#--rendering-basics---sounds---main.rb'>Rendering Basics - Sounds - main.rb</a></li>
+<li><a href='#--rendering-basics---audio-mixer---main.rb'>Rendering Basics - Audio Mixer - main.rb</a></li>
+<li><a href='#--rendering-basics---sound-synthesis---main.rb'>Rendering Basics - Sound Synthesis - main.rb</a></li>
<li><a href='#--input-basics---keyboard---main.rb'>Input Basics - Keyboard - main.rb</a></li>
<li><a href='#--input-basics---mouse---main.rb'>Input Basics - Mouse - main.rb</a></li>
<li><a href='#--input-basics---mouse-point-to-rect---main.rb'>Input Basics - Mouse Point To Rect - main.rb</a></li>
<li><a href='#--input-basics---mouse-rect-to-rect---main.rb'>Input Basics - Mouse Rect To Rect - main.rb</a></li>
<li><a href='#--input-basics---controller---main.rb'>Input Basics - Controller - main.rb</a></li>
+<li><a href='#--input-basics---touch---main.rb'>Input Basics - Touch - main.rb</a></li>
<li><a href='#--rendering-sprites---animation-using-separate-pngs---main.rb'>Rendering Sprites - Animation Using Separate Pngs - main.rb</a></li>
<li><a href='#--rendering-sprites---animation-using-sprite-sheet---main.rb'>Rendering Sprites - Animation Using Sprite Sheet - main.rb</a></li>
<li><a href='#--rendering-sprites---animation-states---main.rb'>Rendering Sprites - Animation States - main.rb</a></li>
@@ -100,6 +103,7 @@
<li><a href='#--advanced-rendering---render-target-viewports---main.rb'>Advanced Rendering - Render Target Viewports - main.rb</a></li>
<li><a href='#--advanced-rendering---render-primitive-hierarchies---main.rb'>Advanced Rendering - Render Primitive Hierarchies - main.rb</a></li>
<li><a href='#--advanced-rendering---render-primitives-as-hash---main.rb'>Advanced Rendering - Render Primitives As Hash - main.rb</a></li>
+<li><a href='#--advanced-rendering---pixel-arrays---main.rb'>Advanced Rendering - Pixel Arrays - main.rb</a></li>
<li><a href='#--tweening-lerping-easing-functions---easing-functions---main.rb'>Tweening Lerping Easing Functions - Easing Functions - main.rb</a></li>
<li><a href='#--tweening-lerping-easing-functions---cubic-bezier---main.rb'>Tweening Lerping Easing Functions - Cubic Bezier - main.rb</a></li>
<li><a href='#--tweening-lerping-easing-functions---easing-using-spline---main.rb'>Tweening Lerping Easing Functions - Easing Using Spline - main.rb</a></li>
@@ -123,6 +127,8 @@
<li><a href='#--advanced-debugging---unit-tests---state_serialization_experimental_tests.rb'>Advanced Debugging - Unit Tests - state_serialization_experimental_tests.rb</a></li>
<li><a href='#--http---retrieve-images---main.rb'>Http - Retrieve Images - main.rb</a></li>
<li><a href='#--12-c-extensions---basics---main.rb'>12 C Extensions - Basics - main.rb</a></li>
+<li><a href='#--12-c-extensions---intermediate---main.rb'>12 C Extensions - Intermediate - main.rb</a></li>
+<li><a href='#--12-c-extensions---native-pixel-arrays---main.rb'>12 C Extensions - Native Pixel Arrays - main.rb</a></li>
<li><a href='#--3d---3d-cube---main.rb'>3d - 3d Cube - main.rb</a></li>
<li><a href='#--arcade---dueling-starships---main.rb'>Arcade - Dueling Starships - main.rb</a></li>
<li><a href='#--arcade/flappy-dragon/credits.txt'>arcade/flappy dragon/credits.txt</a></li>
@@ -140,7 +146,6 @@
<li><a href='#--platformer---clepto-frog---map.rb'>Platformer - Clepto Frog - map.rb</a></li>
<li><a href='#--platformer---gorillas-basic---credits.txt'>Platformer - Gorillas Basic - credits.txt</a></li>
<li><a href='#--platformer---gorillas-basic---main.rb'>Platformer - Gorillas Basic - main.rb</a></li>
-<li><a href='#--platformer---gorillas-basic---repl.rb'>Platformer - Gorillas Basic - repl.rb</a></li>
<li><a href='#--platformer---gorillas-basic---tests.rb'>Platformer - Gorillas Basic - tests.rb</a></li>
<li><a href='#--platformer---gorillas-basic---tests---building_generation_tests.rb'>Platformer - Gorillas Basic - Tests - building_generation_tests.rb</a></li>
<li><a href='#--platformer---the-little-probe---main.rb'>Platformer - The Little Probe - main.rb</a></li>
@@ -150,7 +155,6 @@
<li><a href='#--rpg-narrative---choose-your-own-adventure---main.rb'>Rpg Narrative - Choose Your Own Adventure - main.rb</a></li>
<li><a href='#--rpg-narrative---return-of-serenity---lowrez_simulator.rb'>Rpg Narrative - Return Of Serenity - lowrez_simulator.rb</a></li>
<li><a href='#--rpg-narrative---return-of-serenity---main.rb'>Rpg Narrative - Return Of Serenity - main.rb</a></li>
-<li><a href='#--rpg-narrative---return-of-serenity---repl.rb'>Rpg Narrative - Return Of Serenity - repl.rb</a></li>
<li><a href='#--rpg-narrative---return-of-serenity---require.rb'>Rpg Narrative - Return Of Serenity - require.rb</a></li>
<li><a href='#--rpg-narrative---return-of-serenity---storyline.rb'>Rpg Narrative - Return Of Serenity - storyline.rb</a></li>
<li><a href='#--rpg-narrative---return-of-serenity---storyline_anka.rb'>Rpg Narrative - Return Of Serenity - storyline_anka.rb</a></li>
@@ -187,12 +191,17 @@
<li><a href='#--geometry.rb'>geometry.rb</a></li>
<li><a href='#--grid.rb'>grid.rb</a></li>
<li><a href='#--inputs.rb'>inputs.rb</a></li>
+<li><a href='#--ios_wizard.rb'>ios_wizard.rb</a></li>
+<li><a href='#--itch_wizard.rb'>itch_wizard.rb</a></li>
+<li><a href='#--layout.rb'>layout.rb</a></li>
<li><a href='#--log.rb'>log.rb</a></li>
<li><a href='#--numeric.rb'>numeric.rb</a></li>
+<li><a href='#--runtime/draw.rb'>runtime/draw.rb</a></li>
<li><a href='#--runtime/framerate_diagnostics.rb'>runtime/framerate_diagnostics.rb</a></li>
<li><a href='#--string.rb'>string.rb</a></li>
<li><a href='#--tests.rb'>tests.rb</a></li>
<li><a href='#--trace.rb'>trace.rb</a></li>
+<li><a href='#--wizards.rb'>wizards.rb</a></li>
</ul> </div>
<div id='content'>
<h1 id='--dragonruby-game-toolkit-live-docs'>DragonRuby Game Toolkit Live Docs</h1>
@@ -1144,6 +1153,16 @@ end
<p>
The GTK::Runtime class is the core of DragonRuby. It is globally accessible via <code>$gtk</code>.
</p>
+<h1 id='--docs---gtk--runtime#write_file-'>DOCS: <code>GTK::Runtime#write_file</code></h1>
+<p>
+This function takes in two parameters. The first paramter is the file path and assumes the the game directory is the root. The second parameter is the string that will be written. The method overwrites whatever is currently in the file. Use <code>GTK::Runtime#append_file</code> to append to the file as opposed to overwriting.
+</p>
+<pre>def tick args
+ if args.inputs.mouse.click
+ args.gtk.write_file "last-mouse-click.txt", "Mouse was clicked at #{args.state.tick_count}."
+ end
+end
+</pre>
<h1 id='--docs---gtk--runtime#reset-'>DOCS: <code>GTK::Runtime#reset</code></h1>
<p>
This function will reset Kernel.tick_count to 0 and will remove all data from args.state.
@@ -1157,16 +1176,6 @@ This function returns the width and height of a string.
args.state.string_size_font_size ||= args.gtk.calcstringbox "Hello World"
end
</pre>
-<h1 id='--docs---gtk--runtime#write_file-'>DOCS: <code>GTK::Runtime#write_file</code></h1>
-<p>
-This function takes in two parameters. The first paramter is the file path and assumes the the game directory is the root. The second parameter is the string that will be written. The method overwrites whatever is currently in the file. Use <code>GTK::Runtime#append_file</code> to append to the file as opposed to overwriting.
-</p>
-<pre>def tick args
- if args.inputs.mouse.click
- args.gtk.write_file "last-mouse-click.txt", "Mouse was clicked at #{args.state.tick_count}."
- end
-end
-</pre>
<h1 id='--docs---array-'>DOCS: <code>Array</code></h1>
<p>
The Array class has been extend to provide methods that will help in common game development tasks. Array is one of the most powerful classes in Ruby and a very fundamental component of Game Toolkit.
@@ -1485,6 +1494,25 @@ You have to use <code>args.outputs.borders</code>:
args.outputs.borders << [100, 100, 160, 90]
end
</pre>
+<h1 id='--docs---gtk--outputs#screenshots-'>DOCS: <code>GTK::Outputs#screenshots</code></h1>
+<p>
+Add a hash to this collection to take a screenshot and save as png file. The keys of the hash can be provided in any order.
+</p>
+<pre>def tick args
+ args.outputs.screenshots << {
+ x: 0, y: 0, w: 100, h: 100, # Which portion of the screen should be captured
+ path: 'screenshot.png', # Output path of PNG file (inside game directory)
+ r: 255, g: 255, b: 255, a: 0 # Optional chroma key
+ }
+end
+</pre>
+<h2>Chroma key (Making a color transparent)</h2>
+<p>
+By specifying the r, g, b and a keys of the hash you change the transparency of a color in the resulting PNG file. This can be useful if you want to create files with transparent background like spritesheets. The transparency of the color specified by <code>r</code>, <code>g</code>, <code>b</code> will be set to the transparency specified by <code>a</code>.
+</p>
+<p>
+The example above sets the color white (255, 255, 255) as transparent.
+</p>
<h1 id='--docs---gtk--mouse-'>DOCS: <code>GTK::Mouse</code></h1>
<p>
The mouse is accessible via <code>args.inputs.mouse</code>:
@@ -2823,10 +2851,6 @@ def tick args
end
</pre>
-<h1 id='--learn-ruby-optional---intermediate-ruby-primer---repl.rb'>Learn Ruby Optional - Intermediate Ruby Primer - repl.rb</h1>
-<pre># ./samples/00_learn_ruby_optional/00_intermediate_ruby_primer/app/repl.rb
-
-</pre>
<h1 id='--rendering-basics---labels---main.rb'>Rendering Basics - Labels - main.rb</h1>
<pre># ./samples/01_rendering_basics/01_labels/app/main.rb
=begin
@@ -3298,6 +3322,530 @@ def tick_instructions args, text, y = 715
end
</pre>
+<h1 id='--rendering-basics---audio-mixer---main.rb'>Rendering Basics - Audio Mixer - main.rb</h1>
+<pre># ./samples/01_rendering_basics/06_audio_mixer/app/main.rb
+$gtk.reset
+
+$boxsize = 30
+
+def render_sources args
+ mouse_in_panel = (args.state.selected != 0) && args.inputs.mouse.position.inside_rect?([900, 450, 340, 250])
+ mouse_new_down = (args.state.mouse_held == 1)
+
+ if (mouse_new_down && !mouse_in_panel)
+ args.state.selected = 0 # will reset below if we hit something.
+ end
+
+ args.audio.keys.each { |k|
+ s = args.audio[k]
+
+ if (mouse_new_down) && !mouse_in_panel && args.inputs.mouse.position.inside_rect?([s[:screenx], s[:screeny], $boxsize, $boxsize])
+ args.state.selected = k
+ args.state.dragging_source = true
+ end
+
+ isselected = (k == args.state.selected)
+
+ if isselected && args.state.dragging_source
+ # you can hang anything on the audio hashes you want, so we store the
+ # actual screen position so it doesn't scale weirdly vs your mouse.
+ s[:screenx] = args.inputs.mouse.x - ($boxsize / 2)
+ s[:screeny] = args.inputs.mouse.y - ($boxsize / 2)
+
+ s[:screeny] = 50 if s[:screeny] < 50
+ s[:screeny] = (719 - $boxsize) if s[:screeny] > (719 - $boxsize)
+ s[:screenx] = 0 if s[:screenx] < 0
+ s[:screenx] = (1279 - $boxsize) if s[:screenx] > (1279 - $boxsize)
+
+ s[:x] = ((s[:screenx] / 1279.0) * 2.0) - 1.0 # scale to -1.0 - 1.0 range
+ s[:y] = ((s[:screeny] / 719.0) * 2.0) - 1.0 # scale to -1.0 - 1.0 range
+ end
+
+ color = isselected ? [ 0, 255, 0, 255 ] : [ 0, 0, 255, 255 ]
+ args.outputs.primitives << [s[:screenx], s[:screeny], $boxsize, $boxsize, *color].solid
+ }
+end
+
+def render_panel args
+ s = args.audio[args.state.selected]
+ return if s.nil?
+ mouse_down = (args.state.mouse_held > 0)
+
+ args.outputs.primitives << [900, 450, 340, 250, 127, 127, 200, 255].solid
+ args.outputs.primitives << [1075, 690, "Source ##{args.state.selected}", 3, 1, 255, 255, 255].label
+ args.outputs.primitives << [910, 660, 1230, 660, 255, 255, 255].line
+ args.outputs.primitives << [910, 650, "screen: (#{s[:screenx].to_i}, #{s[:screeny].to_i})", 0, 0, 255, 255, 255].label
+ args.outputs.primitives << [910, 625, "position: (#{s[:x].round(5).to_s[0..6]}, #{s[:y].round(5).to_s[0..6]})", 0, 0, 255, 255, 255].label
+
+ slider = [1022, 586, 200, 7]
+ if mouse_down && args.inputs.mouse.position.inside_rect?(slider)
+ s[:pitch] = ((args.inputs.mouse.x - slider[0]).to_f / (slider[2]-1.0)) * 2.0
+ end
+ slidercolor = (s[:pitch] / 2.0) * 255
+ args.outputs.primitives << [*slider, slidercolor, slidercolor, slidercolor, 255].solid
+ args.outputs.primitives << [910, 600, "pitch: #{s[:pitch].round(3).to_s[0..2]}", 0, 0, 255, 255, 255].label
+
+ slider = [1022, 561, 200, 7]
+ if mouse_down && args.inputs.mouse.position.inside_rect?(slider)
+ s[:gain] = (args.inputs.mouse.x - slider[0]).to_f / (slider[2]-1.0)
+ end
+ slidercolor = s[:gain] * 255
+ args.outputs.primitives << [*slider, slidercolor, slidercolor, slidercolor, 255].solid
+ args.outputs.primitives << [910, 575, "gain: #{s[:gain].round(3).to_s[0..2]}", 0, 0, 255, 255, 255].label
+
+ checkbox = [1022, 533, 10, 12]
+ if (args.state.mouse_held == 1) && args.inputs.mouse.position.inside_rect?(checkbox)
+ s[:looping] = !s[:looping]
+ end
+ checkboxcolor = s[:looping] ? 255 : 0
+ args.outputs.primitives << [*checkbox, checkboxcolor, checkboxcolor, checkboxcolor, 255].solid
+ args.outputs.primitives << [910, 550, "looping:", 0, 0, 255, 255, 255].label
+
+ checkbox = [1022, 508, 10, 12]
+ if (args.state.mouse_held == 1) && args.inputs.mouse.position.inside_rect?(checkbox)
+ s[:paused] = !s[:paused]
+ end
+ checkboxcolor = s[:paused] ? 255 : 0
+ args.outputs.primitives << [*checkbox, checkboxcolor, checkboxcolor, checkboxcolor, 255].solid
+ args.outputs.primitives << [910, 525, "paused:", 0, 0, 255, 255, 255].label
+
+ button = [910, 460, 320, 20]
+ if (args.state.mouse_held == 1) && args.inputs.mouse.position.inside_rect?(button)
+ args.audio.delete(args.state.selected)
+ args.state.selected = 0
+ end
+ args.outputs.primitives << [*button, 255, 0, 0, 255].solid
+ args.outputs.primitives << [button[0] + (button[2] / 2), button[1]+20, "DELETE SOURCE", 0, 1, 255, 255, 0].label
+end
+
+def spawn_new_sound args, num
+ input = nil
+ input = "sounds/#{num}.#{(num == 6) ? 'ogg' : 'wav'}"
+
+ # Spawn randomly in an area that won't be covered by UI.
+ screenx = (rand * 600.0) + 200.0
+ screeny = (rand * 400.0) + 100.0
+
+ args.state.next_sound_index += 1
+
+ # you can hang anything on the audio hashes you want, so we store the
+ # actual screen position in here for convenience.
+ args.audio[args.state.next_sound_index] = {
+ input: input,
+ screenx: screenx,
+ screeny: screeny,
+ x: ((screenx / 1279.0) * 2.0) - 1.0, # scale to -1.0 - 1.0 range
+ y: ((screeny / 719.0) * 2.0) - 1.0, # scale to -1.0 - 1.0 range
+ z: 0.0,
+ gain: 1.0,
+ pitch: 1.0,
+ looping: true,
+ paused: false
+ }
+
+ args.state.selected = args.state.next_sound_index
+end
+
+def render_launcher args
+ total = 6
+ x = (1280 - (total * $boxsize * 3)) / 2
+ y = 10
+ args.outputs.primitives << [0, 0, 1280, ((y*2) + $boxsize), 127, 127, 127, 255].solid
+ for i in 1..total
+ args.outputs.primitives << [x, y, $boxsize, $boxsize, 255, 255, 255, 255].solid
+ args.outputs.primitives << [x+8, y+28, i.to_s, 3, 0, 0, 0, 255, 255].label
+ if args.inputs.mouse.click && args.inputs.mouse.click.point.inside_rect?([x, y, $boxsize, $boxsize])
+ spawn_new_sound args, i
+ end
+ x = x + ($boxsize * 3)
+ end
+end
+
+def render_ui args
+ render_launcher args
+ render_panel args
+end
+
+def tick args
+ args.state.mouse_held ||= 0
+ args.state.dragging_source ||= false
+ args.state.selected ||= 0
+ args.state.next_sound_index ||= 0
+
+ if args.inputs.mouse.up
+ args.state.mouse_held = 0
+ args.state.dragging_source = false
+ elsif args.inputs.mouse.down || (args.state.mouse_held > 0)
+ args.state.mouse_held += 1
+ else
+ end
+
+ args.outputs.background_color = [ 0, 0, 0, 255 ]
+ render_sources args
+ render_ui args
+end
+
+</pre>
+<h1 id='--rendering-basics---sound-synthesis---main.rb'>Rendering Basics - Sound Synthesis - main.rb</h1>
+<pre># ./samples/01_rendering_basics/07_sound_synthesis/app/main.rb
+def tick args
+ defaults args
+ render args
+ input args
+ process_audio_queue args
+end
+
+def defaults args
+ args.state.sine_waves ||= {}
+ args.state.audio_queue ||= []
+ args.state.buttons ||= [
+ (frequency_buttons args),
+ (note_buttons args),
+ (bell_buttons args)
+ ].flatten
+end
+
+def frequency_buttons args
+ [
+ (button args,
+ row: 4.0, col: 0, text: "300hz",
+ frequency: 300,
+ method_to_call: :play_sine_wave),
+ (button args,
+ row: 5.0, col: 0, text: "400hz",
+ frequency: 400,
+ method_to_call: :play_sine_wave),
+ (button args,
+ row: 6.0, col: 0, text: "500hz",
+ frequency: 500,
+ method_to_call: :play_sine_wave),
+ ]
+end
+
+def play_sine_wave args, sender
+ queue_sine_wave args,
+ frequency: sender[:frequency],
+ duration: 1.seconds,
+ fade_out: true
+end
+
+
+def note_buttons args
+ [
+ (button args,
+ row: 1.5, col: 3, text: "C4",
+ note: :c, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 2.5, col: 3, text: "D4",
+ note: :d, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 3.5, col: 3, text: "E4",
+ note: :e, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 4.5, col: 3, text: "F4",
+ note: :f, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 5.5, col: 3, text: "G4",
+ note: :g, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 6.5, col: 3, text: "A5",
+ note: :a, octave: 5, method_to_call: :play_note),
+ (button args,
+ row: 7.5, col: 3, text: "B5",
+ note: :b, octave: 5, method_to_call: :play_note),
+ (button args,
+ row: 8.5, col: 3, text: "C5",
+ note: :c, octave: 5, method_to_call: :play_note),
+ ]
+end
+
+def play_note args, sender
+ queue_sine_wave args,
+ frequency: (frequency_for note: sender[:note],
+ octave: sender[:octave]),
+ duration: 1.seconds,
+ fade_out: true
+end
+
+def bell_buttons args
+ [
+ (button args,
+ row: 1.5, col: 6, text: "Bell C4",
+ note: :c, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 2.5, col: 6, text: "Bell D4",
+ note: :d, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 3.5, col: 6, text: "Bell E4",
+ note: :e, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 4.5, col: 6, text: "Bell F4",
+ note: :f, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 5.5, col: 6, text: "Bell G4",
+ note: :g, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 6.5, col: 6, text: "Bell A5",
+ note: :a, octave: 5, method_to_call: :play_bell),
+ (button args,
+ row: 7.5, col: 6, text: "Bell B5",
+ note: :b, octave: 5, method_to_call: :play_bell),
+ (button args,
+ row: 8.5, col: 6, text: "Bell C5",
+ note: :c, octave: 5, method_to_call: :play_bell),
+ ]
+end
+
+def play_bell args, sender
+ queue_bell args,
+ frequency: (frequency_for note: sender[:note],
+ octave: sender[:octave]),
+ duration: 2.seconds,
+ fade_out: true
+end
+
+def render args
+ args.outputs.borders << args.state.buttons.map { |b| b[:border] }
+ args.outputs.labels << args.state.buttons.map { |b| b[:label] }
+ args.outputs.labels << args.layout
+ .rect(row: 0,
+ col: 11.5)
+ .yield_self { |r| r.merge y: r.y + r.h }
+ .merge(text: "This is a Pro only feature. Click here to watch the YouTube video if you are on the Standard License.",
+ alignment_enum: 1)
+end
+
+def input args
+ args.state.buttons.each do |b|
+ if args.inputs.mouse.click.inside_rect? b[:rect]
+ parameter_string = (b.slice :frequency, :note, :octave).map { |k, v| "#{k}: #{v}" }.join ", "
+ args.gtk.notify! "#{b[:method_to_call]} #{parameter_string}"
+ send b[:method_to_call], args, b
+ end
+ end
+
+ if args.inputs.mouse.click.inside_rect? (args.layout.rect(row: 0).yield_self { |r| r.merge y: r.y + r.h.half, h: r.h.half })
+ args.gtk.openurl 'https://www.youtube.com/watch?v=zEzovM5jT-k&ab_channel=AmirRajan'
+ end
+end
+
+def process_audio_queue args
+ to_queue = args.state.audio_queue.find_all { |v| v[:queue_at] <= args.tick_count }
+ args.state.audio_queue -= to_queue
+
+ to_queue.each do |a|
+ args.audio[a[:id]] = a
+ end
+
+ args.audio.each do |k, v|
+ if v[:decay_rate]
+ v[:gain] -= v[:decay_rate]
+ end
+ end
+
+ sounds_to_stop = args.audio.find_all do |k, v|
+ v[:stop_at] && args.state.tick_count >= v[:stop_at]
+ end
+
+ sounds_to_stop.each do |(k, v)|
+ args.audio.delete k
+ end
+end
+
+def graph_sine_wave args, sine_wave, frequency
+ if args.state.tick_count != args.state.graphed_at
+ args.outputs.static_lines.clear
+ args.outputs.static_sprites.clear
+ end
+
+ r, g, b = frequency.to_i % 80, frequency.to_i % 128, frequency.to_i % 255
+ center_row = args.layout.rect(row: 5, col: 9)
+ x_scale = 20
+ y_scale = 100
+ max_points = 20
+
+ points = sine_wave
+ if sine_wave.length > max_points
+ resolution = sine_wave.length.idiv max_points
+ points = sine_wave.find_all
+ .with_index { |y, i| i % resolution == 0 }
+ end
+
+ args.outputs.static_lines << points.map_with_index do |y, x|
+ next_y = points[x + 1]
+
+ if next_y
+ {
+ x: center_row.x + (x * x_scale),
+ y: center_row.y + center_row.h.half + y_scale * y,
+ x2: center_row.x + ((x + 1) * x_scale),
+ y2: center_row.y + center_row.h.half + y_scale * next_y,
+ r: r,
+ g: g,
+ b: b
+ }
+ end
+ end
+
+ args.outputs.static_sprites << points.map_with_index do |y, x|
+ {
+ x: (center_row.x + (x * x_scale)) - 1,
+ y: (center_row.y + center_row.h.half + y_scale * y) - 1,
+ w: 2,
+ h: 2,
+ path: 'sprites/square-black.png'
+ }
+ end
+
+ args.state.graphed_at = args.state.tick_count
+end
+
+def defaults_period_sine_wave_for
+ { frequency: 440, sample_rate: 48000 }
+end
+
+def sine_wave_for opts = { }
+ opts = defaults_period_sine_wave_for.merge opts
+ frequency = opts[:frequency]
+ sample_rate = opts[:sample_rate]
+ period_size = (sample_rate.fdiv frequency).ceil
+ period_size.map_with_index do |i|
+ Math::sin((2.0 * Math::PI) / (sample_rate.to_f / frequency.to_f) * i)
+ end.to_a
+end
+
+def generate_audio_data sine_wave, sample_rate
+ sample_size = (sample_rate.fdiv (1000.fdiv 60)).ceil
+ copy_count = (sample_size.fdiv sine_wave.length).ceil
+ sine_wave * copy_count
+end
+
+def defaults_queue_sine_wave
+ { frequency: 440, duration: 60, gain: 1.0, fade_out: false, queue_in: 0 }
+end
+
+def queue_sine_wave args, opts = { }
+ opts = defaults_queue_sine_wave.merge opts
+ decay_rate = 0
+ decay_rate = 1.fdiv(opts[:duration]) * opts[:gain] if opts[:fade_out]
+ frequency = opts[:frequency]
+ sample_rate = 48000
+
+ audio_state = {
+ id: (new_id! args),
+ frequency: frequency,
+ sample_rate: 48000,
+ stop_at: args.tick_count + opts[:queue_in] + opts[:duration],
+ gain: opts[:gain].to_f,
+ queue_at: args.state.tick_count + opts[:queue_in],
+ decay_rate: decay_rate,
+ pitch: 1.0,
+ looping: true,
+ paused: false
+ }
+
+ sine_wave = sine_wave_for frequency: frequency, sample_rate: sample_rate
+ args.state.sine_waves[frequency] ||= sine_wave_for frequency: frequency, sample_rate: sample_rate
+
+ proc = lambda do
+ generate_audio_data args.state.sine_waves[frequency], sample_rate
+ end
+
+ audio_state[:input] = [1, sample_rate, proc]
+ graph_sine_wave args, sine_wave, frequency
+ args.state.audio_queue << audio_state
+end
+
+def defaults_queue_bell
+ { frequency: 440, duration: 1.seconds, queue_in: 0 }
+end
+
+def queue_bell args, opts = {}
+ (bell_to_sine_waves (defaults_queue_bell.merge opts)).each { |b| queue_sine_wave args, b }
+end
+
+def bell_harmonics
+ [
+ { frequency_ratio: 0.5, duration_ratio: 1.00 },
+ { frequency_ratio: 1.0, duration_ratio: 0.80 },
+ { frequency_ratio: 2.0, duration_ratio: 0.60 },
+ { frequency_ratio: 3.0, duration_ratio: 0.40 },
+ { frequency_ratio: 4.2, duration_ratio: 0.25 },
+ { frequency_ratio: 5.4, duration_ratio: 0.20 },
+ { frequency_ratio: 6.8, duration_ratio: 0.15 }
+ ]
+end
+
+def bell_to_sine_waves opts
+ bell_harmonics.map do |b|
+ {
+ frequency: opts[:frequency] * b[:frequency_ratio],
+ duration: opts[:duration] * b[:duration_ratio],
+ queue_in: opts[:queue_in],
+ gain: (1.fdiv bell_harmonics.length),
+ fade_out: true
+ }
+ end
+end
+
+def defaults_frequency_for
+ { note: :a, octave: 5, sharp: false, flat: false }
+end
+
+def frequency_for opts = {}
+ opts = defaults_frequency_for.merge opts
+ octave_offset_multiplier = opts[:octave] - 5
+ note = note_frequencies_octave_5[opts[:note]]
+ if octave_offset_multiplier < 0
+ note = note * 1 / (octave_offset_multiplier.abs + 1)
+ elsif octave_offset_multiplier > 0
+ note = note * (octave_offset_multiplier.abs + 1) / 1
+ end
+ note
+end
+
+def note_frequencies_octave_5
+ {
+ a: 440.0,
+ a_sharp: 466.16, b_flat: 466.16,
+ b: 493.88,
+ c: 523.25,
+ c_sharp: 554.37, d_flat: 587.33,
+ d: 587.33,
+ d_sharp: 622.25, e_flat: 659.25,
+ e: 659.25,
+ f: 698.25,
+ f_sharp: 739.99, g_flat: 739.99,
+ g: 783.99,
+ g_sharp: 830.61, a_flat: 830.61
+ }
+end
+
+def new_id! args
+ args.state.audio_id ||= 0
+ args.state.audio_id += 1
+end
+
+def button args, opts
+ button_def = opts.merge rect: (args.layout.rect (opts.merge w: 2, h: 1))
+
+ button_def[:border] = button_def[:rect].merge r: 0, g: 0, b: 0
+
+ font_size_enum = args.layout.font_relative_size_enum 0
+ label_offset_x = 4
+ label_offset_y = button_def[:rect].h.half + button_def[:rect].h.idiv(4)
+
+ button_def[:label] = button_def[:rect].merge text: opts[:text],
+ size_enum: font_size_enum,
+ x: button_def[:rect].x + label_offset_x,
+ y: button_def[:rect].y + label_offset_y
+
+ button_def
+end
+
+$gtk.reset
+
+</pre>
<h1 id='--input-basics---keyboard---main.rb'>Input Basics - Keyboard - main.rb</h1>
<pre># ./samples/02_input_basics/01_keyboard/app/main.rb
=begin
@@ -3888,6 +4436,52 @@ def tick_instructions args, text, y = 715
end
</pre>
+<h1 id='--input-basics---touch---main.rb'>Input Basics - Touch - main.rb</h1>
+<pre># ./samples/02_input_basics/06_touch/app/main.rb
+def tick args
+ args.outputs.background_color = [ 0, 0, 0 ]
+ args.outputs.primitives << [640, 700, "Touch your screen.", 5, 1, 255, 255, 255].label
+
+ # If you don't want to get fancy, you can just look for finger_one
+ # (and _two, if you like), which are assigned in the order new touches hit
+ # the screen. If not nil, they are touching right now, and are just
+ # references to specific items in the args.input.touch hash.
+ # If finger_one lifts off, it will become nil, but finger_two, if it was
+ # touching, remains until it also lifts off. When all fingers lift off, the
+ # the next new touch will be finger_one again, but until then, new touches
+ # don't fill in earlier slots.
+ if !args.inputs.finger_one.nil?
+ args.outputs.primitives << [640, 650, "Finger #1 is touching at (#{args.inputs.finger_one.x}, #{args.inputs.finger_one.y}).", 5, 1, 255, 255, 255].label
+ end
+ if !args.inputs.finger_two.nil?
+ args.outputs.primitives << [640, 600, "Finger #2 is touching at (#{args.inputs.finger_two.x}, #{args.inputs.finger_two.y}).", 5, 1, 255, 255, 255].label
+ end
+
+ # Here's the more flexible interface: this will report as many simultaneous
+ # touches as the system can handle, but it's a little more effort to track
+ # them. Each item in the args.input.touch hash has a unique key (an
+ # incrementing integer) that exists until the finger lifts off. You can
+ # tell which order the touches happened globally by the key value, or
+ # by the touch[id].touch_order field, which resets to zero each time all
+ # touches have lifted.
+
+ args.state.colors ||= [
+ 0xFF0000, 0x00FF00, 0x1010FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF
+ ]
+
+ size = 100
+ args.inputs.touch.each { |k,v|
+ color = args.state.colors[v.touch_order % 7]
+ r = (color & 0xFF0000) >> 16
+ g = (color & 0x00FF00) >> 8
+ b = (color & 0x0000FF)
+ args.outputs.primitives << [v.x - (size / 2), v.y + (size / 2), size, size, r, g, b, 255].solid
+ args.outputs.primitives << [v.x, v.y + size, k.to_s, 0, 1, 0, 0, 0].label
+ }
+end
+
+
+</pre>
<h1 id='--rendering-sprites---animation-using-separate-pngs---main.rb'>Rendering Sprites - Animation Using Separate Pngs - main.rb</h1>
<pre># ./samples/03_rendering_sprites/01_animation_using_separate_pngs/app/main.rb
=begin
@@ -8395,6 +8989,51 @@ def tick args
end
</pre>
+<h1 id='--advanced-rendering---pixel-arrays---main.rb'>Advanced Rendering - Pixel Arrays - main.rb</h1>
+<pre># ./samples/07_advanced_rendering/06_pixel_arrays/app/main.rb
+$gtk.reset
+
+def tick args
+ args.state.posinc ||= 1
+ args.state.pos ||= 0
+ args.state.rotation ||= 0
+
+ dimension = 10 # keep it small and let the GPU scale it when rendering the sprite.
+
+ # Set up our "scanner" pixel array and fill it with black pixels.
+ args.pixel_array(:scanner).width = dimension
+ args.pixel_array(:scanner).height = dimension
+ args.pixel_array(:scanner).pixels.fill(0xFF000000, 0, dimension * dimension) # black, full alpha
+
+ # Draw a green line that bounces up and down the sprite.
+ args.pixel_array(:scanner).pixels.fill(0xFF00FF00, dimension * args.state.pos, dimension) # green, full alpha
+
+ # Adjust position for next frame.
+ args.state.pos += args.state.posinc
+ if args.state.posinc > 0 && args.state.pos >= dimension
+ args.state.posinc = -1
+ args.state.pos = dimension - 1
+ elsif args.state.posinc < 0 && args.state.pos < 0
+ args.state.posinc = 1
+ args.state.pos = 1
+ end
+
+ # New/changed pixel arrays get uploaded to the GPU before we render
+ # anything. At that point, they can be scaled, rotated, and otherwise
+ # used like any other sprite.
+ w = 100
+ h = 100
+ x = (1280 - w) / 2
+ y = (720 - h) / 2
+ args.outputs.background_color = [64, 0, 128]
+ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite
+ args.state.rotation += 1
+
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+end
+
+
+</pre>
<h1 id='--tweening-lerping-easing-functions---easing-functions---main.rb'>Tweening Lerping Easing Functions - Easing Functions - main.rb</h1>
<pre># ./samples/08_tweening_lerping_easing_functions/01_easing_functions/app/main.rb
def tick args
@@ -9609,12 +10248,12 @@ def test_serialize args, assert
GTK::Entity.__reset_id__!
args.state.player_one = "test"
result = args.gtk.serialize_state args.state
- assert.equal! result, "{:entity_id=>3, :tick_count=>-1, :player_one=>\"test\"}"
+ assert.equal! result, "{:entity_id=>3, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>\"test\"}"
GTK::Entity.__reset_id__!
args.gtk.write_file 'state.txt', ''
result = args.gtk.serialize_state 'state.txt', args.state
- assert.equal! result, "{:entity_id=>3, :tick_count=>-1, :player_one=>\"test\"}"
+ assert.equal! result, "{:entity_id=>3, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>\"test\"}"
end
def test_deserialize args, assert
@@ -9645,8 +10284,9 @@ def test_strict_entity_serialization args, assert
args.state.player_two = args.state.new_entity_strict(:player_strict, name: "Ken")
serialized_state = args.gtk.serialize_state args.state
- assert.equal! serialized_state, '{:entity_id=>1, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>3, :entity_name=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :name=>"Ken"}}'
+ assert.equal! serialized_state, '{:entity_id=>1, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_keys_by_ref=>{}, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>3, :entity_name=>:player_strict, :entity_type=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :entity_keys_by_ref=>{:entity_type=>:entity_name, :global_created_at_elapsed=>:created_at}, :name=>"Ken"}}'
+ GTK::Entity.__reset_id__!
deserialize_state = args.gtk.deserialize_state serialized_state
assert.equal! args.state.player_one.name, deserialize_state.player_one.name
@@ -9662,8 +10302,9 @@ def test_strict_entity_serialization_with_nil args, assert
args.state.player_two = args.state.new_entity_strict(:player_strict, name: "Ken", blood_type: nil)
serialized_state = args.gtk.serialize_state args.state
- assert.equal! serialized_state, '{:entity_id=>3, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>3, :entity_name=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :name=>"Ken", :blood_type=>nil}}'
+ assert.equal! serialized_state, '{:entity_id=>9, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_keys_by_ref=>{}, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>2, :entity_name=>:player_strict, :entity_type=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :entity_keys_by_ref=>{:entity_type=>:entity_name, :global_created_at_elapsed=>:created_at}, :name=>"Ken", :blood_type=>nil}}'
+ GTK::Entity.__reset_id__!
deserialized_state = args.gtk.deserialize_state serialized_state
assert.equal! args.state.player_one.name, deserialized_state.player_one.name
@@ -9684,12 +10325,41 @@ def test_multiple_strict_entities args, assert
args.state.enemy = args.state.new_entity_strict(:enemy, name: "Bison", other_property: 'extra mean')
serialized_state = args.gtk.serialize_state args.state
+
+ GTK::Entity.__reset_id__!
deserialized_state = args.gtk.deserialize_state serialized_state
assert.equal! deserialized_state.player.name, "Ryu"
assert.equal! deserialized_state.enemy.other_property, "extra mean"
end
+def test_by_reference_state args, assert
+ GTK::Entity.__reset_id__!
+ args.state.a = { name: "Jane Doe" }
+ args.state.b = args.state.a
+ assert.equal! args.state.a.object_id, args.state.b.object_id
+ serialized_state = args.gtk.serialize_state args.state
+
+ GTK::Entity.__reset_id__!
+ deserialized_state = args.gtk.deserialize_state serialized_state
+ assert.equal! deserialized_state.a.object_id, deserialized_state.b.object_id
+end
+
+def test_by_reference_state_strict_entities args, assert
+ GTK::Entity.__reset_id__!
+ args.state.a = { name: "Jane Doe" }
+ args.state.strict_entity = args.state.new_entity_strict(:couple) do |e|
+ e.one = args.state.new_entity_strict(:person, name: "Jane")
+ e.two = e.one
+ end
+ assert.equal! args.state.strict_entity.one, args.state.strict_entity.two
+ serialized_state = args.gtk.serialize_state args.state
+
+ GTK::Entity.__reset_id__!
+ deserialized_state = args.gtk.deserialize_state serialized_state
+ assert.equal! deserialized_state.strict_entity.one, deserialized_state.strict_entity.two
+end
+
$tests.start
</pre>
@@ -9875,6 +10545,55 @@ end
</pre>
+<h1 id='--12-c-extensions---intermediate---main.rb'>12 C Extensions - Intermediate - main.rb</h1>
+<pre># ./samples/12_c_extensions/02_intermediate/app/main.rb
+$gtk.ffi_misc.gtk_dlopen("ext")
+include FFI::RE
+
+def split_words(input)
+ words = []
+ last = IntPointer.new
+ re = re_compile("\\w+")
+ first = re_matchp(re, input, last)
+ while first != -1
+ words << input.slice(first, last.value)
+ input = input.slice(last.value + first, input.length)
+ first = re_matchp(re, input, last)
+ end
+ words
+end
+
+def tick args
+ args.outputs.labels << [640, 500, split_words("hello, dragonriders!").join(' '), 5, 1]
+end
+
+</pre>
+<h1 id='--12-c-extensions---native-pixel-arrays---main.rb'>12 C Extensions - Native Pixel Arrays - main.rb</h1>
+<pre># ./samples/12_c_extensions/03_native_pixel_arrays/app/main.rb
+$gtk.ffi_misc.gtk_dlopen("ext")
+include FFI::CExt
+
+def tick args
+ args.state.rotation ||= 0
+
+ update_scanner_texture # this calls into a C extension!
+
+ # New/changed pixel arrays get uploaded to the GPU before we render
+ # anything. At that point, they can be scaled, rotated, and otherwise
+ # used like any other sprite.
+ w = 100
+ h = 100
+ x = (1280 - w) / 2
+ y = (720 - h) / 2
+ args.outputs.background_color = [64, 0, 128]
+ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite
+ args.state.rotation += 1
+
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+end
+
+
+</pre>
<h1 id='--3d---3d-cube---main.rb'>3d - 3d Cube - main.rb</h1>
<pre># ./samples/99_genre_3d/3d_cube/app/main.rb
STARTX = 0.0
@@ -15520,27 +16239,6 @@ def tick args
end
</pre>
-<h1 id='--platformer---gorillas-basic---repl.rb'>Platformer - Gorillas Basic - repl.rb</h1>
-<pre># ./samples/99_genre_platformer/gorillas_basic/app/repl.rb
-begin
- if $gtk.args.state.current_turn == :player_1_angle
- $gtk.args.state.player_1_angle = "#{60 + 10.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- $gtk.args.state.player_1_velocity = "#{30 + 20.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- elsif $gtk.args.state.current_turn == :player_2_angle
- $gtk.args.state.player_2_angle = "#{60 + 10.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- $gtk.args.state.player_2_velocity = "#{30 + 20.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- else
- $you_so_basic_gorillas.input_execute_turn
- end
-rescue Exception => e
- puts e
-end
-
-</pre>
<h1 id='--platformer---gorillas-basic---tests.rb'>Platformer - Gorillas Basic - tests.rb</h1>
<pre># ./samples/99_genre_platformer/gorillas_basic/app/tests.rb
$gtk.reset 100
@@ -18930,11 +19628,6 @@ def player_xs args, x, y
end
</pre>
-<h1 id='--rpg-narrative---return-of-serenity---repl.rb'>Rpg Narrative - Return Of Serenity - repl.rb</h1>
-<pre># ./samples/99_genre_rpg_narrative/return_of_serenity/app/repl.rb
-puts $gtk.args.state.current_scene
-
-</pre>
<h1 id='--rpg-narrative---return-of-serenity---require.rb'>Rpg Narrative - Return Of Serenity - require.rb</h1>
<pre># ./samples/99_genre_rpg_narrative/return_of_serenity/app/require.rb
require 'app/lowrez_simulator.rb'
@@ -21693,6 +22386,11 @@ module GTK
# @return [Outputs]
attr_accessor :outputs
+ # Contains the means to interact with the audio mixer.
+ #
+ # @return [Hash]
+ attr_accessor :audio
+
# Contains display size information to assist in positioning things on the screen.
#
# @return [Grid]
@@ -21723,9 +22421,12 @@ module GTK
attr_accessor :wizards
+ attr_accessor :layout
+
def initialize runtime, recording
@inputs = Inputs.new
@outputs = Outputs.new args: self
+ @audio = {}
@passes = []
@state = OpenEntity.new
@state.tick_count = -1
@@ -21733,9 +22434,11 @@ module GTK
@recording = recording
@grid = Grid.new runtime
@render_targets = {}
+ @pixel_arrays = {}
@all_tests = []
@geometry = GTK::Geometry
@wizards = Wizards.new
+ @layout = GTK::Layout.new @grid.w, @grid.h
end
@@ -21764,6 +22467,26 @@ module GTK
[grid, inputs, state, outputs, runtime, passes]
end
+ def clear_pixel_arrays
+ pixel_arrays_clear
+ end
+
+ def pixel_arrays_clear
+ @pixel_arrays = {}
+ end
+
+ def pixel_arrays
+ @pixel_arrays
+ end
+
+ def pixel_array name
+ name = name.to_s
+ if !@pixel_arrays[name]
+ @pixel_arrays[name] = PixelArray.new
+ end
+ @pixel_arrays[name]
+ end
+
def clear_render_targets
render_targets_clear
end
@@ -21970,7 +22693,7 @@ end
@assertion_performed = true
if actual != expected
actual_string = "#{actual}#{actual.nil? ? " (nil) " : " " }".strip
- message = "actual:\n#{actual_string} did not equal\nexpected:\n#{expected}.\n#{message}"
+ message = "actual:\n#{actual_string}\n\ndid not equal\n\nexpected:\n#{expected}.\n#{message}"
raise message
end
nil
@@ -22039,6 +22762,10 @@ module AttrGTK
args.passes
end
+ def pixel_arrays
+ args.pixel_arrays
+ end
+
def geometry
args.geometry
end
@@ -22116,6 +22843,8 @@ end
module GTK
class Console
+ include ConsoleDeprecated
+
attr_accessor :show_reason, :log, :logo, :background_color,
:text_color, :animation_duration,
:max_log_lines, :max_history, :log,
@@ -22186,7 +22915,7 @@ module GTK
@disabled = false
end
- def addsprite obj
+ def add_sprite obj
@log_invocation_count += 1
obj[:id] ||= "id_#{obj[:path]}_#{Time.now.to_i}".to_sym
@@ -22206,14 +22935,14 @@ module GTK
def add_primitive obj
if obj.is_a? Hash
- addsprite obj
+ add_sprite obj
else
- addtext obj
+ add_text obj
end
nil
end
- def addtext obj
+ def add_text obj
@last_log_lines_count ||= 1
@log_invocation_count += 1
@@ -22337,12 +23066,12 @@ S
@toasted_at = Kernel.global_tick_count
log_once_info :perma_toast_tip, "Use console.perma_toast to show the toast for longer."
dwim_duration = 5.seconds
- addtext "* toast :#{id}"
+ add_text "* toast :#{id}"
puts "* TOAST: :#{id}"
messages.each do |message|
lines = message.to_s.wrapped_lines(self.console_text_width)
dwim_duration += lines.length.seconds
- addtext "** #{message}"
+ add_text "** #{message}"
puts "** #{message}"
end
show :toast
@@ -22560,6 +23289,10 @@ S
@command_history_index -= 1
self.current_input_str = @command_history[@command_history_index].dup
end
+ elsif args.inputs.keyboard.key_down.left
+ prompt.move_cursor_left
+ elsif args.inputs.keyboard.key_down.right
+ prompt.move_cursor_right
elsif inputs_scroll_up_full? args
scroll_up_full
elsif inputs_scroll_down_full? args
@@ -23119,23 +23852,53 @@ module GTK
@cursor_color = Color.new [187, 21, 6]
@console_text_width = console_text_width
+ @cursor_position = 0
+ update_cursor_position_px
+
@last_autocomplete_prefix = nil
@next_candidate_index = 0
end
+ def update_cursor_position_px
+ @cursor_position_px = ($gtk.calcstringbox (@prompt + @current_input_str[0...@cursor_position]), @font_style.size_enum, @font_style.font).x
+ end
+
+ def current_input_str=(str)
+ @current_input_str = str
+ @cursor_position = str.length
+ end
+
def <<(str)
- @current_input_str << str
+ @current_input_str = @current_input_str[0...@cursor_position] + str + @current_input_str[@cursor_position..-1]
+ @cursor_position += str.length
+ update_cursor_position_px
@current_input_changed_at = Kernel.global_tick_count
reset_autocomplete
end
def backspace
- @current_input_str.chop!
+ return if current_input_str.length.zero? || @cursor_position.zero?
+
+ @current_input_str = @current_input_str[0...(@cursor_position - 1)] + @current_input_str[@cursor_position..-1]
+ @cursor_position -= 1
+ update_cursor_position_px
reset_autocomplete
end
+ def move_cursor_left
+ @cursor_position -= 1 if @cursor_position > 0
+ update_cursor_position_px
+ end
+
+ def move_cursor_right
+ @cursor_position += 1 if @cursor_position < current_input_str.length
+ update_cursor_position_px
+ end
+
def clear
@current_input_str = ''
+ @cursor_position = 0
+ update_cursor_position_px
reset_autocomplete
end
@@ -23154,7 +23917,10 @@ module GTK
@next_candidate_index += 1
@next_candidate_index = 0 if @next_candidate_index >= candidates.length
self.current_input_str = display_autocomplete_candidate(candidate)
+ update_cursor_position_px
end
+ rescue Exception => e
+ puts "* BUG: Tab autocompletion failed. Let us know about this.\n#{e}"
end
def pretty_print_strings_as_table items
@@ -23213,7 +23979,21 @@ S
def render(args, x:, y:)
args.outputs.reserved << font_style.label(x: x, y: y, text: "#{@prompt}#{current_input_str}", color: @text_color)
- args.outputs.reserved << font_style.label(x: x - 2, y: y + 3, text: (" " * (@prompt.length + current_input_str.length)) + "|", color: @cursor_color)
+ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 0.5,
+ y: y + 5,
+ x2: x + @cursor_position_px + 0.5,
+ y2: y + @font_style.letter_size.y + 5)
+
+ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 1,
+ y: y + 5,
+ x2: x + @cursor_position_px + 1,
+ y2: y + @font_style.letter_size.y + 5)
+
+ # debugging rectangle for string
+ # args.outputs.reserved << (@cursor_color.to_h.merge x: x,
+ # y: y + 5,
+ # w: @cursor_position_px,
+ # h: @font_style.letter_size.y).border
end
def tick
@@ -25160,6 +25940,59 @@ module GTK
alias_method :inspect, :to_s
end
+
+ # Provides access to multitouch input
+ #
+ # @gtk
+ class FingerTouch
+
+ # @gtk
+ attr_accessor :moved,
+ :moved_at,
+ :global_moved_at,
+ :touch_order,
+ :x, :y
+
+ def initialize
+ @moved = false
+ @moved_at = 0
+ @global_moved_at = 0
+ @touch_order = 0
+ @x = 0
+ @y = 0
+ end
+
+ def point
+ [@x, @y].point
+ end
+
+ def inside_rect? rect
+ point.inside_rect? rect
+ end
+
+ def inside_circle? center, radius
+ point.point_inside_circle? center, radius
+ end
+
+ alias_method :position, :point
+
+ def serialize
+ result = {}
+ result[:x] = @x
+ result[:y] = @y
+ result[:touch_order] = @touch_order
+ result[:moved] = @moved
+ result[:moved_at] = @moved_at
+
+ result
+ end
+
+ def to_s
+ serialize.to_s
+ end
+
+ alias_method :inspect, :to_s
+ end
end
module GTK
@@ -25180,6 +26013,11 @@ module GTK
# @gtk
attr_reader :mouse
+ # @return {FingerTouch}
+ # @gtk
+ attr_reader :touch
+ attr_accessor :finger_one, :finger_two
+
# @gtk
attr_accessor :text, :history
@@ -25187,6 +26025,9 @@ module GTK
@controllers = [Controller.new, Controller.new]
@keyboard = Keyboard.new
@mouse = Mouse.new
+ @touch = {}
+ @finger_one = nil
+ @finger_two = nil
@text = []
end
@@ -25262,6 +26103,9 @@ module GTK
@mouse.clear
@keyboard.clear
@controllers.each(&:clear)
+ @touch.clear
+ @finger_one = nil
+ @finger_two = nil
end
# @return [Hash]
@@ -25278,6 +26122,1382 @@ module GTK
end
</pre>
+<h1 id='--ios_wizard.rb'>ios_wizard.rb</h1>
+<pre># ./dragon/ios_wizard.rb
+# Copyright 2019 DragonRuby LLC
+# MIT License
+# ios_wizard.rb has been released under MIT (*only this file*).
+
+class WizardException < Exception
+ attr_accessor :console_primitives
+
+ def initialize *console_primitives
+ @console_primitives = console_primitives
+ end
+end
+
+class IOSWizard
+ def initialize
+ @doctor_executed_at = 0
+ end
+
+ def relative_path
+ (File.dirname $gtk.binary_path)
+ end
+
+ def steps
+ [
+ :check_for_xcode,
+ :check_for_brew,
+ :check_for_certs,
+ :check_for_device,
+ :check_for_dev_profile,
+ :determine_app_name,
+ :determine_app_id,
+ :blow_away_temp,
+ :stage_app,
+ :write_info_plist,
+ :write_entitlements_plist,
+ :code_sign,
+ :create_ipa,
+ :deploy,
+ ]
+ end
+
+ def get_reserved_sprite png
+ sprite_path = ".dragonruby/sprites/wizards/ios/#{png}"
+
+ if !$gtk.ivar :rcb_release_mode
+ sprite_path = "deploy_template/#{sprite_path}"
+ $gtk.reset_sprite sprite_path
+ end
+
+ if !$gtk.read_file sprite_path
+ log_error "png #{png} not found."
+ end
+
+ sprite_path
+ end
+
+ def start
+ @certificate_name = nil
+ init_wizard_status
+ log_info "Starting iOS Wizard so we can deploy to your device."
+ @start_at = Kernel.global_tick_count
+ steps.each do |m|
+ begin
+ result = (send m) || :success if @wizard_status[m][:result] != :success
+ @wizard_status[m][:result] = result
+ rescue Exception => e
+ if e.is_a? WizardException
+ $console.log.clear
+ $console.archived_log.clear
+ log "=" * $console.console_text_width
+ e.console_primitives.each do |p|
+ $console.add_primitive p
+ end
+ log "=" * $console.console_text_width
+ else
+ log_error "Step #{m} failed."
+ log_error e.to_s
+ end
+
+ $console.set_command "$wizards.ios.start"
+
+ break
+ end
+ end
+
+ return nil
+ end
+
+ def always_fail
+ return false if $gtk.ivar :rcb_release_mode
+ return true
+ end
+
+ def check_for_xcode
+ if !cli_app_exist?(xcodebuild_cli_app)
+ raise WizardException.new(
+ "* You need Xcode to use $wizards.ios.start.",
+ { w: 75, h: 75, path: get_reserved_sprite("xcode.png") },
+ "** 1. Go to http://developer.apple.com and register.",
+ "** 2. Download Xcode 11.3+ from http://developer.apple.com/downloads.",
+ " NOTE: DO NOT install Xcode from the App Store. Use the link above.",
+ { w: 700, h: 359, path: get_reserved_sprite("xcode-downloads.png") },
+ "** 3. After installing. Open up Xcode to accept the EULA."
+ )
+ end
+ end
+
+ def check_for_brew
+ if !cli_app_exist?('brew')
+ raise WizardException.new(
+ "* You need to install Brew.",
+ { w: 700, h: 388, path: get_reserved_sprite("brew.png") },
+ "** 1. Go to http://brew.sh.",
+ "** 2. Copy the command that starts with `/bin/bash -c` on the site.",
+ "** 3. Open Terminal and run the command you copied from the website.",
+ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },
+ )
+ end
+ end
+
+ def init_wizard_status
+ @wizard_status = {}
+ steps.each do |m|
+ @wizard_status[m] = { result: :not_started }
+ end
+
+ previous_step = nil
+ next_step = nil
+ steps.each_cons(2) do |current_step, next_step|
+ @wizard_status[current_step][:next_step] = next_step
+ end
+
+ steps.reverse.each_cons(2) do |current_step, previous_step|
+ @wizard_status[current_step][:previous_step] = previous_step
+ end
+ end
+
+ def restart
+ init_wizard_status
+ start
+ end
+
+ def check_for_dev_profile
+ if !($gtk.read_file 'profiles/development.mobileprovision')
+ $gtk.system "mkdir -p #{relative_path}/profiles"
+ $gtk.system "open #{relative_path}/profiles"
+ $gtk.system "echo Download the mobile provisioning profile and place it here with the name development.mobileprovision > #{relative_path}/profiles/README.txt"
+ raise WizardException.new(
+ "* I didn't find a mobile provision.",
+ "** 1. Go to http://developer.apple.com and click \"Certificates, IDs & Profiles\".",
+ "** 2. Add an App Identifier.",
+ "** 3. Select the App IDs option from the list.",
+ { w: 700, h: 75, path: get_reserved_sprite("identifiers.png") },
+ "** 4. Add your Device next. You can use idevice_id -l to get the UUID of your device.",
+ { w: 365, h: 69, path: get_reserved_sprite("device-link.png") },
+ "** 5. Create a Profile. Associate your certs, id, and device.",
+ { w: 300, h: 122, path: get_reserved_sprite("profiles.png") },
+ "** 6. Download the mobile provision and save it to 'profiles/development.mobileprovision'.",
+ { w: 200, h: 124, path: get_reserved_sprite("profiles-folder.png") },
+ )
+ end
+ end
+
+ def determine_app_name
+ @app_name = dev_profile_xml[:children].first[:children].first[:children][1][:children].first[:data]
+ log_info "App name is: #{@app_name}."
+ end
+
+ def dev_profile_xml
+ xml = $gtk.read_file 'profiles/development.mobileprovision'
+ scrubbed = xml.each_line.map do |l|
+ if l.strip.start_with? "<"
+ if l.start_with? '</plist>'
+ '</plist>'
+ elsif l.include? "Apple Inc."
+ nil
+ elsif l.include? '<data>'
+ nil
+ else
+ l
+ end
+ else
+ nil
+ end
+ end.reject { |l| !l }.join
+ $gtk.parse_xml scrubbed
+ end
+
+ def determine_app_id
+ # lol
+ @app_id = dev_profile_xml[:children].first[:children].first[:children][13][:children][1][:children].first[:data]
+ log_info "App Identifier is set to : #{@app_id}"
+ end
+
+ def set_app_name name
+ @app_name = name
+ start
+ end
+
+ def set_dev_profile path
+ if !$gtk.read_file path
+ log_error "I couldn't find a development profile at #{path}."
+ ask_for_dev_profile
+ else
+ @dev_profile_path = path
+ start
+ end
+ end
+
+ def blow_away_temp
+ sh "rm -rf #{tmp_directory}"
+ end
+
+ def stage_app
+ log_info "Staging."
+ sh "mkdir -p #{tmp_directory}"
+ sh "cp -R #{relative_path}/dragonruby-ios.app \"#{tmp_directory}/#{@app_name}.app\""
+ end
+
+ def set_app_id id
+ log_info = "App Id set to: #{id}"
+ @app_id = id
+ start
+ end
+
+ def check_for_device
+ log_info "Looking for device."
+
+ if !cli_app_exist?(idevice_id_cli_app)
+ raise WizardException.new(
+ "* It doesn't look like you have the libimobiledevice iOS protocol library installed.",
+ "** 1. Open Terminal.",
+ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },
+ "** 2. Run: `brew install libimobiledevice`.",
+ { w: 500, h: 93, path: get_reserved_sprite("brew-install-libimobiledevice.png") },
+ )
+ end
+
+ if connected_devices.length == 0
+ raise WizardException.new("* I couldn't find any connected devices. Connect your iOS device to your Mac and try again.")
+ end
+
+ @device_id = connected_devices.first
+ log_info "I will be using device with UUID #{@device_id}"
+ end
+
+ def check_for_certs
+ log_info "Attempting to find certificates on your computer."
+
+ if !cli_app_exist?(security_cli_app)
+ raise WizardException.new(
+ "* It doesn't look like you have #{security_cli_app}.",
+ "** 1. Open Disk Utility and run First Aid.",
+ { w: 700, h: 148, path: get_reserved_sprite("disk-utility.png") },
+ )
+ end
+
+ if valid_certs.length == 0
+ raise WizardException.new(
+ "* It doesn't look like you have any valid certs installed.",
+ "** 1. Open Xcode.",
+ "** 2. Log into your developer account. Xcode -> Preferences -> Accounts.",
+ { w: 700, h: 98, path: get_reserved_sprite("login-xcode.png") },
+ "** 3. After loggin in, select Manage Certificates...",
+ { w: 700, h: 115, path: get_reserved_sprite("manage-certificates.png") },
+ "** 4. Add a certificate for Apple Development.",
+ { w: 700, h: 217, path: get_reserved_sprite("add-cert.png") },
+ )
+ raise "You do not have any Apple development certs on this computer."
+ end
+
+ @certificate_name = valid_certs.first[:name]
+ log_info "I will be using '#{@certificate_name}' to deploy to your device."
+ end
+
+ def idevice_id_cli_app
+ "idevice_id"
+ end
+
+ def security_cli_app
+ "/usr/bin/security"
+ end
+
+ def xcodebuild_cli_app
+ "xcodebuild"
+ end
+
+ def valid_certs
+ certs = sh("#{security_cli_app} -q find-identity -p codesigning -v").each_line.map do |l|
+ if l.include?(")") && !l.include?("Developer ID") && l.include?("Development")
+ l.strip
+ else
+ nil
+ end
+ end.reject_nil.map do |l|
+ number, id, name = l.split(' ', 3)
+ name = name.gsub("\"", "") if name
+ {
+ number: 1,
+ id: id,
+ name: name
+ }
+ end
+ end
+
+ def connected_devices
+ sh("idevice_id -l").strip.each_line.map do |l|
+ l.strip
+ end.reject { |l| l.length == 0 }
+ end
+
+ def cli_app_exist? app
+ `which #{app}`.strip.length != 0
+ end
+
+ def write_entitlements_plist
+ entitlement_plist_string = <<-XML
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>application-identifier</key>
+ <string>:app_id</string>
+ <key>get-task-allow</key>
+ <true/>
+ </dict>
+</plist>
+XML
+
+ log_info "Creating Entitlements.plist"
+
+ $gtk.write_file_root "tmp/ios/Entitlements.plist", entitlement_plist_string.gsub(":app_id", @app_id).strip
+
+ sh "/usr/bin/plutil -convert binary1 \"#{tmp_directory}/Entitlements.plist\""
+ sh "/usr/bin/plutil -convert xml1 \"#{tmp_directory}/Entitlements.plist\""
+
+ @entitlement_plist_written = true
+ end
+
+ def code_sign
+ sh "cp #{@dev_profile_path} \"#{app_path}/embedded.mobileprovision\""
+
+ log_info "Signing app with #{@certificate_name}."
+
+ sh "/usr/bin/plutil -convert binary1 \"#{app_path}/Info.plist\""
+
+ sh "CODESIGN_ALLOCATE=\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate\" /usr/bin/codesign -f -s \"#{@certificate_name}\" --entitlements #{tmp_directory}/Entitlements.plist \"#{tmp_directory}/#{@app_name}.app\""
+
+ @code_sign_completed = true
+ end
+
+ def write_info_plist
+ log_info "Adding Info.plist."
+
+ info_plist_string = <<-XML
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ <key>NSExceptionDomains</key>
+ <dict>
+ <key>google.com</key>
+ <dict>
+ <key>NSExceptionAllowsInsecureHTTPLoads</key>
+ <true/>
+ <key>NSIncludesSubdomains</key>
+ <true/>
+ </dict>
+ </dict>
+ </dict>
+ <key>BuildMachineOSBuild</key>
+ <string>19C57</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>:app_name</string>
+ <key>CFBundleExecutable</key>
+ <string>Runtime</string>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>AppIcon60x60</string>
+ </array>
+ <key>CFBundleIcons</key>
+ <dict>
+ <key>CFBundlePrimaryIcon</key>
+ <dict>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>AppIcon60x60</string>
+ </array>
+ <key>CFBundleIconName</key>
+ <string>AppIcon</string>
+ </dict>
+ </dict>
+ <key>CFBundleIcons~ipad</key>
+ <dict>
+ <key>CFBundlePrimaryIcon</key>
+ <dict>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>AppIcon60x60</string>
+ <string>AppIcon76x76</string>
+ </array>
+ <key>CFBundleIconName</key>
+ <string>AppIcon</string>
+ </dict>
+ </dict>
+ <key>CFBundleIdentifier</key>
+ <string>com.carlile.swisscheese</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>:app_name</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleSupportedPlatforms</key>
+ <array>
+ <string>iPhoneOS</string>
+ </array>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>DTCompiler</key>
+ <string>com.apple.compilers.llvm.clang.1_0</string>
+ <key>DTPlatformBuild</key>
+ <string>17B102</string>
+ <key>DTPlatformName</key>
+ <string>iphoneos</string>
+ <key>DTPlatformVersion</key>
+ <string>13.2</string>
+ <key>DTSDKBuild</key>
+ <string>17B102</string>
+ <key>DTSDKName</key>
+ <string>iphoneos13.2</string>
+ <key>DTXcode</key>
+ <string>01131</string>
+ <key>DTXcodeBuild</key>
+ <string>11C505</string>
+ <key>ITSAppUsesNonExemptEncryption</key>
+ <false/>
+ <key>MinimumOSVersion</key>
+ <string>11.0</string>
+ <key>UIAppFonts</key>
+ <array/>
+ <key>UIBackgroundModes</key>
+ <array/>
+ <key>UIDeviceFamily</key>
+ <array>
+ <integer>1</integer>
+ <integer>2</integer>
+ </array>
+ <key>UILaunchImages</key>
+ <array>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>11.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-1100-Portrait-2436h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{375, 812}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>8.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-800-Portrait-736h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{414, 736}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>8.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-800-667h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{375, 667}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-700</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{320, 480}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-700-568h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{320, 568}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-700-Portrait</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{768, 1024}</string>
+ </dict>
+ </array>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>arm64</string>
+ </array>
+ <key>UIRequiresFullScreen</key>
+ <true/>
+ <key>UIStatusBarStyle</key>
+ <string>UIStatusBarStyleDefault</string>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>#{device_orientation_xml}</string>
+ </array>
+</dict>
+</plist>
+XML
+
+ # <string>UIInterfaceOrientationPortrait</string>
+ # <string>UIInterfaceOrientationLandscapeRight</string>
+
+ $gtk.write_file_root "tmp/ios/#{@app_name}.app/Info.plist", info_plist_string.gsub(":app_name", @app_name).strip
+
+ @info_plist_written = true
+ end
+
+ def device_orientation_xml
+ return "UIInterfaceOrientationLandscapeRight" if $gtk.logical_width > $gtk.logical_height
+ return "UIInterfaceOrientationPortrait"
+ end
+
+ def tmp_directory
+ "#{relative_path}/tmp/ios"
+ end
+
+ def app_path
+ "#{tmp_directory}/#{@app_name}.app"
+ end
+
+ def root_folder
+ "#{relative_path}/#{$gtk.cli_arguments[:dragonruby]}"
+ end
+
+ def write_ip_address
+ $gtk.write_file "app/server_ip_address.txt", $gtk.ffi_misc.get_local_ip_address.strip
+ end
+
+ def create_ipa
+ write_ip_address
+ sh "rm \"#{@app_name}\".ipa"
+ sh "rm -rf \"#{app_path}/app\""
+ sh "rm -rf \"#{app_path}/sounds\""
+ sh "rm -rf \"#{app_path}/sprites\""
+ sh "rm -rf \"#{app_path}/data\""
+ sh "rm -rf \"#{app_path}/fonts\""
+ sh "cp -r \"#{root_folder}/app/\" \"#{app_path}/app/\""
+ sh "cp -r \"#{root_folder}/sounds/\" \"#{app_path}/sounds/\""
+ sh "cp -r \"#{root_folder}/sprites/\" \"#{app_path}/sprites/\""
+ sh "cp -r \"#{root_folder}/data/\" \"#{app_path}/data/\""
+ sh "cp -r \"#{root_folder}/fonts/\" \"#{app_path}/fonts/\""
+ sh "mkdir -p #{tmp_directory}/ipa_root/Payload"
+ sh "cp -r \"#{app_path}\" \"#{tmp_directory}/ipa_root/Payload\""
+ sh "chmod -R 755 \"#{tmp_directory}/ipa_root/Payload\""
+ do_zip
+ sh "cp \"#{tmp_directory}/ipa_root/archive.zip\" \"#{tmp_directory}/#{@app_name}.ipa\""
+ sh "XCODE_DIR=\"/Applications/Xcode.app/Contents/Developer\" \"#{relative_path}/dragonruby-deploy-ios\" -d \"#{@device_id}\" \"#{tmp_directory}/#{@app_name}.ipa\""
+ cmd_result = `ps -e | grep civetweb`
+ is_civet_running = (`ps -e | grep civetweb`).strip.each_line.to_a.length > 2
+ if !is_civet_running
+ $gtk.system "cp \"#{relative_path}/civetweb\" \"#{tmp_directory}/../src_backup/civetweb\""
+ $gtk.system "open \"#{tmp_directory}/../src_backup/civetweb\" -g"
+ else
+ log "* INFO: civetweb is running already running. No need to start another instance."
+ end
+ log_info "Check your device!!"
+ end
+
+ def do_zip
+ $gtk.write_file_root "tmp/ios/do_zip.sh", <<-SCRIPT
+pushd #{tmp_directory}/ipa_root/
+zip -q -r archive.zip Payload
+popd
+SCRIPT
+
+ sh "sh #{tmp_directory}/do_zip.sh"
+ end
+
+ def sh cmd
+ log_info cmd.strip
+ result = `#{cmd}`
+ if result.strip.length > 0
+ log_info result.strip.each_line.map(&:strip).join("\n")
+ end
+ result
+ end
+
+ def deploy
+ end
+end
+
+</pre>
+<h1 id='--itch_wizard.rb'>itch_wizard.rb</h1>
+<pre># ./dragon/itch_wizard.rb
+# Copyright 2019 DragonRuby LLC
+# MIT License
+# itch_wizard.rb has been released under MIT (*only this file*).
+
+class ItchWizard
+ def steps
+ [
+ :check_metadata,
+ :deploy
+ ]
+ end
+
+ def metadata_file_path
+ "metadata/game_metadata.txt"
+ end
+
+ def get_metadata
+ metadata = $gtk.read_file metadata_file_path
+
+ if !metadata
+ write_blank_metadata
+ metadata = $gtk.read_file metadata_file_path
+ end
+
+ dev_id, dev_title, game_id, game_title, version, icon = *metadata.each_line.to_a
+
+ {
+ dev_id: dev_id.strip,
+ dev_title: dev_title.strip,
+ game_id: game_id.strip,
+ game_title: game_title.strip,
+ version: version.strip,
+ icon: icon.strip
+ }
+ end
+
+ def write_blank_metadata
+ $gtk.write_file metadata_file_path, <<-S.strip
+#devid=myname
+#devtitle=My Name
+#gameid=mygame
+#gametitle=My Game
+#version=0.1
+#icon=metadata/icon.png
+S
+ end
+
+ def check_metadata
+ metadata_text = $gtk.read_file metadata_file_path
+ if !metadata_text
+ write_blank_metadata
+ end
+
+ if metadata_text.each_line.to_a.length != 6
+ write_blank_metadata
+ end
+
+ log "* INFO: Contents of #{metadata_file_path}:"
+ log "#+begin_src txt"
+ metadata_text.each_line { |l| log " #{l}" }
+ log "#+end_src"
+ metadata = get_metadata
+
+ if metadata[:dev_id].start_with?("#") || !@dev_id
+ log "* PROMPT: Please provide your username for Itch."
+ $console.set_command "$wizards.itch.set_dev_id \"your-itch-username\""
+ return :need_dev_id
+ end
+
+ if metadata[:dev_title].start_with?("#") || !@dev_title
+ log "* PROMPT: Please provide developer's/company's name that you want displayed."
+ $console.set_command "$wizards.itch.set_dev_title \"Your Name\""
+ return :need_dev_title
+ end
+
+ if metadata[:game_id].start_with?("#") || !@game_id
+ log "* PROMPT: Please provide the id for you game. This is the id you specified when you set up a new game page on Itch."
+ $console.set_command "$wizards.itch.set_game_id \"your-game-id\""
+ return :need_game_id
+ end
+
+ if metadata[:game_title].start_with?("#") || !@game_title
+ log "* PROMPT: Please provide the display name for your game. (This can include spaces)"
+ $console.set_command "$wizards.itch.set_game_title \"Your Game\""
+ return :need_game_title
+ end
+
+ if metadata[:version].start_with?("#") || !@version
+ log "* PROMPT: Please provide the version for your game."
+ $console.set_command "$wizards.itch.set_version \"1.0\""
+ return :need_version
+ end
+
+ if metadata[:icon].start_with?("#") || !@icon
+ log "* PROPT: Please provide icon path for your game."
+ $console.set_command "$wizards.itch.set_icon \"icon.png\""
+ return :need_icon
+ end
+
+ return :success
+ end
+
+ def set_dev_id value
+ @dev_id = value
+ write_metadata
+ start
+ end
+
+ def set_dev_title value
+ @dev_title = value
+ write_metadata
+ start
+ end
+
+ def set_game_id value
+ @game_id = value
+ write_metadata
+ start
+ end
+
+ def set_game_title value
+ @game_title = value
+ write_metadata
+ start
+ end
+
+ def set_version value
+ @version = value
+ write_metadata
+ start
+ end
+
+ def set_icon value
+ @icon = value
+ write_metadata
+ start
+ end
+
+ def write_metadata
+ text = ""
+ if @dev_id
+ text += "devid=#{@dev_id}\n"
+ else
+ text += "#devid=myname\n"
+ end
+
+ if @dev_title
+ text += "devtitle=#{@dev_title}\n"
+ else
+ text += "#devtitle=My Name\n"
+ end
+
+ if @game_id
+ text += "gameid=#{@game_id}\n"
+ else
+ text += "#gameid=gameid\n"
+ end
+
+ if @game_title
+ text += "gametitle=#{@game_title}\n"
+ else
+ text += "#gametitle=Game Name\n"
+ end
+
+ if @version
+ text += "version=#{@version}\n"
+ else
+ text += "#version=0.1\n"
+ end
+
+ if @icon
+ text += "icon=metadata/#{@icon}\n"
+ else
+ text += "#icon=metadata/icon.png\n"
+ end
+
+ $gtk.write_file metadata_file_path, text
+ end
+
+ def relative_path
+ (File.dirname $gtk.binary_path)
+ end
+
+ def package_command
+ "#{File.join $gtk.get_base_dir, 'dragonruby-publish'}"
+ end
+
+ def deploy
+ log_info "* Running dragonruby-publish: #{package_command}"
+ results = $gtk.exec package_command
+ log "#+begin_src"
+ log results
+ log "#+end_src"
+ :success
+ end
+
+ def start
+ log "================"
+ log "* INFO: Starting Itch Wizard."
+ @start_at = Kernel.global_tick_count
+ steps.each do |m|
+ begin
+ log_info "Running Itch Wizard Step: ~$wizards.itch.#{m}~"
+ result = (send m) || :success if @wizard_status[m][:result] != :success
+ @wizard_status[m][:result] = result
+ if result != :success
+ log_info "Exiting wizard. :#{result}"
+ break
+ end
+ rescue Exception => e
+ if e.is_a? WizardException
+ $console.log.clear
+ $console.archived_log.clear
+ log "=" * $console.console_text_width
+ e.console_primitives.each do |p|
+ $console.add_primitive p
+ end
+ log "=" * $console.console_text_width
+ $console.set_command (e.console_command || "$wizards.itch.start")
+ else
+ log_error "Step #{m} failed."
+ log_error e.to_s
+ $console.set_command "$wizards.itch.start"
+ end
+
+ break
+ end
+ end
+ end
+
+ def reset
+ @dev_id = nil
+ @dev_title = nil
+ @game_id = nil
+ @game_title = nil
+ @version = nil
+ @icon = nil
+ init_wizard_status
+ end
+
+ def restart
+ reset
+ start
+ end
+
+ def initialize
+ reset
+ end
+
+ def init_wizard_status
+ @wizard_status = {}
+
+ steps.each do |m|
+ @wizard_status[m] = { result: :not_started }
+ end
+
+ previous_step = nil
+ next_step = nil
+
+ steps.each_cons(2) do |current_step, next_step|
+ @wizard_status[current_step][:next_step] = next_step
+ end
+
+ steps.reverse.each_cons(2) do |current_step, previous_step|
+ @wizard_status[current_step][:previous_step] = previous_step
+ end
+ end
+end
+
+</pre>
+<h1 id='--layout.rb'>layout.rb</h1>
+<pre># ./dragon/layout.rb
+# Copyright 2019 DragonRuby LLC
+# MIT License
+# layout.rb has been released under MIT (*only this file*).
+
+module GTK
+ class Margin
+ attr :left, :right, :top, :bottom
+
+ def initialize
+ @left = 0
+ @right = 0
+ @top = 0
+ @bottom = 0
+ end
+
+ def serialize
+ {
+ left: @left,
+ right: @right,
+ top: @top,
+ bottom: @bottom,
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class SafeArea
+ attr :w, :h, :margin
+
+ def initialize
+ @w = 0
+ @h = 0
+ @margin = Margin.new
+ end
+
+ def serialize
+ {
+ w: @w,
+ h: @h,
+ margin: @margin.serialize
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class GridArea
+ attr :w, :h, :margin, :gutter, :col_count, :row_count, :cell_w, :cell_h, :outer_gutter
+
+ def initialize
+ @w = 0
+ @h = 0
+ @gutter = 0
+ @outer_gutter = 0
+ @col_count = 0
+ @row_count = 0
+ @margin = Margin.new
+ end
+
+ def serialize
+ {
+ w: @w,
+ h: @h,
+ gutter: @gutter,
+ outer_gutter: @outer_gutter,
+ col_count: @col_count,
+ row_count: @row_count,
+ margin: @margin.serialize
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class ControlArea
+ attr :cell_size, :w, :h, :margin
+
+ def initialize
+ @margin = Margin.new
+ end
+
+ def serialize
+ {
+ cell_size: @cell_size,
+ w: @w,
+ h: @h,
+ margin: @margin.serialize,
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class Device
+ attr :w, :h, :safe_area, :grid_area, :control_area, :name, :aspect
+
+ def initialize
+ @name = ""
+ @w = 0
+ @h = 0
+ @safe_area = SafeArea.new
+ @grid_area = GridArea.new
+ @control_area = ControlArea.new
+ @aspect = AspectRatio.new
+ end
+
+ def assert! result, message
+ return if result
+ raise message
+ end
+
+ def check_math!
+ assert! (@control_area.w + @control_area.margin.left + @control_area.margin.right) == @w, "Math for Width didn't pan out."
+ assert! (@control_area.h + @control_area.margin.top + @control_area.margin.bottom) == @h, "Math for Height didn't pan out."
+ end
+
+ def serialize
+ {
+ name: @name,
+ w: @w,
+ h: @h,
+ aspect: @aspect.serialize,
+ safe_area: @safe_area.serialize,
+ grid_area: @grid_area.serialize,
+ control_area: @control_area.serialize
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class AspectRatio
+ attr :w, :h, :u
+
+ def initialize
+ @w = 0
+ @h = 0
+ @u = 0
+ end
+
+ def serialize
+ {
+ w: @w,
+ h: @h,
+ u: @u
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class Layout
+ attr :w, :h, :rect_cache
+
+ def initialize w, h
+ @w = w
+ @h = h
+ @rect_cache = {}
+ init_device @w, @h
+ end
+
+ def u_for_16x9 w, h
+ u = (w.fdiv 16).floor
+ u = (h.fdiv 9).floor if (u * 9) > h
+
+ {
+ u: u,
+ w: u * 16,
+ h: u * 9
+ }
+ end
+
+ def font_relative_size_enum size_enum
+ base_line_logical = 22
+ base_line_actual = font_size_med
+ target_logical = size_enum
+ target_logical = 1 if target_logical <= 0
+ (base_line_actual / base_line_logical) * target_logical
+ end
+
+ def font_px_to_pt px
+ (px / 1.33333).floor
+ end
+
+ def font_pt_to_px pt
+ pt * 1.333333
+ end
+
+ def font_size_cell
+ (cell_height / 1.33333)
+ end
+
+ def font_size_xl
+ font_size_cell
+ end
+
+ def font_size_lg
+ font_size_cell * 0.8
+ end
+
+ def font_size_med
+ font_size_cell * 0.7
+ end
+
+ def font_size_sm
+ font_size_cell * 0.6
+ end
+
+ def font_size_xs
+ font_size_cell * 0.5
+ end
+
+ def font_size
+ font_size_cell * 0.7
+ end
+
+ def logical_rect
+ @logical_rect ||= { x: 0,
+ y: 0,
+ w: @w,
+ h: @h }
+ end
+
+ def safe_rect
+ @safe_rect ||= { x: 0,
+ y: 0,
+ w: @w,
+ h: @h }
+ end
+
+ def control_rect
+ @control_rect ||= { x: device.control_area.margin.left,
+ y: device.control_area.margin.top,
+ w: device.control_area.w,
+ h: device.control_area.h }
+ end
+
+ def row_count
+ device.grid_area.row_count
+ end
+
+ def col_count
+ device.grid_area.col_count
+ end
+
+ def gutter_height
+ device.grid_area.gutter
+ end
+
+ def gutter_width
+ device.grid_area.gutter
+ end
+
+ def outer_gutter
+ device.grid_area.outer_gutter
+ end
+
+ def cell_height
+ device.control_area.cell_size
+ end
+
+ def cell_width
+ device.control_area.cell_size
+ end
+
+ def rect_defaults
+ {
+ row: nil,
+ col: nil,
+ h: 1,
+ w: 1,
+ dx: 0,
+ dy: 0,
+ rect: :control_rect
+ }
+ end
+
+ def rect opts
+ opts = rect_defaults.merge opts
+ result = send opts[:rect]
+ if opts[:row] && opts[:col] && opts[:w] && opts[:h]
+ col = rect_col opts[:col], opts[:w]
+ row = rect_row opts[:row], opts[:h]
+ result = control_rect.merge x: col.x,
+ y: row.y,
+ w: col.w,
+ h: row.h
+ elsif opts[:row] && !opts[:col]
+ result = rect_row opts[:row], opts[:h]
+ elsif !opts[:row] && opts[:col]
+ result = rect_col opts[:col], opts[:w]
+ else
+ raise "LayoutTheory::rect unable to process opts #{opts}."
+ end
+
+ if opts[:max_height] && opts[:max_height] >= 0
+ if result[:h] > opts[:max_height]
+ delta = (result[:h] - opts[:max_height]) * 2
+ result[:y] += delta
+ result[:h] = opts[:max_height]
+ end
+ end
+
+ if opts[:max_width] && opts[:max_width] >= 0
+ if result[:w] > opts[:max_width]
+ delta = (result[:w] - opts[:max_width]) * 2
+ result[:x] += delta
+ result[:w] = opts[:max_width]
+ end
+ end
+
+ result[:x] += opts[:dx]
+ result[:y] += opts[:dy]
+
+ if opts[:include_row_gutter]
+ result[:x] -= device.grid_area.gutter
+ result[:w] += device.grid_area.gutter * 2
+ end
+
+ if opts[:include_col_gutter]
+ result[:y] -= device.grid_area.gutter
+ result[:h] += device.grid_area.gutter * 2
+ end
+
+ result
+ end
+
+ def rect_center reference, target
+ delta_x = (reference.w - target.w).fdiv 2
+ delta_y = (reference.h - target.h).fdiv 2
+ [target.x - delta_x, target.y - delta_y, target.w, target.h]
+ end
+
+ def rect_row index, h
+ @rect_cache[:row] ||= {}
+ @rect_cache[:row][index] ||= {}
+ return @rect_cache[:row][index][h] if @rect_cache[:row][index][h]
+ row_h = (device.grid_area.gutter * (h - 1)) +
+ (device.control_area.cell_size * h)
+
+ row_h = row_h.to_i
+ row_h -= 1 if row_h.odd?
+
+ row_y = (control_rect.y) +
+ (device.grid_area.gutter * index) +
+ (device.control_area.cell_size * index)
+
+ row_y = row_y.to_i
+ row_y += 1 if row_y.odd? && (index + 1) > @device.grid_area.row_count.half
+ row_y += 1 if row_y.odd? && (index + 1) <= @device.grid_area.row_count.half
+
+ row_y = device.h - row_y - row_h
+
+ result = control_rect.merge y: row_y, h: row_h
+ @rect_cache[:row][index][h] = result
+ @rect_cache[:row][index][h]
+ end
+
+ def rect_col index, w
+ @rect_cache[:col] ||= {}
+ @rect_cache[:col][index] ||= {}
+ return @rect_cache[:col][index][w] if @rect_cache[:col][index][w]
+ col_x = (control_rect.x) +
+ (device.grid_area.gutter * index) +
+ (device.control_area.cell_size * index)
+
+ col_x = col_x.to_i
+ col_x -= 1 if col_x.odd? && (index + 1) < @device.grid_area.col_count.half
+ col_x += 1 if col_x.odd? && (index + 1) >= @device.grid_area.col_count.half
+
+ col_w = (device.grid_area.gutter * (w - 1)) +
+ (device.control_area.cell_size * w)
+
+ col_w = col_w.to_i
+ col_w -= 1 if col_w.odd?
+
+ result = control_rect.merge x: col_x, w: col_w
+ @rect_cache[:col][index][w] = result
+ @rect_cache[:col][index][w]
+ end
+
+ def device
+ @device
+ end
+
+ def init_device w, h
+ @device = Device.new
+ @device.w = w
+ @device.h = h
+ @device.name = "Device"
+ @device.aspect.w = (u_for_16x9 w, h)[:w]
+ @device.aspect.h = (u_for_16x9 w, h)[:h]
+ @device.aspect.u = (u_for_16x9 w, h)[:u]
+ @device.safe_area.w = @device.aspect.u * 16
+ @device.safe_area.h = @device.aspect.u * 9
+ @device.safe_area.margin.left = ((@device.w - @device.safe_area.w).fdiv 2).floor
+ @device.safe_area.margin.right = ((@device.w - @device.safe_area.w).fdiv 2).floor
+ @device.safe_area.margin.top = ((@device.h - @device.safe_area.h).fdiv 2).floor
+ @device.safe_area.margin.bottom = ((@device.h - @device.safe_area.h).fdiv 2).floor
+ @device.grid_area.outer_gutter = @device.w / 80
+ @device.grid_area.gutter = @device.w / 160
+
+ @device.grid_area.w = @device.safe_area.w - (@device.grid_area.outer_gutter * 2)
+ @device.grid_area.h = @device.safe_area.h - (@device.grid_area.outer_gutter * 2)
+
+ @device.grid_area.margin.left = ((@device.w - @device.grid_area.w).fdiv 2).floor
+ @device.grid_area.margin.right = ((@device.w - @device.grid_area.w).fdiv 2).floor
+ @device.grid_area.margin.top = ((@device.h - @device.grid_area.h).fdiv 2).floor
+ @device.grid_area.margin.bottom = ((@device.h - @device.grid_area.h).fdiv 2).floor
+
+ @device.grid_area.col_count = 24
+ @device.grid_area.row_count = 12
+ @device.grid_area.cell_w = ((@device.aspect.w - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.col_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.col_count
+ @device.grid_area.cell_h = ((@device.aspect.h - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.row_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.row_count
+
+ @device.control_area.cell_size = @device.grid_area.cell_w
+ @device.control_area.cell_size = @device.grid_area.cell_h if @device.grid_area.cell_h < @device.grid_area.cell_w && @device.grid_area.cell_h > 0
+ @device.control_area.cell_size = @device.control_area.cell_size.floor
+ @device.control_area.w = (@device.control_area.cell_size * @device.grid_area.col_count) + (@device.grid_area.gutter * (@device.grid_area.col_count - 1))
+ @device.control_area.h = (@device.control_area.cell_size * @device.grid_area.row_count) + (@device.grid_area.gutter * (@device.grid_area.row_count - 1))
+ @device.control_area.margin.left = (@device.w - @device.control_area.w).fdiv 2
+ @device.control_area.margin.right = (@device.w - @device.control_area.w).fdiv 2
+ @device.control_area.margin.top = (@device.h - @device.control_area.h).fdiv 2
+ @device.control_area.margin.bottom = (@device.h - @device.control_area.h).fdiv 2
+ @device
+ end
+
+ def serialize
+ {
+ device: @device.serialize,
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+end
+
+</pre>
<h1 id='--log.rb'>log.rb</h1>
<pre># ./dragon/log.rb
# coding: utf-8
@@ -26047,6 +28267,11 @@ S
return 720 - self unless $gtk
$gtk.args.grid.h - self
end
+
+ def from_right
+ return 1280 - self unless $gtk
+ $gtk.args.grid.w - self
+ end
end
class Fixnum
@@ -26194,6 +28419,245 @@ class Integer
end
</pre>
+<h1 id='--runtime/draw.rb'>runtime/draw.rb</h1>
+<pre># ./dragon/runtime/draw.rb
+# Copyright 2019 DragonRuby LLC
+# MIT License
+# draw.rb has been released under MIT (*only this file*).
+
+module GTK
+ class Runtime
+ module Draw
+ def primitives pass
+ if $top_level.respond_to? :primitives_override
+ return $top_level.tick_render @args, pass
+ end
+
+ # Don't change this draw order unless you understand
+ # the implications.
+
+ # pass.solids.each { |s| draw_solid s }
+ # while loops are faster than each with block
+ idx = 0
+ while idx < pass.solids.length
+ draw_solid (pass.solids.value idx) # accessing an array using .value instead of [] is faster
+ idx += 1
+ end
+
+ # pass.static_solids.each { |s| draw_solid s }
+ idx = 0
+ while idx < pass.static_solids.length
+ draw_solid (pass.static_solids.value idx)
+ idx += 1
+ end
+
+ # pass.sprites.each { |s| draw_sprite s }
+ idx = 0
+ while idx < pass.sprites.length
+ draw_sprite (pass.sprites.value idx)
+ idx += 1
+ end
+
+ # pass.static_sprites.each { |s| draw_sprite s }
+ idx = 0
+ while idx < pass.static_sprites.length
+ draw_sprite (pass.static_sprites.value idx)
+ idx += 1
+ end
+
+ # pass.primitives.each { |p| draw_primitive p }
+ idx = 0
+ while idx < pass.primitives.length
+ draw_primitive (pass.primitives.value idx)
+ idx += 1
+ end
+
+ # pass.static_primitives.each { |p| draw_primitive p }
+ idx = 0
+ while idx < pass.static_primitives.length
+ draw_primitive (pass.static_primitives.value idx)
+ idx += 1
+ end
+
+ # pass.labels.each { |l| draw_label l }
+ idx = 0
+ while idx < pass.labels.length
+ draw_label (pass.labels.value idx)
+ idx += 1
+ end
+
+ # pass.static_labels.each { |l| draw_label l }
+ idx = 0
+ while idx < pass.static_labels.length
+ draw_label (pass.static_labels.value idx)
+ idx += 1
+ end
+
+ # pass.lines.each { |l| draw_line l }
+ idx = 0
+ while idx < pass.lines.length
+ draw_line (pass.lines.value idx)
+ idx += 1
+ end
+
+ # pass.static_lines.each { |l| draw_line l }
+ idx = 0
+ while idx < pass.static_lines.length
+ draw_line (pass.static_lines.value idx)
+ idx += 1
+ end
+
+ # pass.borders.each { |b| draw_border b }
+ idx = 0
+ while idx < pass.borders.length
+ draw_border (pass.borders.value idx)
+ idx += 1
+ end
+
+ # pass.static_borders.each { |b| draw_border b }
+ idx = 0
+ while idx < pass.static_borders.length
+ draw_border (pass.static_borders.value idx)
+ idx += 1
+ end
+
+ if !$gtk.production
+ # pass.debug.each { |r| draw_primitive r }
+ idx = 0
+ while idx < pass.debug.length
+ draw_primitive (pass.debug.value idx)
+ idx += 1
+ end
+
+ # pass.static_debug.each { |r| draw_primitive r }
+ idx = 0
+ while idx < pass.static_debug.length
+ draw_primitive (pass.static_debug.value idx)
+ idx += 1
+ end
+ end
+
+ # pass.reserved.each { |r| draw_primitive r }
+ idx = 0
+ while idx < pass.reserved.length
+ draw_primitive (pass.reserved.value idx)
+ idx += 1
+ end
+
+ # pass.static_reserved.each { |r| draw_primitive r }
+ idx = 0
+ while idx < pass.static_reserved.length
+ draw_primitive (pass.static_reserved.value idx)
+ idx += 1
+ end
+ rescue Exception => e
+ pause!
+ pretty_print_exception_and_export! e
+ end
+
+ def draw_solid s
+ return unless s
+ if s.respond_to? :draw_override
+ s.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_solid s.x, s.y, s.w, s.h, s.r, s.g, s.b, s.a
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed s, e, :solid
+ end
+
+ def draw_sprite s
+ return unless s
+ if s.respond_to? :draw_override
+ s.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_sprite_3 s.x, s.y, s.w, s.h,
+ s.path.s_or_default,
+ s.angle,
+ s.a, s.r, s.g, s.b,
+ s.tile_x, s.tile_y, s.tile_w, s.tile_h,
+ !!s.flip_horizontally, !!s.flip_vertically,
+ s.angle_anchor_x, s.angle_anchor_y,
+ s.source_x, s.source_y, s.source_w, s.source_h
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed s, e, :sprite
+ end
+
+ def draw_screenshot s
+ return unless s
+ if s.respond_to? :draw_override
+ s.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_screenshot s.path.s_or_default,
+ s.x, s.y, s.w, s.h,
+ s.angle,
+ s.a, s.r, s.g, s.b,
+ s.tile_x, s.tile_y, s.tile_w, s.tile_h,
+ !!s.flip_horizontally, !!s.flip_vertically,
+ s.angle_anchor_x, s.angle_anchor_y,
+ s.source_x, s.source_y, s.source_w, s.source_h
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed s, e, :screenshot
+ end
+
+ def draw_label l
+ return unless l
+ if l.respond_to? :draw_override
+ l.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_label l.x, l.y, l.text.s_or_default,
+ l.size_enum, l.alignment_enum,
+ l.r, l.g, l.b, l.a,
+ l.font.s_or_default(nil)
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed l, e, :label
+ end
+
+ def draw_line l
+ return unless l
+ if l.respond_to? :draw_override
+ l.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_line l.x, l.y, l.x2, l.y2, l.r, l.g, l.b, l.a
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed l, e, :line
+ end
+
+ def draw_border s
+ return unless s
+ if s.respond_to? :draw_override
+ s.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_border s.x, s.y, s.w, s.h, s.r, s.g, s.b, s.a
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed s, e, :border
+ end
+
+ def draw_screenshots
+ @args.outputs.screenshots.each { |s| draw_screenshot s }
+ end
+
+ def pixel_arrays
+ @args.pixel_arrays.each { |k,v|
+ if v.pixels.length == (v.width * v.height) # !!! FIXME: warning? exception? Different API?
+ @ffi_draw.upload_pixel_array k.to_s, v.width.to_i, v.height.to_i, v.pixels
+ end
+ }
+ rescue Exception => e
+ pause!
+ pretty_print_exception_and_export! e
+ end
+
+ end
+ end
+end
+
+</pre>
<h1 id='--runtime/framerate_diagnostics.rb'>runtime/framerate_diagnostics.rb</h1>
<pre># ./dragon/runtime/framerate_diagnostics.rb
# Copyright 2019 DragonRuby LLC
@@ -26470,6 +28934,10 @@ S
def rtrim!
rstrip!
end
+
+ def serialize
+ self
+ end
end
</pre>
@@ -26623,6 +29091,9 @@ end
# MIT License
# trace.rb has been released under MIT (*only this file*).
+# Contributors outside of DragonRuby who also hold Copyright:
+# - Dan Healy: https://github.com/danhealy
+
module GTK
module Trace
IGNORED_METHODS = [
@@ -26702,10 +29173,19 @@ module GTK
methods.reject { |m| m.start_with? "__trace_" }.reject { |m| IGNORED_METHODS.include? m }
end
+ def self.trace_times_string
+ str = []
+ $trace_performance.sort_by {|method_name, times| -times[:avg] }.each do |method_name, times|
+ str << "#{method_name}: #{times[:sum].round(2)}/#{times[:count]} #{times[:min]}ms min, #{times[:avg].round(2)}ms avg, #{times[:max]}ms max"
+ end
+ str.join("\n")
+ end
+
def self.flush_trace pad_with_newline = false
$trace_puts ||= []
+ puts "(Trace info flushed!)"
if $trace_puts.length > 0
- text = $trace_puts.join("")
+ text = $trace_puts.join("").strip + "\n" + self.trace_times_string + "\n"
if pad_with_newline
$gtk.append_file_root 'logs/trace.txt', "\n" + text.strip
else
@@ -26720,6 +29200,15 @@ module GTK
$trace_history ||= []
$trace_enabled = true
$trace_call_depth ||=0
+ $trace_performance = Hash.new {|h,k|
+ h[k] = {
+ min: 100000,
+ max: 0,
+ avg: 0,
+ sum: 0,
+ count: 0
+ }
+ }
flush_trace
instance = $top_level unless instance
return if Trace.traced_classes.include? instance.class
@@ -26737,15 +29226,27 @@ module GTK
instance.__trace_call_depth__ += 1
$trace_call_depth = instance.__trace_call_depth__
parameters = "#{args}"[1..-2]
+
$trace_puts << "\n #{tab_width}#{m}(#{parameters})"
- execution_time = Time.new.to_i
+
+ execution_time = Time.new
+
$last_method_traced = trace_method_name
$trace_history << [m, parameters]
+
result = send(trace_method_name, *args)
- completion_time = Time.new.to_i
+
+ class_m = "#{instance.class}##{m}"
+ completion_time = ((Time.new - execution_time).to_f * 1000).round(2)
+ $trace_performance[class_m][:min] = [$trace_performance[class_m][:min], completion_time].min
+ $trace_performance[class_m][:max] = [$trace_performance[class_m][:max], completion_time].max
+ $trace_performance[class_m][:count] += 1
+ $trace_performance[class_m][:sum] += completion_time
+ $trace_performance[class_m][:avg] = $trace_performance[class_m][:sum].fdiv($trace_performance[class_m][:count])
+
instance.__trace_call_depth__ -= 1
instance.__trace_call_depth__ = instance.__trace_call_depth__.greater 0
- $trace_puts << "\n #{tab_width} success: #{m}"
+ $trace_puts << "\n #{tab_width} #{completion_time > 10 ? '!!! ' : ''}#{completion_time}ms success: #{m}"
if instance.__trace_call_depth__ == 0
$trace_puts << "\n"
$trace_history.clear
@@ -26771,6 +29272,24 @@ module GTK
end
</pre>
+<h1 id='--wizards.rb'>wizards.rb</h1>
+<pre># ./dragon/wizards.rb
+# Copyright 2019 DragonRuby LLC
+# MIT License
+# wizards.rb has been released under MIT (*only this file*).
+
+module GTK
+ class Wizards
+ attr_accessor :ios, :itch
+
+ def initialize
+ @ios = IOSWizard.new
+ @itch = ItchWizard.new
+ end
+ end
+end
+
+</pre>
</div>
</body>
</html>
diff --git a/docs/docs.txt b/docs/docs.txt
index c79543f..6887e35 100644
--- a/docs/docs.txt
+++ b/docs/docs.txt
@@ -1167,19 +1167,6 @@ do
* DOCS: ~GTK::Runtime~
The GTK::Runtime class is the core of DragonRuby. It is globally accessible via ~$gtk~.
-* DOCS: ~GTK::Runtime#reset~
-This function will reset Kernel.tick_count to 0 and will remove all data from args.state.
-
-* DOCS: ~GTK::Runtime#calcstringbox~
-This function returns the width and height of a string.
-
-#+begin_src ruby
- def tick args
- args.state.string_size ||= args.gtk.calcstringbox "Hello World"
- args.state.string_size_font_size ||= args.gtk.calcstringbox "Hello World"
- end
-#+end_src
-
* DOCS: ~GTK::Runtime#write_file~
This function takes in two parameters. The first paramter is the file path and assumes the the game
directory is the root. The second parameter is the string that will be written. The method overwrites whatever
@@ -1193,6 +1180,19 @@ is currently in the file. Use ~GTK::Runtime#append_file~ to append to the file a
end
#+end_src
+* DOCS: ~GTK::Runtime#reset~
+This function will reset Kernel.tick_count to 0 and will remove all data from args.state.
+
+* DOCS: ~GTK::Runtime#calcstringbox~
+This function returns the width and height of a string.
+
+#+begin_src ruby
+ def tick args
+ args.state.string_size ||= args.gtk.calcstringbox "Hello World"
+ args.state.string_size_font_size ||= args.gtk.calcstringbox "Hello World"
+ end
+#+end_src
+
* DOCS: ~Array~
The Array class has been extend to provide methods that
@@ -1568,6 +1568,29 @@ You have to use ~args.outputs.borders~:
#+end_src
+* DOCS: ~GTK::Outputs#screenshots~
+
+Add a hash to this collection to take a screenshot and save as png file.
+The keys of the hash can be provided in any order.
+
+#+begin_src
+ def tick args
+ args.outputs.screenshots << {
+ x: 0, y: 0, w: 100, h: 100, # Which portion of the screen should be captured
+ path: 'screenshot.png', # Output path of PNG file (inside game directory)
+ r: 255, g: 255, b: 255, a: 0 # Optional chroma key
+ }
+ end
+#+end_src
+
+** Chroma key (Making a color transparent)
+
+By specifying the r, g, b and a keys of the hash you change the transparency of a color in the resulting PNG file.
+This can be useful if you want to create files with transparent background like spritesheets.
+The transparency of the color specified by ~r~, ~g~, ~b~ will be set to the transparency specified by ~a~.
+
+The example above sets the color white (255, 255, 255) as transparent.
+
* DOCS: ~GTK::Mouse~
The mouse is accessible via ~args.inputs.mouse~:
@@ -2953,12 +2976,6 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
-* Learn Ruby Optional - Intermediate Ruby Primer - repl.rb
-#+begin_src ruby
- # ./samples/00_learn_ruby_optional/00_intermediate_ruby_primer/app/repl.rb
-
-#+end_src
-
* Rendering Basics - Labels - main.rb
#+begin_src ruby
# ./samples/01_rendering_basics/01_labels/app/main.rb
@@ -3440,6 +3457,534 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
+* Rendering Basics - Audio Mixer - main.rb
+#+begin_src ruby
+ # ./samples/01_rendering_basics/06_audio_mixer/app/main.rb
+ $gtk.reset
+
+ $boxsize = 30
+
+ def render_sources args
+ mouse_in_panel = (args.state.selected != 0) && args.inputs.mouse.position.inside_rect?([900, 450, 340, 250])
+ mouse_new_down = (args.state.mouse_held == 1)
+
+ if (mouse_new_down && !mouse_in_panel)
+ args.state.selected = 0 # will reset below if we hit something.
+ end
+
+ args.audio.keys.each { |k|
+ s = args.audio[k]
+
+ if (mouse_new_down) && !mouse_in_panel && args.inputs.mouse.position.inside_rect?([s[:screenx], s[:screeny], $boxsize, $boxsize])
+ args.state.selected = k
+ args.state.dragging_source = true
+ end
+
+ isselected = (k == args.state.selected)
+
+ if isselected && args.state.dragging_source
+ # you can hang anything on the audio hashes you want, so we store the
+ # actual screen position so it doesn't scale weirdly vs your mouse.
+ s[:screenx] = args.inputs.mouse.x - ($boxsize / 2)
+ s[:screeny] = args.inputs.mouse.y - ($boxsize / 2)
+
+ s[:screeny] = 50 if s[:screeny] < 50
+ s[:screeny] = (719 - $boxsize) if s[:screeny] > (719 - $boxsize)
+ s[:screenx] = 0 if s[:screenx] < 0
+ s[:screenx] = (1279 - $boxsize) if s[:screenx] > (1279 - $boxsize)
+
+ s[:x] = ((s[:screenx] / 1279.0) * 2.0) - 1.0 # scale to -1.0 - 1.0 range
+ s[:y] = ((s[:screeny] / 719.0) * 2.0) - 1.0 # scale to -1.0 - 1.0 range
+ end
+
+ color = isselected ? [ 0, 255, 0, 255 ] : [ 0, 0, 255, 255 ]
+ args.outputs.primitives << [s[:screenx], s[:screeny], $boxsize, $boxsize, *color].solid
+ }
+ end
+
+ def render_panel args
+ s = args.audio[args.state.selected]
+ return if s.nil?
+ mouse_down = (args.state.mouse_held > 0)
+
+ args.outputs.primitives << [900, 450, 340, 250, 127, 127, 200, 255].solid
+ args.outputs.primitives << [1075, 690, "Source ##{args.state.selected}", 3, 1, 255, 255, 255].label
+ args.outputs.primitives << [910, 660, 1230, 660, 255, 255, 255].line
+ args.outputs.primitives << [910, 650, "screen: (#{s[:screenx].to_i}, #{s[:screeny].to_i})", 0, 0, 255, 255, 255].label
+ args.outputs.primitives << [910, 625, "position: (#{s[:x].round(5).to_s[0..6]}, #{s[:y].round(5).to_s[0..6]})", 0, 0, 255, 255, 255].label
+
+ slider = [1022, 586, 200, 7]
+ if mouse_down && args.inputs.mouse.position.inside_rect?(slider)
+ s[:pitch] = ((args.inputs.mouse.x - slider[0]).to_f / (slider[2]-1.0)) * 2.0
+ end
+ slidercolor = (s[:pitch] / 2.0) * 255
+ args.outputs.primitives << [*slider, slidercolor, slidercolor, slidercolor, 255].solid
+ args.outputs.primitives << [910, 600, "pitch: #{s[:pitch].round(3).to_s[0..2]}", 0, 0, 255, 255, 255].label
+
+ slider = [1022, 561, 200, 7]
+ if mouse_down && args.inputs.mouse.position.inside_rect?(slider)
+ s[:gain] = (args.inputs.mouse.x - slider[0]).to_f / (slider[2]-1.0)
+ end
+ slidercolor = s[:gain] * 255
+ args.outputs.primitives << [*slider, slidercolor, slidercolor, slidercolor, 255].solid
+ args.outputs.primitives << [910, 575, "gain: #{s[:gain].round(3).to_s[0..2]}", 0, 0, 255, 255, 255].label
+
+ checkbox = [1022, 533, 10, 12]
+ if (args.state.mouse_held == 1) && args.inputs.mouse.position.inside_rect?(checkbox)
+ s[:looping] = !s[:looping]
+ end
+ checkboxcolor = s[:looping] ? 255 : 0
+ args.outputs.primitives << [*checkbox, checkboxcolor, checkboxcolor, checkboxcolor, 255].solid
+ args.outputs.primitives << [910, 550, "looping:", 0, 0, 255, 255, 255].label
+
+ checkbox = [1022, 508, 10, 12]
+ if (args.state.mouse_held == 1) && args.inputs.mouse.position.inside_rect?(checkbox)
+ s[:paused] = !s[:paused]
+ end
+ checkboxcolor = s[:paused] ? 255 : 0
+ args.outputs.primitives << [*checkbox, checkboxcolor, checkboxcolor, checkboxcolor, 255].solid
+ args.outputs.primitives << [910, 525, "paused:", 0, 0, 255, 255, 255].label
+
+ button = [910, 460, 320, 20]
+ if (args.state.mouse_held == 1) && args.inputs.mouse.position.inside_rect?(button)
+ args.audio.delete(args.state.selected)
+ args.state.selected = 0
+ end
+ args.outputs.primitives << [*button, 255, 0, 0, 255].solid
+ args.outputs.primitives << [button[0] + (button[2] / 2), button[1]+20, "DELETE SOURCE", 0, 1, 255, 255, 0].label
+ end
+
+ def spawn_new_sound args, num
+ input = nil
+ input = "sounds/#{num}.#{(num == 6) ? 'ogg' : 'wav'}"
+
+ # Spawn randomly in an area that won't be covered by UI.
+ screenx = (rand * 600.0) + 200.0
+ screeny = (rand * 400.0) + 100.0
+
+ args.state.next_sound_index += 1
+
+ # you can hang anything on the audio hashes you want, so we store the
+ # actual screen position in here for convenience.
+ args.audio[args.state.next_sound_index] = {
+ input: input,
+ screenx: screenx,
+ screeny: screeny,
+ x: ((screenx / 1279.0) * 2.0) - 1.0, # scale to -1.0 - 1.0 range
+ y: ((screeny / 719.0) * 2.0) - 1.0, # scale to -1.0 - 1.0 range
+ z: 0.0,
+ gain: 1.0,
+ pitch: 1.0,
+ looping: true,
+ paused: false
+ }
+
+ args.state.selected = args.state.next_sound_index
+ end
+
+ def render_launcher args
+ total = 6
+ x = (1280 - (total * $boxsize * 3)) / 2
+ y = 10
+ args.outputs.primitives << [0, 0, 1280, ((y*2) + $boxsize), 127, 127, 127, 255].solid
+ for i in 1..total
+ args.outputs.primitives << [x, y, $boxsize, $boxsize, 255, 255, 255, 255].solid
+ args.outputs.primitives << [x+8, y+28, i.to_s, 3, 0, 0, 0, 255, 255].label
+ if args.inputs.mouse.click && args.inputs.mouse.click.point.inside_rect?([x, y, $boxsize, $boxsize])
+ spawn_new_sound args, i
+ end
+ x = x + ($boxsize * 3)
+ end
+ end
+
+ def render_ui args
+ render_launcher args
+ render_panel args
+ end
+
+ def tick args
+ args.state.mouse_held ||= 0
+ args.state.dragging_source ||= false
+ args.state.selected ||= 0
+ args.state.next_sound_index ||= 0
+
+ if args.inputs.mouse.up
+ args.state.mouse_held = 0
+ args.state.dragging_source = false
+ elsif args.inputs.mouse.down || (args.state.mouse_held > 0)
+ args.state.mouse_held += 1
+ else
+ end
+
+ args.outputs.background_color = [ 0, 0, 0, 255 ]
+ render_sources args
+ render_ui args
+ end
+
+#+end_src
+
+* Rendering Basics - Sound Synthesis - main.rb
+#+begin_src ruby
+ # ./samples/01_rendering_basics/07_sound_synthesis/app/main.rb
+ def tick args
+ defaults args
+ render args
+ input args
+ process_audio_queue args
+ end
+
+ def defaults args
+ args.state.sine_waves ||= {}
+ args.state.audio_queue ||= []
+ args.state.buttons ||= [
+ (frequency_buttons args),
+ (note_buttons args),
+ (bell_buttons args)
+ ].flatten
+ end
+
+ def frequency_buttons args
+ [
+ (button args,
+ row: 4.0, col: 0, text: "300hz",
+ frequency: 300,
+ method_to_call: :play_sine_wave),
+ (button args,
+ row: 5.0, col: 0, text: "400hz",
+ frequency: 400,
+ method_to_call: :play_sine_wave),
+ (button args,
+ row: 6.0, col: 0, text: "500hz",
+ frequency: 500,
+ method_to_call: :play_sine_wave),
+ ]
+ end
+
+ def play_sine_wave args, sender
+ queue_sine_wave args,
+ frequency: sender[:frequency],
+ duration: 1.seconds,
+ fade_out: true
+ end
+
+
+ def note_buttons args
+ [
+ (button args,
+ row: 1.5, col: 3, text: "C4",
+ note: :c, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 2.5, col: 3, text: "D4",
+ note: :d, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 3.5, col: 3, text: "E4",
+ note: :e, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 4.5, col: 3, text: "F4",
+ note: :f, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 5.5, col: 3, text: "G4",
+ note: :g, octave: 4, method_to_call: :play_note),
+ (button args,
+ row: 6.5, col: 3, text: "A5",
+ note: :a, octave: 5, method_to_call: :play_note),
+ (button args,
+ row: 7.5, col: 3, text: "B5",
+ note: :b, octave: 5, method_to_call: :play_note),
+ (button args,
+ row: 8.5, col: 3, text: "C5",
+ note: :c, octave: 5, method_to_call: :play_note),
+ ]
+ end
+
+ def play_note args, sender
+ queue_sine_wave args,
+ frequency: (frequency_for note: sender[:note],
+ octave: sender[:octave]),
+ duration: 1.seconds,
+ fade_out: true
+ end
+
+ def bell_buttons args
+ [
+ (button args,
+ row: 1.5, col: 6, text: "Bell C4",
+ note: :c, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 2.5, col: 6, text: "Bell D4",
+ note: :d, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 3.5, col: 6, text: "Bell E4",
+ note: :e, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 4.5, col: 6, text: "Bell F4",
+ note: :f, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 5.5, col: 6, text: "Bell G4",
+ note: :g, octave: 4, method_to_call: :play_bell),
+ (button args,
+ row: 6.5, col: 6, text: "Bell A5",
+ note: :a, octave: 5, method_to_call: :play_bell),
+ (button args,
+ row: 7.5, col: 6, text: "Bell B5",
+ note: :b, octave: 5, method_to_call: :play_bell),
+ (button args,
+ row: 8.5, col: 6, text: "Bell C5",
+ note: :c, octave: 5, method_to_call: :play_bell),
+ ]
+ end
+
+ def play_bell args, sender
+ queue_bell args,
+ frequency: (frequency_for note: sender[:note],
+ octave: sender[:octave]),
+ duration: 2.seconds,
+ fade_out: true
+ end
+
+ def render args
+ args.outputs.borders << args.state.buttons.map { |b| b[:border] }
+ args.outputs.labels << args.state.buttons.map { |b| b[:label] }
+ args.outputs.labels << args.layout
+ .rect(row: 0,
+ col: 11.5)
+ .yield_self { |r| r.merge y: r.y + r.h }
+ .merge(text: "This is a Pro only feature. Click here to watch the YouTube video if you are on the Standard License.",
+ alignment_enum: 1)
+ end
+
+ def input args
+ args.state.buttons.each do |b|
+ if args.inputs.mouse.click.inside_rect? b[:rect]
+ parameter_string = (b.slice :frequency, :note, :octave).map { |k, v| "#{k}: #{v}" }.join ", "
+ args.gtk.notify! "#{b[:method_to_call]} #{parameter_string}"
+ send b[:method_to_call], args, b
+ end
+ end
+
+ if args.inputs.mouse.click.inside_rect? (args.layout.rect(row: 0).yield_self { |r| r.merge y: r.y + r.h.half, h: r.h.half })
+ args.gtk.openurl 'https://www.youtube.com/watch?v=zEzovM5jT-k&ab_channel=AmirRajan'
+ end
+ end
+
+ def process_audio_queue args
+ to_queue = args.state.audio_queue.find_all { |v| v[:queue_at] <= args.tick_count }
+ args.state.audio_queue -= to_queue
+
+ to_queue.each do |a|
+ args.audio[a[:id]] = a
+ end
+
+ args.audio.each do |k, v|
+ if v[:decay_rate]
+ v[:gain] -= v[:decay_rate]
+ end
+ end
+
+ sounds_to_stop = args.audio.find_all do |k, v|
+ v[:stop_at] && args.state.tick_count >= v[:stop_at]
+ end
+
+ sounds_to_stop.each do |(k, v)|
+ args.audio.delete k
+ end
+ end
+
+ def graph_sine_wave args, sine_wave, frequency
+ if args.state.tick_count != args.state.graphed_at
+ args.outputs.static_lines.clear
+ args.outputs.static_sprites.clear
+ end
+
+ r, g, b = frequency.to_i % 80, frequency.to_i % 128, frequency.to_i % 255
+ center_row = args.layout.rect(row: 5, col: 9)
+ x_scale = 20
+ y_scale = 100
+ max_points = 20
+
+ points = sine_wave
+ if sine_wave.length > max_points
+ resolution = sine_wave.length.idiv max_points
+ points = sine_wave.find_all
+ .with_index { |y, i| i % resolution == 0 }
+ end
+
+ args.outputs.static_lines << points.map_with_index do |y, x|
+ next_y = points[x + 1]
+
+ if next_y
+ {
+ x: center_row.x + (x * x_scale),
+ y: center_row.y + center_row.h.half + y_scale * y,
+ x2: center_row.x + ((x + 1) * x_scale),
+ y2: center_row.y + center_row.h.half + y_scale * next_y,
+ r: r,
+ g: g,
+ b: b
+ }
+ end
+ end
+
+ args.outputs.static_sprites << points.map_with_index do |y, x|
+ {
+ x: (center_row.x + (x * x_scale)) - 1,
+ y: (center_row.y + center_row.h.half + y_scale * y) - 1,
+ w: 2,
+ h: 2,
+ path: 'sprites/square-black.png'
+ }
+ end
+
+ args.state.graphed_at = args.state.tick_count
+ end
+
+ def defaults_period_sine_wave_for
+ { frequency: 440, sample_rate: 48000 }
+ end
+
+ def sine_wave_for opts = { }
+ opts = defaults_period_sine_wave_for.merge opts
+ frequency = opts[:frequency]
+ sample_rate = opts[:sample_rate]
+ period_size = (sample_rate.fdiv frequency).ceil
+ period_size.map_with_index do |i|
+ Math::sin((2.0 * Math::PI) / (sample_rate.to_f / frequency.to_f) * i)
+ end.to_a
+ end
+
+ def generate_audio_data sine_wave, sample_rate
+ sample_size = (sample_rate.fdiv (1000.fdiv 60)).ceil
+ copy_count = (sample_size.fdiv sine_wave.length).ceil
+ sine_wave * copy_count
+ end
+
+ def defaults_queue_sine_wave
+ { frequency: 440, duration: 60, gain: 1.0, fade_out: false, queue_in: 0 }
+ end
+
+ def queue_sine_wave args, opts = { }
+ opts = defaults_queue_sine_wave.merge opts
+ decay_rate = 0
+ decay_rate = 1.fdiv(opts[:duration]) * opts[:gain] if opts[:fade_out]
+ frequency = opts[:frequency]
+ sample_rate = 48000
+
+ audio_state = {
+ id: (new_id! args),
+ frequency: frequency,
+ sample_rate: 48000,
+ stop_at: args.tick_count + opts[:queue_in] + opts[:duration],
+ gain: opts[:gain].to_f,
+ queue_at: args.state.tick_count + opts[:queue_in],
+ decay_rate: decay_rate,
+ pitch: 1.0,
+ looping: true,
+ paused: false
+ }
+
+ sine_wave = sine_wave_for frequency: frequency, sample_rate: sample_rate
+ args.state.sine_waves[frequency] ||= sine_wave_for frequency: frequency, sample_rate: sample_rate
+
+ proc = lambda do
+ generate_audio_data args.state.sine_waves[frequency], sample_rate
+ end
+
+ audio_state[:input] = [1, sample_rate, proc]
+ graph_sine_wave args, sine_wave, frequency
+ args.state.audio_queue << audio_state
+ end
+
+ def defaults_queue_bell
+ { frequency: 440, duration: 1.seconds, queue_in: 0 }
+ end
+
+ def queue_bell args, opts = {}
+ (bell_to_sine_waves (defaults_queue_bell.merge opts)).each { |b| queue_sine_wave args, b }
+ end
+
+ def bell_harmonics
+ [
+ { frequency_ratio: 0.5, duration_ratio: 1.00 },
+ { frequency_ratio: 1.0, duration_ratio: 0.80 },
+ { frequency_ratio: 2.0, duration_ratio: 0.60 },
+ { frequency_ratio: 3.0, duration_ratio: 0.40 },
+ { frequency_ratio: 4.2, duration_ratio: 0.25 },
+ { frequency_ratio: 5.4, duration_ratio: 0.20 },
+ { frequency_ratio: 6.8, duration_ratio: 0.15 }
+ ]
+ end
+
+ def bell_to_sine_waves opts
+ bell_harmonics.map do |b|
+ {
+ frequency: opts[:frequency] * b[:frequency_ratio],
+ duration: opts[:duration] * b[:duration_ratio],
+ queue_in: opts[:queue_in],
+ gain: (1.fdiv bell_harmonics.length),
+ fade_out: true
+ }
+ end
+ end
+
+ def defaults_frequency_for
+ { note: :a, octave: 5, sharp: false, flat: false }
+ end
+
+ def frequency_for opts = {}
+ opts = defaults_frequency_for.merge opts
+ octave_offset_multiplier = opts[:octave] - 5
+ note = note_frequencies_octave_5[opts[:note]]
+ if octave_offset_multiplier < 0
+ note = note * 1 / (octave_offset_multiplier.abs + 1)
+ elsif octave_offset_multiplier > 0
+ note = note * (octave_offset_multiplier.abs + 1) / 1
+ end
+ note
+ end
+
+ def note_frequencies_octave_5
+ {
+ a: 440.0,
+ a_sharp: 466.16, b_flat: 466.16,
+ b: 493.88,
+ c: 523.25,
+ c_sharp: 554.37, d_flat: 587.33,
+ d: 587.33,
+ d_sharp: 622.25, e_flat: 659.25,
+ e: 659.25,
+ f: 698.25,
+ f_sharp: 739.99, g_flat: 739.99,
+ g: 783.99,
+ g_sharp: 830.61, a_flat: 830.61
+ }
+ end
+
+ def new_id! args
+ args.state.audio_id ||= 0
+ args.state.audio_id += 1
+ end
+
+ def button args, opts
+ button_def = opts.merge rect: (args.layout.rect (opts.merge w: 2, h: 1))
+
+ button_def[:border] = button_def[:rect].merge r: 0, g: 0, b: 0
+
+ font_size_enum = args.layout.font_relative_size_enum 0
+ label_offset_x = 4
+ label_offset_y = button_def[:rect].h.half + button_def[:rect].h.idiv(4)
+
+ button_def[:label] = button_def[:rect].merge text: opts[:text],
+ size_enum: font_size_enum,
+ x: button_def[:rect].x + label_offset_x,
+ y: button_def[:rect].y + label_offset_y
+
+ button_def
+ end
+
+ $gtk.reset
+
+#+end_src
+
* Input Basics - Keyboard - main.rb
#+begin_src ruby
# ./samples/02_input_basics/01_keyboard/app/main.rb
@@ -4040,6 +4585,54 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
+* Input Basics - Touch - main.rb
+#+begin_src ruby
+ # ./samples/02_input_basics/06_touch/app/main.rb
+ def tick args
+ args.outputs.background_color = [ 0, 0, 0 ]
+ args.outputs.primitives << [640, 700, "Touch your screen.", 5, 1, 255, 255, 255].label
+
+ # If you don't want to get fancy, you can just look for finger_one
+ # (and _two, if you like), which are assigned in the order new touches hit
+ # the screen. If not nil, they are touching right now, and are just
+ # references to specific items in the args.input.touch hash.
+ # If finger_one lifts off, it will become nil, but finger_two, if it was
+ # touching, remains until it also lifts off. When all fingers lift off, the
+ # the next new touch will be finger_one again, but until then, new touches
+ # don't fill in earlier slots.
+ if !args.inputs.finger_one.nil?
+ args.outputs.primitives << [640, 650, "Finger #1 is touching at (#{args.inputs.finger_one.x}, #{args.inputs.finger_one.y}).", 5, 1, 255, 255, 255].label
+ end
+ if !args.inputs.finger_two.nil?
+ args.outputs.primitives << [640, 600, "Finger #2 is touching at (#{args.inputs.finger_two.x}, #{args.inputs.finger_two.y}).", 5, 1, 255, 255, 255].label
+ end
+
+ # Here's the more flexible interface: this will report as many simultaneous
+ # touches as the system can handle, but it's a little more effort to track
+ # them. Each item in the args.input.touch hash has a unique key (an
+ # incrementing integer) that exists until the finger lifts off. You can
+ # tell which order the touches happened globally by the key value, or
+ # by the touch[id].touch_order field, which resets to zero each time all
+ # touches have lifted.
+
+ args.state.colors ||= [
+ 0xFF0000, 0x00FF00, 0x1010FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF
+ ]
+
+ size = 100
+ args.inputs.touch.each { |k,v|
+ color = args.state.colors[v.touch_order % 7]
+ r = (color & 0xFF0000) >> 16
+ g = (color & 0x00FF00) >> 8
+ b = (color & 0x0000FF)
+ args.outputs.primitives << [v.x - (size / 2), v.y + (size / 2), size, size, r, g, b, 255].solid
+ args.outputs.primitives << [v.x, v.y + size, k.to_s, 0, 1, 0, 0, 0].label
+ }
+ end
+
+
+#+end_src
+
* Rendering Sprites - Animation Using Separate Pngs - main.rb
#+begin_src ruby
# ./samples/03_rendering_sprites/01_animation_using_separate_pngs/app/main.rb
@@ -8587,6 +9180,53 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
+* Advanced Rendering - Pixel Arrays - main.rb
+#+begin_src ruby
+ # ./samples/07_advanced_rendering/06_pixel_arrays/app/main.rb
+ $gtk.reset
+
+ def tick args
+ args.state.posinc ||= 1
+ args.state.pos ||= 0
+ args.state.rotation ||= 0
+
+ dimension = 10 # keep it small and let the GPU scale it when rendering the sprite.
+
+ # Set up our "scanner" pixel array and fill it with black pixels.
+ args.pixel_array(:scanner).width = dimension
+ args.pixel_array(:scanner).height = dimension
+ args.pixel_array(:scanner).pixels.fill(0xFF000000, 0, dimension * dimension) # black, full alpha
+
+ # Draw a green line that bounces up and down the sprite.
+ args.pixel_array(:scanner).pixels.fill(0xFF00FF00, dimension * args.state.pos, dimension) # green, full alpha
+
+ # Adjust position for next frame.
+ args.state.pos += args.state.posinc
+ if args.state.posinc > 0 && args.state.pos >= dimension
+ args.state.posinc = -1
+ args.state.pos = dimension - 1
+ elsif args.state.posinc < 0 && args.state.pos < 0
+ args.state.posinc = 1
+ args.state.pos = 1
+ end
+
+ # New/changed pixel arrays get uploaded to the GPU before we render
+ # anything. At that point, they can be scaled, rotated, and otherwise
+ # used like any other sprite.
+ w = 100
+ h = 100
+ x = (1280 - w) / 2
+ y = (720 - h) / 2
+ args.outputs.background_color = [64, 0, 128]
+ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite
+ args.state.rotation += 1
+
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+ end
+
+
+#+end_src
+
* Tweening Lerping Easing Functions - Easing Functions - main.rb
#+begin_src ruby
# ./samples/08_tweening_lerping_easing_functions/01_easing_functions/app/main.rb
@@ -9840,12 +10480,12 @@ Follows is a source code listing for all files that have been open sourced. This
GTK::Entity.__reset_id__!
args.state.player_one = "test"
result = args.gtk.serialize_state args.state
- assert.equal! result, "{:entity_id=>3, :tick_count=>-1, :player_one=>\"test\"}"
+ assert.equal! result, "{:entity_id=>3, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>\"test\"}"
GTK::Entity.__reset_id__!
args.gtk.write_file 'state.txt', ''
result = args.gtk.serialize_state 'state.txt', args.state
- assert.equal! result, "{:entity_id=>3, :tick_count=>-1, :player_one=>\"test\"}"
+ assert.equal! result, "{:entity_id=>3, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>\"test\"}"
end
def test_deserialize args, assert
@@ -9876,8 +10516,9 @@ Follows is a source code listing for all files that have been open sourced. This
args.state.player_two = args.state.new_entity_strict(:player_strict, name: "Ken")
serialized_state = args.gtk.serialize_state args.state
- assert.equal! serialized_state, '{:entity_id=>1, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>3, :entity_name=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :name=>"Ken"}}'
+ assert.equal! serialized_state, '{:entity_id=>1, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_keys_by_ref=>{}, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>3, :entity_name=>:player_strict, :entity_type=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :entity_keys_by_ref=>{:entity_type=>:entity_name, :global_created_at_elapsed=>:created_at}, :name=>"Ken"}}'
+ GTK::Entity.__reset_id__!
deserialize_state = args.gtk.deserialize_state serialized_state
assert.equal! args.state.player_one.name, deserialize_state.player_one.name
@@ -9893,8 +10534,9 @@ Follows is a source code listing for all files that have been open sourced. This
args.state.player_two = args.state.new_entity_strict(:player_strict, name: "Ken", blood_type: nil)
serialized_state = args.gtk.serialize_state args.state
- assert.equal! serialized_state, '{:entity_id=>3, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>3, :entity_name=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :name=>"Ken", :blood_type=>nil}}'
+ assert.equal! serialized_state, '{:entity_id=>9, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_keys_by_ref=>{}, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>2, :entity_name=>:player_strict, :entity_type=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :entity_keys_by_ref=>{:entity_type=>:entity_name, :global_created_at_elapsed=>:created_at}, :name=>"Ken", :blood_type=>nil}}'
+ GTK::Entity.__reset_id__!
deserialized_state = args.gtk.deserialize_state serialized_state
assert.equal! args.state.player_one.name, deserialized_state.player_one.name
@@ -9915,12 +10557,41 @@ Follows is a source code listing for all files that have been open sourced. This
args.state.enemy = args.state.new_entity_strict(:enemy, name: "Bison", other_property: 'extra mean')
serialized_state = args.gtk.serialize_state args.state
+
+ GTK::Entity.__reset_id__!
deserialized_state = args.gtk.deserialize_state serialized_state
assert.equal! deserialized_state.player.name, "Ryu"
assert.equal! deserialized_state.enemy.other_property, "extra mean"
end
+ def test_by_reference_state args, assert
+ GTK::Entity.__reset_id__!
+ args.state.a = { name: "Jane Doe" }
+ args.state.b = args.state.a
+ assert.equal! args.state.a.object_id, args.state.b.object_id
+ serialized_state = args.gtk.serialize_state args.state
+
+ GTK::Entity.__reset_id__!
+ deserialized_state = args.gtk.deserialize_state serialized_state
+ assert.equal! deserialized_state.a.object_id, deserialized_state.b.object_id
+ end
+
+ def test_by_reference_state_strict_entities args, assert
+ GTK::Entity.__reset_id__!
+ args.state.a = { name: "Jane Doe" }
+ args.state.strict_entity = args.state.new_entity_strict(:couple) do |e|
+ e.one = args.state.new_entity_strict(:person, name: "Jane")
+ e.two = e.one
+ end
+ assert.equal! args.state.strict_entity.one, args.state.strict_entity.two
+ serialized_state = args.gtk.serialize_state args.state
+
+ GTK::Entity.__reset_id__!
+ deserialized_state = args.gtk.deserialize_state serialized_state
+ assert.equal! deserialized_state.strict_entity.one, deserialized_state.strict_entity.two
+ end
+
$tests.start
#+end_src
@@ -10113,6 +10784,59 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
+* 12 C Extensions - Intermediate - main.rb
+#+begin_src ruby
+ # ./samples/12_c_extensions/02_intermediate/app/main.rb
+ $gtk.ffi_misc.gtk_dlopen("ext")
+ include FFI::RE
+
+ def split_words(input)
+ words = []
+ last = IntPointer.new
+ re = re_compile("\\w+")
+ first = re_matchp(re, input, last)
+ while first != -1
+ words << input.slice(first, last.value)
+ input = input.slice(last.value + first, input.length)
+ first = re_matchp(re, input, last)
+ end
+ words
+ end
+
+ def tick args
+ args.outputs.labels << [640, 500, split_words("hello, dragonriders!").join(' '), 5, 1]
+ end
+
+#+end_src
+
+* 12 C Extensions - Native Pixel Arrays - main.rb
+#+begin_src ruby
+ # ./samples/12_c_extensions/03_native_pixel_arrays/app/main.rb
+ $gtk.ffi_misc.gtk_dlopen("ext")
+ include FFI::CExt
+
+ def tick args
+ args.state.rotation ||= 0
+
+ update_scanner_texture # this calls into a C extension!
+
+ # New/changed pixel arrays get uploaded to the GPU before we render
+ # anything. At that point, they can be scaled, rotated, and otherwise
+ # used like any other sprite.
+ w = 100
+ h = 100
+ x = (1280 - w) / 2
+ y = (720 - h) / 2
+ args.outputs.background_color = [64, 0, 128]
+ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite
+ args.state.rotation += 1
+
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+ end
+
+
+#+end_src
+
* 3d - 3d Cube - main.rb
#+begin_src ruby
# ./samples/99_genre_3d/3d_cube/app/main.rb
@@ -15792,29 +16516,6 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
-* Platformer - Gorillas Basic - repl.rb
-#+begin_src ruby
- # ./samples/99_genre_platformer/gorillas_basic/app/repl.rb
- begin
- if $gtk.args.state.current_turn == :player_1_angle
- $gtk.args.state.player_1_angle = "#{60 + 10.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- $gtk.args.state.player_1_velocity = "#{30 + 20.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- elsif $gtk.args.state.current_turn == :player_2_angle
- $gtk.args.state.player_2_angle = "#{60 + 10.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- $gtk.args.state.player_2_velocity = "#{30 + 20.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- else
- $you_so_basic_gorillas.input_execute_turn
- end
- rescue Exception => e
- puts e
- end
-
-#+end_src
-
* Platformer - Gorillas Basic - tests.rb
#+begin_src ruby
# ./samples/99_genre_platformer/gorillas_basic/app/tests.rb
@@ -19222,13 +19923,6 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
-* Rpg Narrative - Return Of Serenity - repl.rb
-#+begin_src ruby
- # ./samples/99_genre_rpg_narrative/return_of_serenity/app/repl.rb
- puts $gtk.args.state.current_scene
-
-#+end_src
-
* Rpg Narrative - Return Of Serenity - require.rb
#+begin_src ruby
# ./samples/99_genre_rpg_narrative/return_of_serenity/app/require.rb
@@ -22026,6 +22720,11 @@ Follows is a source code listing for all files that have been open sourced. This
# @return [Outputs]
attr_accessor :outputs
+ # Contains the means to interact with the audio mixer.
+ #
+ # @return [Hash]
+ attr_accessor :audio
+
# Contains display size information to assist in positioning things on the screen.
#
# @return [Grid]
@@ -22056,9 +22755,12 @@ Follows is a source code listing for all files that have been open sourced. This
attr_accessor :wizards
+ attr_accessor :layout
+
def initialize runtime, recording
@inputs = Inputs.new
@outputs = Outputs.new args: self
+ @audio = {}
@passes = []
@state = OpenEntity.new
@state.tick_count = -1
@@ -22066,9 +22768,11 @@ Follows is a source code listing for all files that have been open sourced. This
@recording = recording
@grid = Grid.new runtime
@render_targets = {}
+ @pixel_arrays = {}
@all_tests = []
@geometry = GTK::Geometry
@wizards = Wizards.new
+ @layout = GTK::Layout.new @grid.w, @grid.h
end
@@ -22097,6 +22801,26 @@ Follows is a source code listing for all files that have been open sourced. This
[grid, inputs, state, outputs, runtime, passes]
end
+ def clear_pixel_arrays
+ pixel_arrays_clear
+ end
+
+ def pixel_arrays_clear
+ @pixel_arrays = {}
+ end
+
+ def pixel_arrays
+ @pixel_arrays
+ end
+
+ def pixel_array name
+ name = name.to_s
+ if !@pixel_arrays[name]
+ @pixel_arrays[name] = PixelArray.new
+ end
+ @pixel_arrays[name]
+ end
+
def clear_render_targets
render_targets_clear
end
@@ -22305,7 +23029,7 @@ Follows is a source code listing for all files that have been open sourced. This
@assertion_performed = true
if actual != expected
actual_string = "#{actual}#{actual.nil? ? " (nil) " : " " }".strip
- message = "actual:\n#{actual_string} did not equal\nexpected:\n#{expected}.\n#{message}"
+ message = "actual:\n#{actual_string}\n\ndid not equal\n\nexpected:\n#{expected}.\n#{message}"
raise message
end
nil
@@ -22376,6 +23100,10 @@ Follows is a source code listing for all files that have been open sourced. This
args.passes
end
+ def pixel_arrays
+ args.pixel_arrays
+ end
+
def geometry
args.geometry
end
@@ -22457,6 +23185,8 @@ Follows is a source code listing for all files that have been open sourced. This
module GTK
class Console
+ include ConsoleDeprecated
+
attr_accessor :show_reason, :log, :logo, :background_color,
:text_color, :animation_duration,
:max_log_lines, :max_history, :log,
@@ -22527,7 +23257,7 @@ Follows is a source code listing for all files that have been open sourced. This
@disabled = false
end
- def addsprite obj
+ def add_sprite obj
@log_invocation_count += 1
obj[:id] ||= "id_#{obj[:path]}_#{Time.now.to_i}".to_sym
@@ -22547,14 +23277,14 @@ Follows is a source code listing for all files that have been open sourced. This
def add_primitive obj
if obj.is_a? Hash
- addsprite obj
+ add_sprite obj
else
- addtext obj
+ add_text obj
end
nil
end
- def addtext obj
+ def add_text obj
@last_log_lines_count ||= 1
@log_invocation_count += 1
@@ -22678,12 +23408,12 @@ Follows is a source code listing for all files that have been open sourced. This
@toasted_at = Kernel.global_tick_count
log_once_info :perma_toast_tip, "Use console.perma_toast to show the toast for longer."
dwim_duration = 5.seconds
- addtext "* toast :#{id}"
+ add_text "* toast :#{id}"
puts "* TOAST: :#{id}"
messages.each do |message|
lines = message.to_s.wrapped_lines(self.console_text_width)
dwim_duration += lines.length.seconds
- addtext "** #{message}"
+ add_text "** #{message}"
puts "** #{message}"
end
show :toast
@@ -22901,6 +23631,10 @@ Follows is a source code listing for all files that have been open sourced. This
@command_history_index -= 1
self.current_input_str = @command_history[@command_history_index].dup
end
+ elsif args.inputs.keyboard.key_down.left
+ prompt.move_cursor_left
+ elsif args.inputs.keyboard.key_down.right
+ prompt.move_cursor_right
elsif inputs_scroll_up_full? args
scroll_up_full
elsif inputs_scroll_down_full? args
@@ -23468,23 +24202,53 @@ Follows is a source code listing for all files that have been open sourced. This
@cursor_color = Color.new [187, 21, 6]
@console_text_width = console_text_width
+ @cursor_position = 0
+ update_cursor_position_px
+
@last_autocomplete_prefix = nil
@next_candidate_index = 0
end
+ def update_cursor_position_px
+ @cursor_position_px = ($gtk.calcstringbox (@prompt + @current_input_str[0...@cursor_position]), @font_style.size_enum, @font_style.font).x
+ end
+
+ def current_input_str=(str)
+ @current_input_str = str
+ @cursor_position = str.length
+ end
+
def <<(str)
- @current_input_str << str
+ @current_input_str = @current_input_str[0...@cursor_position] + str + @current_input_str[@cursor_position..-1]
+ @cursor_position += str.length
+ update_cursor_position_px
@current_input_changed_at = Kernel.global_tick_count
reset_autocomplete
end
def backspace
- @current_input_str.chop!
+ return if current_input_str.length.zero? || @cursor_position.zero?
+
+ @current_input_str = @current_input_str[0...(@cursor_position - 1)] + @current_input_str[@cursor_position..-1]
+ @cursor_position -= 1
+ update_cursor_position_px
reset_autocomplete
end
+ def move_cursor_left
+ @cursor_position -= 1 if @cursor_position > 0
+ update_cursor_position_px
+ end
+
+ def move_cursor_right
+ @cursor_position += 1 if @cursor_position < current_input_str.length
+ update_cursor_position_px
+ end
+
def clear
@current_input_str = ''
+ @cursor_position = 0
+ update_cursor_position_px
reset_autocomplete
end
@@ -23503,7 +24267,10 @@ Follows is a source code listing for all files that have been open sourced. This
@next_candidate_index += 1
@next_candidate_index = 0 if @next_candidate_index >= candidates.length
self.current_input_str = display_autocomplete_candidate(candidate)
+ update_cursor_position_px
end
+ rescue Exception => e
+ puts "* BUG: Tab autocompletion failed. Let us know about this.\n#{e}"
end
def pretty_print_strings_as_table items
@@ -23562,7 +24329,21 @@ Follows is a source code listing for all files that have been open sourced. This
def render(args, x:, y:)
args.outputs.reserved << font_style.label(x: x, y: y, text: "#{@prompt}#{current_input_str}", color: @text_color)
- args.outputs.reserved << font_style.label(x: x - 2, y: y + 3, text: (" " * (@prompt.length + current_input_str.length)) + "|", color: @cursor_color)
+ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 0.5,
+ y: y + 5,
+ x2: x + @cursor_position_px + 0.5,
+ y2: y + @font_style.letter_size.y + 5)
+
+ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 1,
+ y: y + 5,
+ x2: x + @cursor_position_px + 1,
+ y2: y + @font_style.letter_size.y + 5)
+
+ # debugging rectangle for string
+ # args.outputs.reserved << (@cursor_color.to_h.merge x: x,
+ # y: y + 5,
+ # w: @cursor_position_px,
+ # h: @font_style.letter_size.y).border
end
def tick
@@ -25525,6 +26306,59 @@ Follows is a source code listing for all files that have been open sourced. This
alias_method :inspect, :to_s
end
+
+ # Provides access to multitouch input
+ #
+ # @gtk
+ class FingerTouch
+
+ # @gtk
+ attr_accessor :moved,
+ :moved_at,
+ :global_moved_at,
+ :touch_order,
+ :x, :y
+
+ def initialize
+ @moved = false
+ @moved_at = 0
+ @global_moved_at = 0
+ @touch_order = 0
+ @x = 0
+ @y = 0
+ end
+
+ def point
+ [@x, @y].point
+ end
+
+ def inside_rect? rect
+ point.inside_rect? rect
+ end
+
+ def inside_circle? center, radius
+ point.point_inside_circle? center, radius
+ end
+
+ alias_method :position, :point
+
+ def serialize
+ result = {}
+ result[:x] = @x
+ result[:y] = @y
+ result[:touch_order] = @touch_order
+ result[:moved] = @moved
+ result[:moved_at] = @moved_at
+
+ result
+ end
+
+ def to_s
+ serialize.to_s
+ end
+
+ alias_method :inspect, :to_s
+ end
end
module GTK
@@ -25545,6 +26379,11 @@ Follows is a source code listing for all files that have been open sourced. This
# @gtk
attr_reader :mouse
+ # @return {FingerTouch}
+ # @gtk
+ attr_reader :touch
+ attr_accessor :finger_one, :finger_two
+
# @gtk
attr_accessor :text, :history
@@ -25552,6 +26391,9 @@ Follows is a source code listing for all files that have been open sourced. This
@controllers = [Controller.new, Controller.new]
@keyboard = Keyboard.new
@mouse = Mouse.new
+ @touch = {}
+ @finger_one = nil
+ @finger_two = nil
@text = []
end
@@ -25627,6 +26469,9 @@ Follows is a source code listing for all files that have been open sourced. This
@mouse.clear
@keyboard.clear
@controllers.each(&:clear)
+ @touch.clear
+ @finger_one = nil
+ @finger_two = nil
end
# @return [Hash]
@@ -25644,6 +26489,1388 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
+* ios_wizard.rb
+#+begin_src ruby
+ # ./dragon/ios_wizard.rb
+ # Copyright 2019 DragonRuby LLC
+ # MIT License
+ # ios_wizard.rb has been released under MIT (*only this file*).
+
+ class WizardException < Exception
+ attr_accessor :console_primitives
+
+ def initialize *console_primitives
+ @console_primitives = console_primitives
+ end
+ end
+
+ class IOSWizard
+ def initialize
+ @doctor_executed_at = 0
+ end
+
+ def relative_path
+ (File.dirname $gtk.binary_path)
+ end
+
+ def steps
+ [
+ :check_for_xcode,
+ :check_for_brew,
+ :check_for_certs,
+ :check_for_device,
+ :check_for_dev_profile,
+ :determine_app_name,
+ :determine_app_id,
+ :blow_away_temp,
+ :stage_app,
+ :write_info_plist,
+ :write_entitlements_plist,
+ :code_sign,
+ :create_ipa,
+ :deploy,
+ ]
+ end
+
+ def get_reserved_sprite png
+ sprite_path = ".dragonruby/sprites/wizards/ios/#{png}"
+
+ if !$gtk.ivar :rcb_release_mode
+ sprite_path = "deploy_template/#{sprite_path}"
+ $gtk.reset_sprite sprite_path
+ end
+
+ if !$gtk.read_file sprite_path
+ log_error "png #{png} not found."
+ end
+
+ sprite_path
+ end
+
+ def start
+ @certificate_name = nil
+ init_wizard_status
+ log_info "Starting iOS Wizard so we can deploy to your device."
+ @start_at = Kernel.global_tick_count
+ steps.each do |m|
+ begin
+ result = (send m) || :success if @wizard_status[m][:result] != :success
+ @wizard_status[m][:result] = result
+ rescue Exception => e
+ if e.is_a? WizardException
+ $console.log.clear
+ $console.archived_log.clear
+ log "=" * $console.console_text_width
+ e.console_primitives.each do |p|
+ $console.add_primitive p
+ end
+ log "=" * $console.console_text_width
+ else
+ log_error "Step #{m} failed."
+ log_error e.to_s
+ end
+
+ $console.set_command "$wizards.ios.start"
+
+ break
+ end
+ end
+
+ return nil
+ end
+
+ def always_fail
+ return false if $gtk.ivar :rcb_release_mode
+ return true
+ end
+
+ def check_for_xcode
+ if !cli_app_exist?(xcodebuild_cli_app)
+ raise WizardException.new(
+ "* You need Xcode to use $wizards.ios.start.",
+ { w: 75, h: 75, path: get_reserved_sprite("xcode.png") },
+ "** 1. Go to http://developer.apple.com and register.",
+ "** 2. Download Xcode 11.3+ from http://developer.apple.com/downloads.",
+ " NOTE: DO NOT install Xcode from the App Store. Use the link above.",
+ { w: 700, h: 359, path: get_reserved_sprite("xcode-downloads.png") },
+ "** 3. After installing. Open up Xcode to accept the EULA."
+ )
+ end
+ end
+
+ def check_for_brew
+ if !cli_app_exist?('brew')
+ raise WizardException.new(
+ "* You need to install Brew.",
+ { w: 700, h: 388, path: get_reserved_sprite("brew.png") },
+ "** 1. Go to http://brew.sh.",
+ "** 2. Copy the command that starts with `/bin/bash -c` on the site.",
+ "** 3. Open Terminal and run the command you copied from the website.",
+ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },
+ )
+ end
+ end
+
+ def init_wizard_status
+ @wizard_status = {}
+ steps.each do |m|
+ @wizard_status[m] = { result: :not_started }
+ end
+
+ previous_step = nil
+ next_step = nil
+ steps.each_cons(2) do |current_step, next_step|
+ @wizard_status[current_step][:next_step] = next_step
+ end
+
+ steps.reverse.each_cons(2) do |current_step, previous_step|
+ @wizard_status[current_step][:previous_step] = previous_step
+ end
+ end
+
+ def restart
+ init_wizard_status
+ start
+ end
+
+ def check_for_dev_profile
+ if !($gtk.read_file 'profiles/development.mobileprovision')
+ $gtk.system "mkdir -p #{relative_path}/profiles"
+ $gtk.system "open #{relative_path}/profiles"
+ $gtk.system "echo Download the mobile provisioning profile and place it here with the name development.mobileprovision > #{relative_path}/profiles/README.txt"
+ raise WizardException.new(
+ "* I didn't find a mobile provision.",
+ "** 1. Go to http://developer.apple.com and click \"Certificates, IDs & Profiles\".",
+ "** 2. Add an App Identifier.",
+ "** 3. Select the App IDs option from the list.",
+ { w: 700, h: 75, path: get_reserved_sprite("identifiers.png") },
+ "** 4. Add your Device next. You can use idevice_id -l to get the UUID of your device.",
+ { w: 365, h: 69, path: get_reserved_sprite("device-link.png") },
+ "** 5. Create a Profile. Associate your certs, id, and device.",
+ { w: 300, h: 122, path: get_reserved_sprite("profiles.png") },
+ "** 6. Download the mobile provision and save it to 'profiles/development.mobileprovision'.",
+ { w: 200, h: 124, path: get_reserved_sprite("profiles-folder.png") },
+ )
+ end
+ end
+
+ def determine_app_name
+ @app_name = dev_profile_xml[:children].first[:children].first[:children][1][:children].first[:data]
+ log_info "App name is: #{@app_name}."
+ end
+
+ def dev_profile_xml
+ xml = $gtk.read_file 'profiles/development.mobileprovision'
+ scrubbed = xml.each_line.map do |l|
+ if l.strip.start_with? "<"
+ if l.start_with? '</plist>'
+ '</plist>'
+ elsif l.include? "Apple Inc."
+ nil
+ elsif l.include? '<data>'
+ nil
+ else
+ l
+ end
+ else
+ nil
+ end
+ end.reject { |l| !l }.join
+ $gtk.parse_xml scrubbed
+ end
+
+ def determine_app_id
+ # lol
+ @app_id = dev_profile_xml[:children].first[:children].first[:children][13][:children][1][:children].first[:data]
+ log_info "App Identifier is set to : #{@app_id}"
+ end
+
+ def set_app_name name
+ @app_name = name
+ start
+ end
+
+ def set_dev_profile path
+ if !$gtk.read_file path
+ log_error "I couldn't find a development profile at #{path}."
+ ask_for_dev_profile
+ else
+ @dev_profile_path = path
+ start
+ end
+ end
+
+ def blow_away_temp
+ sh "rm -rf #{tmp_directory}"
+ end
+
+ def stage_app
+ log_info "Staging."
+ sh "mkdir -p #{tmp_directory}"
+ sh "cp -R #{relative_path}/dragonruby-ios.app \"#{tmp_directory}/#{@app_name}.app\""
+ end
+
+ def set_app_id id
+ log_info = "App Id set to: #{id}"
+ @app_id = id
+ start
+ end
+
+ def check_for_device
+ log_info "Looking for device."
+
+ if !cli_app_exist?(idevice_id_cli_app)
+ raise WizardException.new(
+ "* It doesn't look like you have the libimobiledevice iOS protocol library installed.",
+ "** 1. Open Terminal.",
+ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },
+ "** 2. Run: `brew install libimobiledevice`.",
+ { w: 500, h: 93, path: get_reserved_sprite("brew-install-libimobiledevice.png") },
+ )
+ end
+
+ if connected_devices.length == 0
+ raise WizardException.new("* I couldn't find any connected devices. Connect your iOS device to your Mac and try again.")
+ end
+
+ @device_id = connected_devices.first
+ log_info "I will be using device with UUID #{@device_id}"
+ end
+
+ def check_for_certs
+ log_info "Attempting to find certificates on your computer."
+
+ if !cli_app_exist?(security_cli_app)
+ raise WizardException.new(
+ "* It doesn't look like you have #{security_cli_app}.",
+ "** 1. Open Disk Utility and run First Aid.",
+ { w: 700, h: 148, path: get_reserved_sprite("disk-utility.png") },
+ )
+ end
+
+ if valid_certs.length == 0
+ raise WizardException.new(
+ "* It doesn't look like you have any valid certs installed.",
+ "** 1. Open Xcode.",
+ "** 2. Log into your developer account. Xcode -> Preferences -> Accounts.",
+ { w: 700, h: 98, path: get_reserved_sprite("login-xcode.png") },
+ "** 3. After loggin in, select Manage Certificates...",
+ { w: 700, h: 115, path: get_reserved_sprite("manage-certificates.png") },
+ "** 4. Add a certificate for Apple Development.",
+ { w: 700, h: 217, path: get_reserved_sprite("add-cert.png") },
+ )
+ raise "You do not have any Apple development certs on this computer."
+ end
+
+ @certificate_name = valid_certs.first[:name]
+ log_info "I will be using '#{@certificate_name}' to deploy to your device."
+ end
+
+ def idevice_id_cli_app
+ "idevice_id"
+ end
+
+ def security_cli_app
+ "/usr/bin/security"
+ end
+
+ def xcodebuild_cli_app
+ "xcodebuild"
+ end
+
+ def valid_certs
+ certs = sh("#{security_cli_app} -q find-identity -p codesigning -v").each_line.map do |l|
+ if l.include?(")") && !l.include?("Developer ID") && l.include?("Development")
+ l.strip
+ else
+ nil
+ end
+ end.reject_nil.map do |l|
+ number, id, name = l.split(' ', 3)
+ name = name.gsub("\"", "") if name
+ {
+ number: 1,
+ id: id,
+ name: name
+ }
+ end
+ end
+
+ def connected_devices
+ sh("idevice_id -l").strip.each_line.map do |l|
+ l.strip
+ end.reject { |l| l.length == 0 }
+ end
+
+ def cli_app_exist? app
+ `which #{app}`.strip.length != 0
+ end
+
+ def write_entitlements_plist
+ entitlement_plist_string = <<-XML
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+ <plist version="1.0">
+ <dict>
+ <key>application-identifier</key>
+ <string>:app_id</string>
+ <key>get-task-allow</key>
+ <true/>
+ </dict>
+ </plist>
+ XML
+
+ log_info "Creating Entitlements.plist"
+
+ $gtk.write_file_root "tmp/ios/Entitlements.plist", entitlement_plist_string.gsub(":app_id", @app_id).strip
+
+ sh "/usr/bin/plutil -convert binary1 \"#{tmp_directory}/Entitlements.plist\""
+ sh "/usr/bin/plutil -convert xml1 \"#{tmp_directory}/Entitlements.plist\""
+
+ @entitlement_plist_written = true
+ end
+
+ def code_sign
+ sh "cp #{@dev_profile_path} \"#{app_path}/embedded.mobileprovision\""
+
+ log_info "Signing app with #{@certificate_name}."
+
+ sh "/usr/bin/plutil -convert binary1 \"#{app_path}/Info.plist\""
+
+ sh "CODESIGN_ALLOCATE=\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate\" /usr/bin/codesign -f -s \"#{@certificate_name}\" --entitlements #{tmp_directory}/Entitlements.plist \"#{tmp_directory}/#{@app_name}.app\""
+
+ @code_sign_completed = true
+ end
+
+ def write_info_plist
+ log_info "Adding Info.plist."
+
+ info_plist_string = <<-XML
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+ <plist version="1.0">
+ <dict>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ <key>NSExceptionDomains</key>
+ <dict>
+ <key>google.com</key>
+ <dict>
+ <key>NSExceptionAllowsInsecureHTTPLoads</key>
+ <true/>
+ <key>NSIncludesSubdomains</key>
+ <true/>
+ </dict>
+ </dict>
+ </dict>
+ <key>BuildMachineOSBuild</key>
+ <string>19C57</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>:app_name</string>
+ <key>CFBundleExecutable</key>
+ <string>Runtime</string>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>AppIcon60x60</string>
+ </array>
+ <key>CFBundleIcons</key>
+ <dict>
+ <key>CFBundlePrimaryIcon</key>
+ <dict>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>AppIcon60x60</string>
+ </array>
+ <key>CFBundleIconName</key>
+ <string>AppIcon</string>
+ </dict>
+ </dict>
+ <key>CFBundleIcons~ipad</key>
+ <dict>
+ <key>CFBundlePrimaryIcon</key>
+ <dict>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>AppIcon60x60</string>
+ <string>AppIcon76x76</string>
+ </array>
+ <key>CFBundleIconName</key>
+ <string>AppIcon</string>
+ </dict>
+ </dict>
+ <key>CFBundleIdentifier</key>
+ <string>com.carlile.swisscheese</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>:app_name</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleSupportedPlatforms</key>
+ <array>
+ <string>iPhoneOS</string>
+ </array>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>DTCompiler</key>
+ <string>com.apple.compilers.llvm.clang.1_0</string>
+ <key>DTPlatformBuild</key>
+ <string>17B102</string>
+ <key>DTPlatformName</key>
+ <string>iphoneos</string>
+ <key>DTPlatformVersion</key>
+ <string>13.2</string>
+ <key>DTSDKBuild</key>
+ <string>17B102</string>
+ <key>DTSDKName</key>
+ <string>iphoneos13.2</string>
+ <key>DTXcode</key>
+ <string>01131</string>
+ <key>DTXcodeBuild</key>
+ <string>11C505</string>
+ <key>ITSAppUsesNonExemptEncryption</key>
+ <false/>
+ <key>MinimumOSVersion</key>
+ <string>11.0</string>
+ <key>UIAppFonts</key>
+ <array/>
+ <key>UIBackgroundModes</key>
+ <array/>
+ <key>UIDeviceFamily</key>
+ <array>
+ <integer>1</integer>
+ <integer>2</integer>
+ </array>
+ <key>UILaunchImages</key>
+ <array>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>11.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-1100-Portrait-2436h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{375, 812}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>8.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-800-Portrait-736h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{414, 736}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>8.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-800-667h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{375, 667}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-700</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{320, 480}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-700-568h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{320, 568}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>LaunchImage-700-Portrait</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{768, 1024}</string>
+ </dict>
+ </array>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>arm64</string>
+ </array>
+ <key>UIRequiresFullScreen</key>
+ <true/>
+ <key>UIStatusBarStyle</key>
+ <string>UIStatusBarStyleDefault</string>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>#{device_orientation_xml}</string>
+ </array>
+ </dict>
+ </plist>
+ XML
+
+ # <string>UIInterfaceOrientationPortrait</string>
+ # <string>UIInterfaceOrientationLandscapeRight</string>
+
+ $gtk.write_file_root "tmp/ios/#{@app_name}.app/Info.plist", info_plist_string.gsub(":app_name", @app_name).strip
+
+ @info_plist_written = true
+ end
+
+ def device_orientation_xml
+ return "UIInterfaceOrientationLandscapeRight" if $gtk.logical_width > $gtk.logical_height
+ return "UIInterfaceOrientationPortrait"
+ end
+
+ def tmp_directory
+ "#{relative_path}/tmp/ios"
+ end
+
+ def app_path
+ "#{tmp_directory}/#{@app_name}.app"
+ end
+
+ def root_folder
+ "#{relative_path}/#{$gtk.cli_arguments[:dragonruby]}"
+ end
+
+ def write_ip_address
+ $gtk.write_file "app/server_ip_address.txt", $gtk.ffi_misc.get_local_ip_address.strip
+ end
+
+ def create_ipa
+ write_ip_address
+ sh "rm \"#{@app_name}\".ipa"
+ sh "rm -rf \"#{app_path}/app\""
+ sh "rm -rf \"#{app_path}/sounds\""
+ sh "rm -rf \"#{app_path}/sprites\""
+ sh "rm -rf \"#{app_path}/data\""
+ sh "rm -rf \"#{app_path}/fonts\""
+ sh "cp -r \"#{root_folder}/app/\" \"#{app_path}/app/\""
+ sh "cp -r \"#{root_folder}/sounds/\" \"#{app_path}/sounds/\""
+ sh "cp -r \"#{root_folder}/sprites/\" \"#{app_path}/sprites/\""
+ sh "cp -r \"#{root_folder}/data/\" \"#{app_path}/data/\""
+ sh "cp -r \"#{root_folder}/fonts/\" \"#{app_path}/fonts/\""
+ sh "mkdir -p #{tmp_directory}/ipa_root/Payload"
+ sh "cp -r \"#{app_path}\" \"#{tmp_directory}/ipa_root/Payload\""
+ sh "chmod -R 755 \"#{tmp_directory}/ipa_root/Payload\""
+ do_zip
+ sh "cp \"#{tmp_directory}/ipa_root/archive.zip\" \"#{tmp_directory}/#{@app_name}.ipa\""
+ sh "XCODE_DIR=\"/Applications/Xcode.app/Contents/Developer\" \"#{relative_path}/dragonruby-deploy-ios\" -d \"#{@device_id}\" \"#{tmp_directory}/#{@app_name}.ipa\""
+ cmd_result = `ps -e | grep civetweb`
+ is_civet_running = (`ps -e | grep civetweb`).strip.each_line.to_a.length > 2
+ if !is_civet_running
+ $gtk.system "cp \"#{relative_path}/civetweb\" \"#{tmp_directory}/../src_backup/civetweb\""
+ $gtk.system "open \"#{tmp_directory}/../src_backup/civetweb\" -g"
+ else
+ log "* INFO: civetweb is running already running. No need to start another instance."
+ end
+ log_info "Check your device!!"
+ end
+
+ def do_zip
+ $gtk.write_file_root "tmp/ios/do_zip.sh", <<-SCRIPT
+ pushd #{tmp_directory}/ipa_root/
+ zip -q -r archive.zip Payload
+ popd
+ SCRIPT
+
+ sh "sh #{tmp_directory}/do_zip.sh"
+ end
+
+ def sh cmd
+ log_info cmd.strip
+ result = `#{cmd}`
+ if result.strip.length > 0
+ log_info result.strip.each_line.map(&:strip).join("\n")
+ end
+ result
+ end
+
+ def deploy
+ end
+ end
+
+#+end_src
+
+* itch_wizard.rb
+#+begin_src ruby
+ # ./dragon/itch_wizard.rb
+ # Copyright 2019 DragonRuby LLC
+ # MIT License
+ # itch_wizard.rb has been released under MIT (*only this file*).
+
+ class ItchWizard
+ def steps
+ [
+ :check_metadata,
+ :deploy
+ ]
+ end
+
+ def metadata_file_path
+ "metadata/game_metadata.txt"
+ end
+
+ def get_metadata
+ metadata = $gtk.read_file metadata_file_path
+
+ if !metadata
+ write_blank_metadata
+ metadata = $gtk.read_file metadata_file_path
+ end
+
+ dev_id, dev_title, game_id, game_title, version, icon = *metadata.each_line.to_a
+
+ {
+ dev_id: dev_id.strip,
+ dev_title: dev_title.strip,
+ game_id: game_id.strip,
+ game_title: game_title.strip,
+ version: version.strip,
+ icon: icon.strip
+ }
+ end
+
+ def write_blank_metadata
+ $gtk.write_file metadata_file_path, <<-S.strip
+ #devid=myname
+ #devtitle=My Name
+ #gameid=mygame
+ #gametitle=My Game
+ #version=0.1
+ #icon=metadata/icon.png
+ S
+ end
+
+ def check_metadata
+ metadata_text = $gtk.read_file metadata_file_path
+ if !metadata_text
+ write_blank_metadata
+ end
+
+ if metadata_text.each_line.to_a.length != 6
+ write_blank_metadata
+ end
+
+ log "* INFO: Contents of #{metadata_file_path}:"
+ log "#+begin_src txt"
+ metadata_text.each_line { |l| log " #{l}" }
+ log "#+end_src"
+ metadata = get_metadata
+
+ if metadata[:dev_id].start_with?("#") || !@dev_id
+ log "* PROMPT: Please provide your username for Itch."
+ $console.set_command "$wizards.itch.set_dev_id \"your-itch-username\""
+ return :need_dev_id
+ end
+
+ if metadata[:dev_title].start_with?("#") || !@dev_title
+ log "* PROMPT: Please provide developer's/company's name that you want displayed."
+ $console.set_command "$wizards.itch.set_dev_title \"Your Name\""
+ return :need_dev_title
+ end
+
+ if metadata[:game_id].start_with?("#") || !@game_id
+ log "* PROMPT: Please provide the id for you game. This is the id you specified when you set up a new game page on Itch."
+ $console.set_command "$wizards.itch.set_game_id \"your-game-id\""
+ return :need_game_id
+ end
+
+ if metadata[:game_title].start_with?("#") || !@game_title
+ log "* PROMPT: Please provide the display name for your game. (This can include spaces)"
+ $console.set_command "$wizards.itch.set_game_title \"Your Game\""
+ return :need_game_title
+ end
+
+ if metadata[:version].start_with?("#") || !@version
+ log "* PROMPT: Please provide the version for your game."
+ $console.set_command "$wizards.itch.set_version \"1.0\""
+ return :need_version
+ end
+
+ if metadata[:icon].start_with?("#") || !@icon
+ log "* PROPT: Please provide icon path for your game."
+ $console.set_command "$wizards.itch.set_icon \"icon.png\""
+ return :need_icon
+ end
+
+ return :success
+ end
+
+ def set_dev_id value
+ @dev_id = value
+ write_metadata
+ start
+ end
+
+ def set_dev_title value
+ @dev_title = value
+ write_metadata
+ start
+ end
+
+ def set_game_id value
+ @game_id = value
+ write_metadata
+ start
+ end
+
+ def set_game_title value
+ @game_title = value
+ write_metadata
+ start
+ end
+
+ def set_version value
+ @version = value
+ write_metadata
+ start
+ end
+
+ def set_icon value
+ @icon = value
+ write_metadata
+ start
+ end
+
+ def write_metadata
+ text = ""
+ if @dev_id
+ text += "devid=#{@dev_id}\n"
+ else
+ text += "#devid=myname\n"
+ end
+
+ if @dev_title
+ text += "devtitle=#{@dev_title}\n"
+ else
+ text += "#devtitle=My Name\n"
+ end
+
+ if @game_id
+ text += "gameid=#{@game_id}\n"
+ else
+ text += "#gameid=gameid\n"
+ end
+
+ if @game_title
+ text += "gametitle=#{@game_title}\n"
+ else
+ text += "#gametitle=Game Name\n"
+ end
+
+ if @version
+ text += "version=#{@version}\n"
+ else
+ text += "#version=0.1\n"
+ end
+
+ if @icon
+ text += "icon=metadata/#{@icon}\n"
+ else
+ text += "#icon=metadata/icon.png\n"
+ end
+
+ $gtk.write_file metadata_file_path, text
+ end
+
+ def relative_path
+ (File.dirname $gtk.binary_path)
+ end
+
+ def package_command
+ "#{File.join $gtk.get_base_dir, 'dragonruby-publish'}"
+ end
+
+ def deploy
+ log_info "* Running dragonruby-publish: #{package_command}"
+ results = $gtk.exec package_command
+ log "#+begin_src"
+ log results
+ log "#+end_src"
+ :success
+ end
+
+ def start
+ log "================"
+ log "* INFO: Starting Itch Wizard."
+ @start_at = Kernel.global_tick_count
+ steps.each do |m|
+ begin
+ log_info "Running Itch Wizard Step: ~$wizards.itch.#{m}~"
+ result = (send m) || :success if @wizard_status[m][:result] != :success
+ @wizard_status[m][:result] = result
+ if result != :success
+ log_info "Exiting wizard. :#{result}"
+ break
+ end
+ rescue Exception => e
+ if e.is_a? WizardException
+ $console.log.clear
+ $console.archived_log.clear
+ log "=" * $console.console_text_width
+ e.console_primitives.each do |p|
+ $console.add_primitive p
+ end
+ log "=" * $console.console_text_width
+ $console.set_command (e.console_command || "$wizards.itch.start")
+ else
+ log_error "Step #{m} failed."
+ log_error e.to_s
+ $console.set_command "$wizards.itch.start"
+ end
+
+ break
+ end
+ end
+ end
+
+ def reset
+ @dev_id = nil
+ @dev_title = nil
+ @game_id = nil
+ @game_title = nil
+ @version = nil
+ @icon = nil
+ init_wizard_status
+ end
+
+ def restart
+ reset
+ start
+ end
+
+ def initialize
+ reset
+ end
+
+ def init_wizard_status
+ @wizard_status = {}
+
+ steps.each do |m|
+ @wizard_status[m] = { result: :not_started }
+ end
+
+ previous_step = nil
+ next_step = nil
+
+ steps.each_cons(2) do |current_step, next_step|
+ @wizard_status[current_step][:next_step] = next_step
+ end
+
+ steps.reverse.each_cons(2) do |current_step, previous_step|
+ @wizard_status[current_step][:previous_step] = previous_step
+ end
+ end
+ end
+
+#+end_src
+
+* layout.rb
+#+begin_src ruby
+ # ./dragon/layout.rb
+ # Copyright 2019 DragonRuby LLC
+ # MIT License
+ # layout.rb has been released under MIT (*only this file*).
+
+ module GTK
+ class Margin
+ attr :left, :right, :top, :bottom
+
+ def initialize
+ @left = 0
+ @right = 0
+ @top = 0
+ @bottom = 0
+ end
+
+ def serialize
+ {
+ left: @left,
+ right: @right,
+ top: @top,
+ bottom: @bottom,
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class SafeArea
+ attr :w, :h, :margin
+
+ def initialize
+ @w = 0
+ @h = 0
+ @margin = Margin.new
+ end
+
+ def serialize
+ {
+ w: @w,
+ h: @h,
+ margin: @margin.serialize
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class GridArea
+ attr :w, :h, :margin, :gutter, :col_count, :row_count, :cell_w, :cell_h, :outer_gutter
+
+ def initialize
+ @w = 0
+ @h = 0
+ @gutter = 0
+ @outer_gutter = 0
+ @col_count = 0
+ @row_count = 0
+ @margin = Margin.new
+ end
+
+ def serialize
+ {
+ w: @w,
+ h: @h,
+ gutter: @gutter,
+ outer_gutter: @outer_gutter,
+ col_count: @col_count,
+ row_count: @row_count,
+ margin: @margin.serialize
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class ControlArea
+ attr :cell_size, :w, :h, :margin
+
+ def initialize
+ @margin = Margin.new
+ end
+
+ def serialize
+ {
+ cell_size: @cell_size,
+ w: @w,
+ h: @h,
+ margin: @margin.serialize,
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class Device
+ attr :w, :h, :safe_area, :grid_area, :control_area, :name, :aspect
+
+ def initialize
+ @name = ""
+ @w = 0
+ @h = 0
+ @safe_area = SafeArea.new
+ @grid_area = GridArea.new
+ @control_area = ControlArea.new
+ @aspect = AspectRatio.new
+ end
+
+ def assert! result, message
+ return if result
+ raise message
+ end
+
+ def check_math!
+ assert! (@control_area.w + @control_area.margin.left + @control_area.margin.right) == @w, "Math for Width didn't pan out."
+ assert! (@control_area.h + @control_area.margin.top + @control_area.margin.bottom) == @h, "Math for Height didn't pan out."
+ end
+
+ def serialize
+ {
+ name: @name,
+ w: @w,
+ h: @h,
+ aspect: @aspect.serialize,
+ safe_area: @safe_area.serialize,
+ grid_area: @grid_area.serialize,
+ control_area: @control_area.serialize
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class AspectRatio
+ attr :w, :h, :u
+
+ def initialize
+ @w = 0
+ @h = 0
+ @u = 0
+ end
+
+ def serialize
+ {
+ w: @w,
+ h: @h,
+ u: @u
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+
+ class Layout
+ attr :w, :h, :rect_cache
+
+ def initialize w, h
+ @w = w
+ @h = h
+ @rect_cache = {}
+ init_device @w, @h
+ end
+
+ def u_for_16x9 w, h
+ u = (w.fdiv 16).floor
+ u = (h.fdiv 9).floor if (u * 9) > h
+
+ {
+ u: u,
+ w: u * 16,
+ h: u * 9
+ }
+ end
+
+ def font_relative_size_enum size_enum
+ base_line_logical = 22
+ base_line_actual = font_size_med
+ target_logical = size_enum
+ target_logical = 1 if target_logical <= 0
+ (base_line_actual / base_line_logical) * target_logical
+ end
+
+ def font_px_to_pt px
+ (px / 1.33333).floor
+ end
+
+ def font_pt_to_px pt
+ pt * 1.333333
+ end
+
+ def font_size_cell
+ (cell_height / 1.33333)
+ end
+
+ def font_size_xl
+ font_size_cell
+ end
+
+ def font_size_lg
+ font_size_cell * 0.8
+ end
+
+ def font_size_med
+ font_size_cell * 0.7
+ end
+
+ def font_size_sm
+ font_size_cell * 0.6
+ end
+
+ def font_size_xs
+ font_size_cell * 0.5
+ end
+
+ def font_size
+ font_size_cell * 0.7
+ end
+
+ def logical_rect
+ @logical_rect ||= { x: 0,
+ y: 0,
+ w: @w,
+ h: @h }
+ end
+
+ def safe_rect
+ @safe_rect ||= { x: 0,
+ y: 0,
+ w: @w,
+ h: @h }
+ end
+
+ def control_rect
+ @control_rect ||= { x: device.control_area.margin.left,
+ y: device.control_area.margin.top,
+ w: device.control_area.w,
+ h: device.control_area.h }
+ end
+
+ def row_count
+ device.grid_area.row_count
+ end
+
+ def col_count
+ device.grid_area.col_count
+ end
+
+ def gutter_height
+ device.grid_area.gutter
+ end
+
+ def gutter_width
+ device.grid_area.gutter
+ end
+
+ def outer_gutter
+ device.grid_area.outer_gutter
+ end
+
+ def cell_height
+ device.control_area.cell_size
+ end
+
+ def cell_width
+ device.control_area.cell_size
+ end
+
+ def rect_defaults
+ {
+ row: nil,
+ col: nil,
+ h: 1,
+ w: 1,
+ dx: 0,
+ dy: 0,
+ rect: :control_rect
+ }
+ end
+
+ def rect opts
+ opts = rect_defaults.merge opts
+ result = send opts[:rect]
+ if opts[:row] && opts[:col] && opts[:w] && opts[:h]
+ col = rect_col opts[:col], opts[:w]
+ row = rect_row opts[:row], opts[:h]
+ result = control_rect.merge x: col.x,
+ y: row.y,
+ w: col.w,
+ h: row.h
+ elsif opts[:row] && !opts[:col]
+ result = rect_row opts[:row], opts[:h]
+ elsif !opts[:row] && opts[:col]
+ result = rect_col opts[:col], opts[:w]
+ else
+ raise "LayoutTheory::rect unable to process opts #{opts}."
+ end
+
+ if opts[:max_height] && opts[:max_height] >= 0
+ if result[:h] > opts[:max_height]
+ delta = (result[:h] - opts[:max_height]) * 2
+ result[:y] += delta
+ result[:h] = opts[:max_height]
+ end
+ end
+
+ if opts[:max_width] && opts[:max_width] >= 0
+ if result[:w] > opts[:max_width]
+ delta = (result[:w] - opts[:max_width]) * 2
+ result[:x] += delta
+ result[:w] = opts[:max_width]
+ end
+ end
+
+ result[:x] += opts[:dx]
+ result[:y] += opts[:dy]
+
+ if opts[:include_row_gutter]
+ result[:x] -= device.grid_area.gutter
+ result[:w] += device.grid_area.gutter * 2
+ end
+
+ if opts[:include_col_gutter]
+ result[:y] -= device.grid_area.gutter
+ result[:h] += device.grid_area.gutter * 2
+ end
+
+ result
+ end
+
+ def rect_center reference, target
+ delta_x = (reference.w - target.w).fdiv 2
+ delta_y = (reference.h - target.h).fdiv 2
+ [target.x - delta_x, target.y - delta_y, target.w, target.h]
+ end
+
+ def rect_row index, h
+ @rect_cache[:row] ||= {}
+ @rect_cache[:row][index] ||= {}
+ return @rect_cache[:row][index][h] if @rect_cache[:row][index][h]
+ row_h = (device.grid_area.gutter * (h - 1)) +
+ (device.control_area.cell_size * h)
+
+ row_h = row_h.to_i
+ row_h -= 1 if row_h.odd?
+
+ row_y = (control_rect.y) +
+ (device.grid_area.gutter * index) +
+ (device.control_area.cell_size * index)
+
+ row_y = row_y.to_i
+ row_y += 1 if row_y.odd? && (index + 1) > @device.grid_area.row_count.half
+ row_y += 1 if row_y.odd? && (index + 1) <= @device.grid_area.row_count.half
+
+ row_y = device.h - row_y - row_h
+
+ result = control_rect.merge y: row_y, h: row_h
+ @rect_cache[:row][index][h] = result
+ @rect_cache[:row][index][h]
+ end
+
+ def rect_col index, w
+ @rect_cache[:col] ||= {}
+ @rect_cache[:col][index] ||= {}
+ return @rect_cache[:col][index][w] if @rect_cache[:col][index][w]
+ col_x = (control_rect.x) +
+ (device.grid_area.gutter * index) +
+ (device.control_area.cell_size * index)
+
+ col_x = col_x.to_i
+ col_x -= 1 if col_x.odd? && (index + 1) < @device.grid_area.col_count.half
+ col_x += 1 if col_x.odd? && (index + 1) >= @device.grid_area.col_count.half
+
+ col_w = (device.grid_area.gutter * (w - 1)) +
+ (device.control_area.cell_size * w)
+
+ col_w = col_w.to_i
+ col_w -= 1 if col_w.odd?
+
+ result = control_rect.merge x: col_x, w: col_w
+ @rect_cache[:col][index][w] = result
+ @rect_cache[:col][index][w]
+ end
+
+ def device
+ @device
+ end
+
+ def init_device w, h
+ @device = Device.new
+ @device.w = w
+ @device.h = h
+ @device.name = "Device"
+ @device.aspect.w = (u_for_16x9 w, h)[:w]
+ @device.aspect.h = (u_for_16x9 w, h)[:h]
+ @device.aspect.u = (u_for_16x9 w, h)[:u]
+ @device.safe_area.w = @device.aspect.u * 16
+ @device.safe_area.h = @device.aspect.u * 9
+ @device.safe_area.margin.left = ((@device.w - @device.safe_area.w).fdiv 2).floor
+ @device.safe_area.margin.right = ((@device.w - @device.safe_area.w).fdiv 2).floor
+ @device.safe_area.margin.top = ((@device.h - @device.safe_area.h).fdiv 2).floor
+ @device.safe_area.margin.bottom = ((@device.h - @device.safe_area.h).fdiv 2).floor
+ @device.grid_area.outer_gutter = @device.w / 80
+ @device.grid_area.gutter = @device.w / 160
+
+ @device.grid_area.w = @device.safe_area.w - (@device.grid_area.outer_gutter * 2)
+ @device.grid_area.h = @device.safe_area.h - (@device.grid_area.outer_gutter * 2)
+
+ @device.grid_area.margin.left = ((@device.w - @device.grid_area.w).fdiv 2).floor
+ @device.grid_area.margin.right = ((@device.w - @device.grid_area.w).fdiv 2).floor
+ @device.grid_area.margin.top = ((@device.h - @device.grid_area.h).fdiv 2).floor
+ @device.grid_area.margin.bottom = ((@device.h - @device.grid_area.h).fdiv 2).floor
+
+ @device.grid_area.col_count = 24
+ @device.grid_area.row_count = 12
+ @device.grid_area.cell_w = ((@device.aspect.w - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.col_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.col_count
+ @device.grid_area.cell_h = ((@device.aspect.h - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.row_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.row_count
+
+ @device.control_area.cell_size = @device.grid_area.cell_w
+ @device.control_area.cell_size = @device.grid_area.cell_h if @device.grid_area.cell_h < @device.grid_area.cell_w && @device.grid_area.cell_h > 0
+ @device.control_area.cell_size = @device.control_area.cell_size.floor
+ @device.control_area.w = (@device.control_area.cell_size * @device.grid_area.col_count) + (@device.grid_area.gutter * (@device.grid_area.col_count - 1))
+ @device.control_area.h = (@device.control_area.cell_size * @device.grid_area.row_count) + (@device.grid_area.gutter * (@device.grid_area.row_count - 1))
+ @device.control_area.margin.left = (@device.w - @device.control_area.w).fdiv 2
+ @device.control_area.margin.right = (@device.w - @device.control_area.w).fdiv 2
+ @device.control_area.margin.top = (@device.h - @device.control_area.h).fdiv 2
+ @device.control_area.margin.bottom = (@device.h - @device.control_area.h).fdiv 2
+ @device
+ end
+
+ def serialize
+ {
+ device: @device.serialize,
+ }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+ end
+ end
+
+#+end_src
+
* log.rb
#+begin_src ruby
# ./dragon/log.rb
@@ -26416,6 +28643,11 @@ Follows is a source code listing for all files that have been open sourced. This
return 720 - self unless $gtk
$gtk.args.grid.h - self
end
+
+ def from_right
+ return 1280 - self unless $gtk
+ $gtk.args.grid.w - self
+ end
end
class Fixnum
@@ -26564,6 +28796,247 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
+* runtime/draw.rb
+#+begin_src ruby
+ # ./dragon/runtime/draw.rb
+ # Copyright 2019 DragonRuby LLC
+ # MIT License
+ # draw.rb has been released under MIT (*only this file*).
+
+ module GTK
+ class Runtime
+ module Draw
+ def primitives pass
+ if $top_level.respond_to? :primitives_override
+ return $top_level.tick_render @args, pass
+ end
+
+ # Don't change this draw order unless you understand
+ # the implications.
+
+ # pass.solids.each { |s| draw_solid s }
+ # while loops are faster than each with block
+ idx = 0
+ while idx < pass.solids.length
+ draw_solid (pass.solids.value idx) # accessing an array using .value instead of [] is faster
+ idx += 1
+ end
+
+ # pass.static_solids.each { |s| draw_solid s }
+ idx = 0
+ while idx < pass.static_solids.length
+ draw_solid (pass.static_solids.value idx)
+ idx += 1
+ end
+
+ # pass.sprites.each { |s| draw_sprite s }
+ idx = 0
+ while idx < pass.sprites.length
+ draw_sprite (pass.sprites.value idx)
+ idx += 1
+ end
+
+ # pass.static_sprites.each { |s| draw_sprite s }
+ idx = 0
+ while idx < pass.static_sprites.length
+ draw_sprite (pass.static_sprites.value idx)
+ idx += 1
+ end
+
+ # pass.primitives.each { |p| draw_primitive p }
+ idx = 0
+ while idx < pass.primitives.length
+ draw_primitive (pass.primitives.value idx)
+ idx += 1
+ end
+
+ # pass.static_primitives.each { |p| draw_primitive p }
+ idx = 0
+ while idx < pass.static_primitives.length
+ draw_primitive (pass.static_primitives.value idx)
+ idx += 1
+ end
+
+ # pass.labels.each { |l| draw_label l }
+ idx = 0
+ while idx < pass.labels.length
+ draw_label (pass.labels.value idx)
+ idx += 1
+ end
+
+ # pass.static_labels.each { |l| draw_label l }
+ idx = 0
+ while idx < pass.static_labels.length
+ draw_label (pass.static_labels.value idx)
+ idx += 1
+ end
+
+ # pass.lines.each { |l| draw_line l }
+ idx = 0
+ while idx < pass.lines.length
+ draw_line (pass.lines.value idx)
+ idx += 1
+ end
+
+ # pass.static_lines.each { |l| draw_line l }
+ idx = 0
+ while idx < pass.static_lines.length
+ draw_line (pass.static_lines.value idx)
+ idx += 1
+ end
+
+ # pass.borders.each { |b| draw_border b }
+ idx = 0
+ while idx < pass.borders.length
+ draw_border (pass.borders.value idx)
+ idx += 1
+ end
+
+ # pass.static_borders.each { |b| draw_border b }
+ idx = 0
+ while idx < pass.static_borders.length
+ draw_border (pass.static_borders.value idx)
+ idx += 1
+ end
+
+ if !$gtk.production
+ # pass.debug.each { |r| draw_primitive r }
+ idx = 0
+ while idx < pass.debug.length
+ draw_primitive (pass.debug.value idx)
+ idx += 1
+ end
+
+ # pass.static_debug.each { |r| draw_primitive r }
+ idx = 0
+ while idx < pass.static_debug.length
+ draw_primitive (pass.static_debug.value idx)
+ idx += 1
+ end
+ end
+
+ # pass.reserved.each { |r| draw_primitive r }
+ idx = 0
+ while idx < pass.reserved.length
+ draw_primitive (pass.reserved.value idx)
+ idx += 1
+ end
+
+ # pass.static_reserved.each { |r| draw_primitive r }
+ idx = 0
+ while idx < pass.static_reserved.length
+ draw_primitive (pass.static_reserved.value idx)
+ idx += 1
+ end
+ rescue Exception => e
+ pause!
+ pretty_print_exception_and_export! e
+ end
+
+ def draw_solid s
+ return unless s
+ if s.respond_to? :draw_override
+ s.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_solid s.x, s.y, s.w, s.h, s.r, s.g, s.b, s.a
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed s, e, :solid
+ end
+
+ def draw_sprite s
+ return unless s
+ if s.respond_to? :draw_override
+ s.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_sprite_3 s.x, s.y, s.w, s.h,
+ s.path.s_or_default,
+ s.angle,
+ s.a, s.r, s.g, s.b,
+ s.tile_x, s.tile_y, s.tile_w, s.tile_h,
+ !!s.flip_horizontally, !!s.flip_vertically,
+ s.angle_anchor_x, s.angle_anchor_y,
+ s.source_x, s.source_y, s.source_w, s.source_h
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed s, e, :sprite
+ end
+
+ def draw_screenshot s
+ return unless s
+ if s.respond_to? :draw_override
+ s.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_screenshot s.path.s_or_default,
+ s.x, s.y, s.w, s.h,
+ s.angle,
+ s.a, s.r, s.g, s.b,
+ s.tile_x, s.tile_y, s.tile_w, s.tile_h,
+ !!s.flip_horizontally, !!s.flip_vertically,
+ s.angle_anchor_x, s.angle_anchor_y,
+ s.source_x, s.source_y, s.source_w, s.source_h
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed s, e, :screenshot
+ end
+
+ def draw_label l
+ return unless l
+ if l.respond_to? :draw_override
+ l.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_label l.x, l.y, l.text.s_or_default,
+ l.size_enum, l.alignment_enum,
+ l.r, l.g, l.b, l.a,
+ l.font.s_or_default(nil)
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed l, e, :label
+ end
+
+ def draw_line l
+ return unless l
+ if l.respond_to? :draw_override
+ l.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_line l.x, l.y, l.x2, l.y2, l.r, l.g, l.b, l.a
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed l, e, :line
+ end
+
+ def draw_border s
+ return unless s
+ if s.respond_to? :draw_override
+ s.draw_override @ffi_draw
+ else
+ @ffi_draw.draw_border s.x, s.y, s.w, s.h, s.r, s.g, s.b, s.a
+ end
+ rescue Exception => e
+ raise_conversion_for_rendering_failed s, e, :border
+ end
+
+ def draw_screenshots
+ @args.outputs.screenshots.each { |s| draw_screenshot s }
+ end
+
+ def pixel_arrays
+ @args.pixel_arrays.each { |k,v|
+ if v.pixels.length == (v.width * v.height) # !!! FIXME: warning? exception? Different API?
+ @ffi_draw.upload_pixel_array k.to_s, v.width.to_i, v.height.to_i, v.pixels
+ end
+ }
+ rescue Exception => e
+ pause!
+ pretty_print_exception_and_export! e
+ end
+
+ end
+ end
+ end
+
+#+end_src
+
* runtime/framerate_diagnostics.rb
#+begin_src ruby
# ./dragon/runtime/framerate_diagnostics.rb
@@ -26843,6 +29316,10 @@ Follows is a source code listing for all files that have been open sourced. This
def rtrim!
rstrip!
end
+
+ def serialize
+ self
+ end
end
#+end_src
@@ -27000,6 +29477,9 @@ Follows is a source code listing for all files that have been open sourced. This
# MIT License
# trace.rb has been released under MIT (*only this file*).
+ # Contributors outside of DragonRuby who also hold Copyright:
+ # - Dan Healy: https://github.com/danhealy
+
module GTK
module Trace
IGNORED_METHODS = [
@@ -27079,10 +29559,19 @@ Follows is a source code listing for all files that have been open sourced. This
methods.reject { |m| m.start_with? "__trace_" }.reject { |m| IGNORED_METHODS.include? m }
end
+ def self.trace_times_string
+ str = []
+ $trace_performance.sort_by {|method_name, times| -times[:avg] }.each do |method_name, times|
+ str << "#{method_name}: #{times[:sum].round(2)}/#{times[:count]} #{times[:min]}ms min, #{times[:avg].round(2)}ms avg, #{times[:max]}ms max"
+ end
+ str.join("\n")
+ end
+
def self.flush_trace pad_with_newline = false
$trace_puts ||= []
+ puts "(Trace info flushed!)"
if $trace_puts.length > 0
- text = $trace_puts.join("")
+ text = $trace_puts.join("").strip + "\n" + self.trace_times_string + "\n"
if pad_with_newline
$gtk.append_file_root 'logs/trace.txt', "\n" + text.strip
else
@@ -27097,6 +29586,15 @@ Follows is a source code listing for all files that have been open sourced. This
$trace_history ||= []
$trace_enabled = true
$trace_call_depth ||=0
+ $trace_performance = Hash.new {|h,k|
+ h[k] = {
+ min: 100000,
+ max: 0,
+ avg: 0,
+ sum: 0,
+ count: 0
+ }
+ }
flush_trace
instance = $top_level unless instance
return if Trace.traced_classes.include? instance.class
@@ -27114,15 +29612,27 @@ Follows is a source code listing for all files that have been open sourced. This
instance.__trace_call_depth__ += 1
$trace_call_depth = instance.__trace_call_depth__
parameters = "#{args}"[1..-2]
+
$trace_puts << "\n #{tab_width}#{m}(#{parameters})"
- execution_time = Time.new.to_i
+
+ execution_time = Time.new
+
$last_method_traced = trace_method_name
$trace_history << [m, parameters]
+
result = send(trace_method_name, *args)
- completion_time = Time.new.to_i
+
+ class_m = "#{instance.class}##{m}"
+ completion_time = ((Time.new - execution_time).to_f * 1000).round(2)
+ $trace_performance[class_m][:min] = [$trace_performance[class_m][:min], completion_time].min
+ $trace_performance[class_m][:max] = [$trace_performance[class_m][:max], completion_time].max
+ $trace_performance[class_m][:count] += 1
+ $trace_performance[class_m][:sum] += completion_time
+ $trace_performance[class_m][:avg] = $trace_performance[class_m][:sum].fdiv($trace_performance[class_m][:count])
+
instance.__trace_call_depth__ -= 1
instance.__trace_call_depth__ = instance.__trace_call_depth__.greater 0
- $trace_puts << "\n #{tab_width} success: #{m}"
+ $trace_puts << "\n #{tab_width} #{completion_time > 10 ? '!!! ' : ''}#{completion_time}ms success: #{m}"
if instance.__trace_call_depth__ == 0
$trace_puts << "\n"
$trace_history.clear
@@ -27149,3 +29659,23 @@ Follows is a source code listing for all files that have been open sourced. This
#+end_src
+* wizards.rb
+#+begin_src ruby
+ # ./dragon/wizards.rb
+ # Copyright 2019 DragonRuby LLC
+ # MIT License
+ # wizards.rb has been released under MIT (*only this file*).
+
+ module GTK
+ class Wizards
+ attr_accessor :ios, :itch
+
+ def initialize
+ @ios = IOSWizard.new
+ @itch = ItchWizard.new
+ end
+ end
+ end
+
+#+end_src
+
diff --git a/docs/parse_log.txt b/docs/parse_log.txt
index 3c9561c..ec5c73d 100644
--- a/docs/parse_log.txt
+++ b/docs/parse_log.txt
@@ -3667,6 +3667,17 @@ This function takes in two parameters. The first paramter is the file path and a
- End of paragraph detected.
*** True Line Result
+** Processing line: ~* DOCS: ~GTK::Runtime#reset~~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* DOCS: ~GTK::Runtime#reset~
+** Processing line: ~This function will reset Kernel.tick_count to 0 and will remove all data from args.state.~
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+This function will reset Kernel.tick_count to 0 and will remove all data from args.state.
** Processing line: ~* DOCS: ~GTK::Runtime#calcstringbox~~
- Header detected.
*** True Line Result
@@ -3708,17 +3719,6 @@ This function returns the width and height of a string.
- End of paragraph detected.
*** True Line Result
-** Processing line: ~* DOCS: ~GTK::Runtime#reset~~
-- Header detected.
-*** True Line Result
-
-*** True Line Result
-* DOCS: ~GTK::Runtime#reset~
-** Processing line: ~This function will reset Kernel.tick_count to 0 and will remove all data from args.state.~
-** Processing line: ~~
-- End of paragraph detected.
-*** True Line Result
-This function will reset Kernel.tick_count to 0 and will remove all data from args.state.
** Processing line: ~* DOCS: ~Array~~
- Header detected.
*** True Line Result
@@ -5134,6 +5134,86 @@ You have to use ~args.outputs.borders~:
- End of paragraph detected.
*** True Line Result
+** Processing line: ~* DOCS: ~GTK::Outputs#screenshots~~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* DOCS: ~GTK::Outputs#screenshots~
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
+** Processing line: ~Add a hash to this collection to take a screenshot and save as png file.~
+** Processing line: ~The keys of the hash can be provided in any order.~
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+Add a hash to this collection to take a screenshot and save as png file. The keys of the hash can be provided in any order.
+** Processing line: ~#+begin_src~
+- Line was identified as the beginning of a code block.
+*** True Line Result
+
+*** True Line Result
+#+begin_src
+** Processing line: ~ def tick args~
+- Inside source: true
+*** True Line Result
+ def tick args
+** Processing line: ~ args.outputs.screenshots << {~
+- Inside source: true
+*** True Line Result
+ args.outputs.screenshots << {
+** Processing line: ~ x: 0, y: 0, w: 100, h: 100, # Which portion of the screen should be captured~
+- Inside source: true
+*** True Line Result
+ x: 0, y: 0, w: 100, h: 100, # Which portion of the screen should be captured
+** Processing line: ~ path: 'screenshot.png', # Output path of PNG file (inside game directory)~
+- Inside source: true
+*** True Line Result
+ path: 'screenshot.png', # Output path of PNG file (inside game directory)
+** Processing line: ~ r: 255, g: 255, b: 255, a: 0 # Optional chroma key~
+- Inside source: true
+*** True Line Result
+ r: 255, g: 255, b: 255, a: 0 # Optional chroma key
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~#+end_src~
+- Line was identified as the end of a code block.
+*** True Line Result
+#+end_src
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
+** Processing line: ~** Chroma key (Making a color transparent)~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+** Chroma key (Making a color transparent)
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
+** Processing line: ~By specifying the r, g, b and a keys of the hash you change the transparency of a color in the resulting PNG file.~
+** Processing line: ~This can be useful if you want to create files with transparent background like spritesheets.~
+** Processing line: ~The transparency of the color specified by ~r~, ~g~, ~b~ will be set to the transparency specified by ~a~.~
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+By specifying the r, g, b and a keys of the hash you change the transparency of a color in the resulting PNG file. This can be useful if you want to create files with transparent background like spritesheets. The transparency of the color specified by ~r~, ~g~, ~b~ will be set to the transparency specified by ~a~.
+** Processing line: ~The example above sets the color white (255, 255, 255) as transparent.~
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+The example above sets the color white (255, 255, 255) as transparent.
** Processing line: ~* DOCS: ~GTK::Mouse~~
- Header detected.
*** True Line Result
@@ -10647,34 +10727,6 @@ Follows is a source code listing for all files that have been open sourced. This
- End of paragraph detected.
*** True Line Result
-** Processing line: ~* Learn Ruby Optional - Intermediate Ruby Primer - repl.rb~
-- Header detected.
-*** True Line Result
-
-*** True Line Result
-* Learn Ruby Optional - Intermediate Ruby Primer - repl.rb
-** Processing line: ~#+begin_src ruby~
-- Line was identified as the beginning of a code block.
-*** True Line Result
-
-*** True Line Result
-#+begin_src ruby
-** Processing line: ~ # ./samples/00_learn_ruby_optional/00_intermediate_ruby_primer/app/repl.rb~
-- Inside source: true
-*** True Line Result
- # ./samples/00_learn_ruby_optional/00_intermediate_ruby_primer/app/repl.rb
-** Processing line: ~~
-- Inside source: true
-*** True Line Result
-
-** Processing line: ~#+end_src~
-- Line was identified as the end of a code block.
-*** True Line Result
-#+end_src
-** Processing line: ~~
-- End of paragraph detected.
-*** True Line Result
-
** Processing line: ~* Rendering Basics - Labels - main.rb~
- Header detected.
*** True Line Result
@@ -13015,6 +13067,18 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
def spawn_new_sound args, num
+** Processing line: ~ input = nil~
+- Inside source: true
+*** True Line Result
+ input = nil
+** Processing line: ~ input = "sounds/#{num}.#{(num == 6) ? 'ogg' : 'wav'}"~
+- Inside source: true
+*** True Line Result
+ input = "sounds/#{num}.#{(num == 6) ? 'ogg' : 'wav'}"
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ # Spawn randomly in an area that won't be covered by UI.~
- Inside source: true
*** True Line Result
@@ -13051,10 +13115,10 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
args.audio[args.state.next_sound_index] = {
-** Processing line: ~ filename: "sounds/#{num}.#{(num == 6) ? 'ogg' : 'wav'}",~
+** Processing line: ~ input: input,~
- Inside source: true
*** True Line Result
- filename: "sounds/#{num}.#{(num == 6) ? 'ogg' : 'wav'}",
+ input: input,
** Processing line: ~ screenx: screenx,~
- Inside source: true
*** True Line Result
@@ -13267,6 +13331,1454 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~#+end_src~
+- Line was identified as the end of a code block.
+*** True Line Result
+#+end_src
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
+** Processing line: ~* Rendering Basics - Sound Synthesis - main.rb~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* Rendering Basics - Sound Synthesis - main.rb
+** Processing line: ~#+begin_src ruby~
+- Line was identified as the beginning of a code block.
+*** True Line Result
+
+*** True Line Result
+#+begin_src ruby
+** Processing line: ~ # ./samples/01_rendering_basics/07_sound_synthesis/app/main.rb~
+- Inside source: true
+*** True Line Result
+ # ./samples/01_rendering_basics/07_sound_synthesis/app/main.rb
+** Processing line: ~ def tick args~
+- Inside source: true
+*** True Line Result
+ def tick args
+** Processing line: ~ defaults args~
+- Inside source: true
+*** True Line Result
+ defaults args
+** Processing line: ~ render args~
+- Inside source: true
+*** True Line Result
+ render args
+** Processing line: ~ input args~
+- Inside source: true
+*** True Line Result
+ input args
+** Processing line: ~ process_audio_queue args~
+- Inside source: true
+*** True Line Result
+ process_audio_queue args
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def defaults args~
+- Inside source: true
+*** True Line Result
+ def defaults args
+** Processing line: ~ args.state.sine_waves ||= {}~
+- Inside source: true
+*** True Line Result
+ args.state.sine_waves ||= {}
+** Processing line: ~ args.state.audio_queue ||= []~
+- Inside source: true
+*** True Line Result
+ args.state.audio_queue ||= []
+** Processing line: ~ args.state.buttons ||= [~
+- Inside source: true
+*** True Line Result
+ args.state.buttons ||= [
+** Processing line: ~ (frequency_buttons args),~
+- Inside source: true
+*** True Line Result
+ (frequency_buttons args),
+** Processing line: ~ (note_buttons args),~
+- Inside source: true
+*** True Line Result
+ (note_buttons args),
+** Processing line: ~ (bell_buttons args)~
+- Inside source: true
+*** True Line Result
+ (bell_buttons args)
+** Processing line: ~ ].flatten~
+- Inside source: true
+*** True Line Result
+ ].flatten
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def frequency_buttons args~
+- Inside source: true
+*** True Line Result
+ def frequency_buttons args
+** Processing line: ~ [~
+- Inside source: true
+*** True Line Result
+ [
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 4.0, col: 0, text: "300hz",~
+- Inside source: true
+*** True Line Result
+ row: 4.0, col: 0, text: "300hz",
+** Processing line: ~ frequency: 300,~
+- Inside source: true
+*** True Line Result
+ frequency: 300,
+** Processing line: ~ method_to_call: :play_sine_wave),~
+- Inside source: true
+*** True Line Result
+ method_to_call: :play_sine_wave),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 5.0, col: 0, text: "400hz",~
+- Inside source: true
+*** True Line Result
+ row: 5.0, col: 0, text: "400hz",
+** Processing line: ~ frequency: 400,~
+- Inside source: true
+*** True Line Result
+ frequency: 400,
+** Processing line: ~ method_to_call: :play_sine_wave),~
+- Inside source: true
+*** True Line Result
+ method_to_call: :play_sine_wave),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 6.0, col: 0, text: "500hz",~
+- Inside source: true
+*** True Line Result
+ row: 6.0, col: 0, text: "500hz",
+** Processing line: ~ frequency: 500,~
+- Inside source: true
+*** True Line Result
+ frequency: 500,
+** Processing line: ~ method_to_call: :play_sine_wave),~
+- Inside source: true
+*** True Line Result
+ method_to_call: :play_sine_wave),
+** Processing line: ~ ]~
+- Inside source: true
+*** True Line Result
+ ]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def play_sine_wave args, sender~
+- Inside source: true
+*** True Line Result
+ def play_sine_wave args, sender
+** Processing line: ~ queue_sine_wave args,~
+- Inside source: true
+*** True Line Result
+ queue_sine_wave args,
+** Processing line: ~ frequency: sender[:frequency],~
+- Inside source: true
+*** True Line Result
+ frequency: sender[:frequency],
+** Processing line: ~ duration: 1.seconds,~
+- Inside source: true
+*** True Line Result
+ duration: 1.seconds,
+** Processing line: ~ fade_out: true~
+- Inside source: true
+*** True Line Result
+ fade_out: true
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def note_buttons args~
+- Inside source: true
+*** True Line Result
+ def note_buttons args
+** Processing line: ~ [~
+- Inside source: true
+*** True Line Result
+ [
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 1.5, col: 3, text: "C4",~
+- Inside source: true
+*** True Line Result
+ row: 1.5, col: 3, text: "C4",
+** Processing line: ~ note: :c, octave: 4, method_to_call: :play_note),~
+- Inside source: true
+*** True Line Result
+ note: :c, octave: 4, method_to_call: :play_note),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 2.5, col: 3, text: "D4",~
+- Inside source: true
+*** True Line Result
+ row: 2.5, col: 3, text: "D4",
+** Processing line: ~ note: :d, octave: 4, method_to_call: :play_note),~
+- Inside source: true
+*** True Line Result
+ note: :d, octave: 4, method_to_call: :play_note),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 3.5, col: 3, text: "E4",~
+- Inside source: true
+*** True Line Result
+ row: 3.5, col: 3, text: "E4",
+** Processing line: ~ note: :e, octave: 4, method_to_call: :play_note),~
+- Inside source: true
+*** True Line Result
+ note: :e, octave: 4, method_to_call: :play_note),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 4.5, col: 3, text: "F4",~
+- Inside source: true
+*** True Line Result
+ row: 4.5, col: 3, text: "F4",
+** Processing line: ~ note: :f, octave: 4, method_to_call: :play_note),~
+- Inside source: true
+*** True Line Result
+ note: :f, octave: 4, method_to_call: :play_note),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 5.5, col: 3, text: "G4",~
+- Inside source: true
+*** True Line Result
+ row: 5.5, col: 3, text: "G4",
+** Processing line: ~ note: :g, octave: 4, method_to_call: :play_note),~
+- Inside source: true
+*** True Line Result
+ note: :g, octave: 4, method_to_call: :play_note),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 6.5, col: 3, text: "A5",~
+- Inside source: true
+*** True Line Result
+ row: 6.5, col: 3, text: "A5",
+** Processing line: ~ note: :a, octave: 5, method_to_call: :play_note),~
+- Inside source: true
+*** True Line Result
+ note: :a, octave: 5, method_to_call: :play_note),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 7.5, col: 3, text: "B5",~
+- Inside source: true
+*** True Line Result
+ row: 7.5, col: 3, text: "B5",
+** Processing line: ~ note: :b, octave: 5, method_to_call: :play_note),~
+- Inside source: true
+*** True Line Result
+ note: :b, octave: 5, method_to_call: :play_note),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 8.5, col: 3, text: "C5",~
+- Inside source: true
+*** True Line Result
+ row: 8.5, col: 3, text: "C5",
+** Processing line: ~ note: :c, octave: 5, method_to_call: :play_note),~
+- Inside source: true
+*** True Line Result
+ note: :c, octave: 5, method_to_call: :play_note),
+** Processing line: ~ ]~
+- Inside source: true
+*** True Line Result
+ ]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def play_note args, sender~
+- Inside source: true
+*** True Line Result
+ def play_note args, sender
+** Processing line: ~ queue_sine_wave args,~
+- Inside source: true
+*** True Line Result
+ queue_sine_wave args,
+** Processing line: ~ frequency: (frequency_for note: sender[:note],~
+- Inside source: true
+*** True Line Result
+ frequency: (frequency_for note: sender[:note],
+** Processing line: ~ octave: sender[:octave]),~
+- Inside source: true
+*** True Line Result
+ octave: sender[:octave]),
+** Processing line: ~ duration: 1.seconds,~
+- Inside source: true
+*** True Line Result
+ duration: 1.seconds,
+** Processing line: ~ fade_out: true~
+- Inside source: true
+*** True Line Result
+ fade_out: true
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def bell_buttons args~
+- Inside source: true
+*** True Line Result
+ def bell_buttons args
+** Processing line: ~ [~
+- Inside source: true
+*** True Line Result
+ [
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 1.5, col: 6, text: "Bell C4",~
+- Inside source: true
+*** True Line Result
+ row: 1.5, col: 6, text: "Bell C4",
+** Processing line: ~ note: :c, octave: 4, method_to_call: :play_bell),~
+- Inside source: true
+*** True Line Result
+ note: :c, octave: 4, method_to_call: :play_bell),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 2.5, col: 6, text: "Bell D4",~
+- Inside source: true
+*** True Line Result
+ row: 2.5, col: 6, text: "Bell D4",
+** Processing line: ~ note: :d, octave: 4, method_to_call: :play_bell),~
+- Inside source: true
+*** True Line Result
+ note: :d, octave: 4, method_to_call: :play_bell),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 3.5, col: 6, text: "Bell E4",~
+- Inside source: true
+*** True Line Result
+ row: 3.5, col: 6, text: "Bell E4",
+** Processing line: ~ note: :e, octave: 4, method_to_call: :play_bell),~
+- Inside source: true
+*** True Line Result
+ note: :e, octave: 4, method_to_call: :play_bell),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 4.5, col: 6, text: "Bell F4",~
+- Inside source: true
+*** True Line Result
+ row: 4.5, col: 6, text: "Bell F4",
+** Processing line: ~ note: :f, octave: 4, method_to_call: :play_bell),~
+- Inside source: true
+*** True Line Result
+ note: :f, octave: 4, method_to_call: :play_bell),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 5.5, col: 6, text: "Bell G4",~
+- Inside source: true
+*** True Line Result
+ row: 5.5, col: 6, text: "Bell G4",
+** Processing line: ~ note: :g, octave: 4, method_to_call: :play_bell),~
+- Inside source: true
+*** True Line Result
+ note: :g, octave: 4, method_to_call: :play_bell),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 6.5, col: 6, text: "Bell A5",~
+- Inside source: true
+*** True Line Result
+ row: 6.5, col: 6, text: "Bell A5",
+** Processing line: ~ note: :a, octave: 5, method_to_call: :play_bell),~
+- Inside source: true
+*** True Line Result
+ note: :a, octave: 5, method_to_call: :play_bell),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 7.5, col: 6, text: "Bell B5",~
+- Inside source: true
+*** True Line Result
+ row: 7.5, col: 6, text: "Bell B5",
+** Processing line: ~ note: :b, octave: 5, method_to_call: :play_bell),~
+- Inside source: true
+*** True Line Result
+ note: :b, octave: 5, method_to_call: :play_bell),
+** Processing line: ~ (button args,~
+- Inside source: true
+*** True Line Result
+ (button args,
+** Processing line: ~ row: 8.5, col: 6, text: "Bell C5",~
+- Inside source: true
+*** True Line Result
+ row: 8.5, col: 6, text: "Bell C5",
+** Processing line: ~ note: :c, octave: 5, method_to_call: :play_bell),~
+- Inside source: true
+*** True Line Result
+ note: :c, octave: 5, method_to_call: :play_bell),
+** Processing line: ~ ]~
+- Inside source: true
+*** True Line Result
+ ]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def play_bell args, sender~
+- Inside source: true
+*** True Line Result
+ def play_bell args, sender
+** Processing line: ~ queue_bell args,~
+- Inside source: true
+*** True Line Result
+ queue_bell args,
+** Processing line: ~ frequency: (frequency_for note: sender[:note],~
+- Inside source: true
+*** True Line Result
+ frequency: (frequency_for note: sender[:note],
+** Processing line: ~ octave: sender[:octave]),~
+- Inside source: true
+*** True Line Result
+ octave: sender[:octave]),
+** Processing line: ~ duration: 2.seconds,~
+- Inside source: true
+*** True Line Result
+ duration: 2.seconds,
+** Processing line: ~ fade_out: true~
+- Inside source: true
+*** True Line Result
+ fade_out: true
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def render args~
+- Inside source: true
+*** True Line Result
+ def render args
+** Processing line: ~ args.outputs.borders << args.state.buttons.map { |b| b[:border] }~
+- Inside source: true
+*** True Line Result
+ args.outputs.borders << args.state.buttons.map { |b| b[:border] }
+** Processing line: ~ args.outputs.labels << args.state.buttons.map { |b| b[:label] }~
+- Inside source: true
+*** True Line Result
+ args.outputs.labels << args.state.buttons.map { |b| b[:label] }
+** Processing line: ~ args.outputs.labels << args.layout~
+- Inside source: true
+*** True Line Result
+ args.outputs.labels << args.layout
+** Processing line: ~ .rect(row: 0,~
+- Inside source: true
+*** True Line Result
+ .rect(row: 0,
+** Processing line: ~ col: 11.5)~
+- Inside source: true
+*** True Line Result
+ col: 11.5)
+** Processing line: ~ .yield_self { |r| r.merge y: r.y + r.h }~
+- Inside source: true
+*** True Line Result
+ .yield_self { |r| r.merge y: r.y + r.h }
+** Processing line: ~ .merge(text: "This is a Pro only feature. Click here to watch the YouTube video if you are on the Standard License.",~
+- Inside source: true
+*** True Line Result
+ .merge(text: "This is a Pro only feature. Click here to watch the YouTube video if you are on the Standard License.",
+** Processing line: ~ alignment_enum: 1)~
+- Inside source: true
+*** True Line Result
+ alignment_enum: 1)
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def input args~
+- Inside source: true
+*** True Line Result
+ def input args
+** Processing line: ~ args.state.buttons.each do |b|~
+- Inside source: true
+*** True Line Result
+ args.state.buttons.each do |b|
+** Processing line: ~ if args.inputs.mouse.click.inside_rect? b[:rect]~
+- Inside source: true
+*** True Line Result
+ if args.inputs.mouse.click.inside_rect? b[:rect]
+** Processing line: ~ parameter_string = (b.slice :frequency, :note, :octave).map { |k, v| "#{k}: #{v}" }.join ", "~
+- Inside source: true
+*** True Line Result
+ parameter_string = (b.slice :frequency, :note, :octave).map { |k, v| "#{k}: #{v}" }.join ", "
+** Processing line: ~ args.gtk.notify! "#{b[:method_to_call]} #{parameter_string}"~
+- Inside source: true
+*** True Line Result
+ args.gtk.notify! "#{b[:method_to_call]} #{parameter_string}"
+** Processing line: ~ send b[:method_to_call], args, b~
+- Inside source: true
+*** True Line Result
+ send b[:method_to_call], args, b
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if args.inputs.mouse.click.inside_rect? (args.layout.rect(row: 0).yield_self { |r| r.merge y: r.y + r.h.half, h: r.h.half })~
+- Inside source: true
+*** True Line Result
+ if args.inputs.mouse.click.inside_rect? (args.layout.rect(row: 0).yield_self { |r| r.merge y: r.y + r.h.half, h: r.h.half })
+** Processing line: ~ args.gtk.openurl 'https://www.youtube.com/watch?v=zEzovM5jT-k&ab_channel=AmirRajan'~
+- Inside source: true
+*** True Line Result
+ args.gtk.openurl 'https://www.youtube.com/watch?v=zEzovM5jT-k&ab_channel=AmirRajan'
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def process_audio_queue args~
+- Inside source: true
+*** True Line Result
+ def process_audio_queue args
+** Processing line: ~ to_queue = args.state.audio_queue.find_all { |v| v[:queue_at] <= args.tick_count }~
+- Inside source: true
+*** True Line Result
+ to_queue = args.state.audio_queue.find_all { |v| v[:queue_at] <= args.tick_count }
+** Processing line: ~ args.state.audio_queue -= to_queue~
+- Inside source: true
+*** True Line Result
+ args.state.audio_queue -= to_queue
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ to_queue.each do |a|~
+- Inside source: true
+*** True Line Result
+ to_queue.each do |a|
+** Processing line: ~ args.audio[a[:id]] = a~
+- Inside source: true
+*** True Line Result
+ args.audio[a[:id]] = a
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ args.audio.each do |k, v|~
+- Inside source: true
+*** True Line Result
+ args.audio.each do |k, v|
+** Processing line: ~ if v[:decay_rate]~
+- Inside source: true
+*** True Line Result
+ if v[:decay_rate]
+** Processing line: ~ v[:gain] -= v[:decay_rate]~
+- Inside source: true
+*** True Line Result
+ v[:gain] -= v[:decay_rate]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ sounds_to_stop = args.audio.find_all do |k, v|~
+- Inside source: true
+*** True Line Result
+ sounds_to_stop = args.audio.find_all do |k, v|
+** Processing line: ~ v[:stop_at] && args.state.tick_count >= v[:stop_at]~
+- Inside source: true
+*** True Line Result
+ v[:stop_at] && args.state.tick_count >= v[:stop_at]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ sounds_to_stop.each do |(k, v)|~
+- Inside source: true
+*** True Line Result
+ sounds_to_stop.each do |(k, v)|
+** Processing line: ~ args.audio.delete k~
+- Inside source: true
+*** True Line Result
+ args.audio.delete k
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def graph_sine_wave args, sine_wave, frequency~
+- Inside source: true
+*** True Line Result
+ def graph_sine_wave args, sine_wave, frequency
+** Processing line: ~ if args.state.tick_count != args.state.graphed_at~
+- Inside source: true
+*** True Line Result
+ if args.state.tick_count != args.state.graphed_at
+** Processing line: ~ args.outputs.static_lines.clear~
+- Inside source: true
+*** True Line Result
+ args.outputs.static_lines.clear
+** Processing line: ~ args.outputs.static_sprites.clear~
+- Inside source: true
+*** True Line Result
+ args.outputs.static_sprites.clear
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ r, g, b = frequency.to_i % 80, frequency.to_i % 128, frequency.to_i % 255~
+- Inside source: true
+*** True Line Result
+ r, g, b = frequency.to_i % 80, frequency.to_i % 128, frequency.to_i % 255
+** Processing line: ~ center_row = args.layout.rect(row: 5, col: 9)~
+- Inside source: true
+*** True Line Result
+ center_row = args.layout.rect(row: 5, col: 9)
+** Processing line: ~ x_scale = 20~
+- Inside source: true
+*** True Line Result
+ x_scale = 20
+** Processing line: ~ y_scale = 100~
+- Inside source: true
+*** True Line Result
+ y_scale = 100
+** Processing line: ~ max_points = 20~
+- Inside source: true
+*** True Line Result
+ max_points = 20
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ points = sine_wave~
+- Inside source: true
+*** True Line Result
+ points = sine_wave
+** Processing line: ~ if sine_wave.length > max_points~
+- Inside source: true
+*** True Line Result
+ if sine_wave.length > max_points
+** Processing line: ~ resolution = sine_wave.length.idiv max_points~
+- Inside source: true
+*** True Line Result
+ resolution = sine_wave.length.idiv max_points
+** Processing line: ~ points = sine_wave.find_all~
+- Inside source: true
+*** True Line Result
+ points = sine_wave.find_all
+** Processing line: ~ .with_index { |y, i| i % resolution == 0 }~
+- Inside source: true
+*** True Line Result
+ .with_index { |y, i| i % resolution == 0 }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ args.outputs.static_lines << points.map_with_index do |y, x|~
+- Inside source: true
+*** True Line Result
+ args.outputs.static_lines << points.map_with_index do |y, x|
+** Processing line: ~ next_y = points[x + 1]~
+- Inside source: true
+*** True Line Result
+ next_y = points[x + 1]
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if next_y~
+- Inside source: true
+*** True Line Result
+ if next_y
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ x: center_row.x + (x * x_scale),~
+- Inside source: true
+*** True Line Result
+ x: center_row.x + (x * x_scale),
+** Processing line: ~ y: center_row.y + center_row.h.half + y_scale * y,~
+- Inside source: true
+*** True Line Result
+ y: center_row.y + center_row.h.half + y_scale * y,
+** Processing line: ~ x2: center_row.x + ((x + 1) * x_scale),~
+- Inside source: true
+*** True Line Result
+ x2: center_row.x + ((x + 1) * x_scale),
+** Processing line: ~ y2: center_row.y + center_row.h.half + y_scale * next_y,~
+- Inside source: true
+*** True Line Result
+ y2: center_row.y + center_row.h.half + y_scale * next_y,
+** Processing line: ~ r: r,~
+- Inside source: true
+*** True Line Result
+ r: r,
+** Processing line: ~ g: g,~
+- Inside source: true
+*** True Line Result
+ g: g,
+** Processing line: ~ b: b~
+- Inside source: true
+*** True Line Result
+ b: b
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ args.outputs.static_sprites << points.map_with_index do |y, x|~
+- Inside source: true
+*** True Line Result
+ args.outputs.static_sprites << points.map_with_index do |y, x|
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ x: (center_row.x + (x * x_scale)) - 1,~
+- Inside source: true
+*** True Line Result
+ x: (center_row.x + (x * x_scale)) - 1,
+** Processing line: ~ y: (center_row.y + center_row.h.half + y_scale * y) - 1,~
+- Inside source: true
+*** True Line Result
+ y: (center_row.y + center_row.h.half + y_scale * y) - 1,
+** Processing line: ~ w: 2,~
+- Inside source: true
+*** True Line Result
+ w: 2,
+** Processing line: ~ h: 2,~
+- Inside source: true
+*** True Line Result
+ h: 2,
+** Processing line: ~ path: 'sprites/square-black.png'~
+- Inside source: true
+*** True Line Result
+ path: 'sprites/square-black.png'
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ args.state.graphed_at = args.state.tick_count~
+- Inside source: true
+*** True Line Result
+ args.state.graphed_at = args.state.tick_count
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def defaults_period_sine_wave_for~
+- Inside source: true
+*** True Line Result
+ def defaults_period_sine_wave_for
+** Processing line: ~ { frequency: 440, sample_rate: 48000 }~
+- Inside source: true
+*** True Line Result
+ { frequency: 440, sample_rate: 48000 }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def sine_wave_for opts = { }~
+- Inside source: true
+*** True Line Result
+ def sine_wave_for opts = { }
+** Processing line: ~ opts = defaults_period_sine_wave_for.merge opts~
+- Inside source: true
+*** True Line Result
+ opts = defaults_period_sine_wave_for.merge opts
+** Processing line: ~ frequency = opts[:frequency]~
+- Inside source: true
+*** True Line Result
+ frequency = opts[:frequency]
+** Processing line: ~ sample_rate = opts[:sample_rate]~
+- Inside source: true
+*** True Line Result
+ sample_rate = opts[:sample_rate]
+** Processing line: ~ period_size = (sample_rate.fdiv frequency).ceil~
+- Inside source: true
+*** True Line Result
+ period_size = (sample_rate.fdiv frequency).ceil
+** Processing line: ~ period_size.map_with_index do |i|~
+- Inside source: true
+*** True Line Result
+ period_size.map_with_index do |i|
+** Processing line: ~ Math::sin((2.0 * Math::PI) / (sample_rate.to_f / frequency.to_f) * i)~
+- Inside source: true
+*** True Line Result
+ Math::sin((2.0 * Math::PI) / (sample_rate.to_f / frequency.to_f) * i)
+** Processing line: ~ end.to_a~
+- Inside source: true
+*** True Line Result
+ end.to_a
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def generate_audio_data sine_wave, sample_rate~
+- Inside source: true
+*** True Line Result
+ def generate_audio_data sine_wave, sample_rate
+** Processing line: ~ sample_size = (sample_rate.fdiv (1000.fdiv 60)).ceil~
+- Inside source: true
+*** True Line Result
+ sample_size = (sample_rate.fdiv (1000.fdiv 60)).ceil
+** Processing line: ~ copy_count = (sample_size.fdiv sine_wave.length).ceil~
+- Inside source: true
+*** True Line Result
+ copy_count = (sample_size.fdiv sine_wave.length).ceil
+** Processing line: ~ sine_wave * copy_count~
+- Inside source: true
+*** True Line Result
+ sine_wave * copy_count
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def defaults_queue_sine_wave~
+- Inside source: true
+*** True Line Result
+ def defaults_queue_sine_wave
+** Processing line: ~ { frequency: 440, duration: 60, gain: 1.0, fade_out: false, queue_in: 0 }~
+- Inside source: true
+*** True Line Result
+ { frequency: 440, duration: 60, gain: 1.0, fade_out: false, queue_in: 0 }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def queue_sine_wave args, opts = { }~
+- Inside source: true
+*** True Line Result
+ def queue_sine_wave args, opts = { }
+** Processing line: ~ opts = defaults_queue_sine_wave.merge opts~
+- Inside source: true
+*** True Line Result
+ opts = defaults_queue_sine_wave.merge opts
+** Processing line: ~ decay_rate = 0~
+- Inside source: true
+*** True Line Result
+ decay_rate = 0
+** Processing line: ~ decay_rate = 1.fdiv(opts[:duration]) * opts[:gain] if opts[:fade_out]~
+- Inside source: true
+*** True Line Result
+ decay_rate = 1.fdiv(opts[:duration]) * opts[:gain] if opts[:fade_out]
+** Processing line: ~ frequency = opts[:frequency]~
+- Inside source: true
+*** True Line Result
+ frequency = opts[:frequency]
+** Processing line: ~ sample_rate = 48000~
+- Inside source: true
+*** True Line Result
+ sample_rate = 48000
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ audio_state = {~
+- Inside source: true
+*** True Line Result
+ audio_state = {
+** Processing line: ~ id: (new_id! args),~
+- Inside source: true
+*** True Line Result
+ id: (new_id! args),
+** Processing line: ~ frequency: frequency,~
+- Inside source: true
+*** True Line Result
+ frequency: frequency,
+** Processing line: ~ sample_rate: 48000,~
+- Inside source: true
+*** True Line Result
+ sample_rate: 48000,
+** Processing line: ~ stop_at: args.tick_count + opts[:queue_in] + opts[:duration],~
+- Inside source: true
+*** True Line Result
+ stop_at: args.tick_count + opts[:queue_in] + opts[:duration],
+** Processing line: ~ gain: opts[:gain].to_f,~
+- Inside source: true
+*** True Line Result
+ gain: opts[:gain].to_f,
+** Processing line: ~ queue_at: args.state.tick_count + opts[:queue_in],~
+- Inside source: true
+*** True Line Result
+ queue_at: args.state.tick_count + opts[:queue_in],
+** Processing line: ~ decay_rate: decay_rate,~
+- Inside source: true
+*** True Line Result
+ decay_rate: decay_rate,
+** Processing line: ~ pitch: 1.0,~
+- Inside source: true
+*** True Line Result
+ pitch: 1.0,
+** Processing line: ~ looping: true,~
+- Inside source: true
+*** True Line Result
+ looping: true,
+** Processing line: ~ paused: false~
+- Inside source: true
+*** True Line Result
+ paused: false
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ sine_wave = sine_wave_for frequency: frequency, sample_rate: sample_rate~
+- Inside source: true
+*** True Line Result
+ sine_wave = sine_wave_for frequency: frequency, sample_rate: sample_rate
+** Processing line: ~ args.state.sine_waves[frequency] ||= sine_wave_for frequency: frequency, sample_rate: sample_rate~
+- Inside source: true
+*** True Line Result
+ args.state.sine_waves[frequency] ||= sine_wave_for frequency: frequency, sample_rate: sample_rate
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ proc = lambda do~
+- Inside source: true
+*** True Line Result
+ proc = lambda do
+** Processing line: ~ generate_audio_data args.state.sine_waves[frequency], sample_rate~
+- Inside source: true
+*** True Line Result
+ generate_audio_data args.state.sine_waves[frequency], sample_rate
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ audio_state[:input] = [1, sample_rate, proc]~
+- Inside source: true
+*** True Line Result
+ audio_state[:input] = [1, sample_rate, proc]
+** Processing line: ~ graph_sine_wave args, sine_wave, frequency~
+- Inside source: true
+*** True Line Result
+ graph_sine_wave args, sine_wave, frequency
+** Processing line: ~ args.state.audio_queue << audio_state~
+- Inside source: true
+*** True Line Result
+ args.state.audio_queue << audio_state
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def defaults_queue_bell~
+- Inside source: true
+*** True Line Result
+ def defaults_queue_bell
+** Processing line: ~ { frequency: 440, duration: 1.seconds, queue_in: 0 }~
+- Inside source: true
+*** True Line Result
+ { frequency: 440, duration: 1.seconds, queue_in: 0 }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def queue_bell args, opts = {}~
+- Inside source: true
+*** True Line Result
+ def queue_bell args, opts = {}
+** Processing line: ~ (bell_to_sine_waves (defaults_queue_bell.merge opts)).each { |b| queue_sine_wave args, b }~
+- Inside source: true
+*** True Line Result
+ (bell_to_sine_waves (defaults_queue_bell.merge opts)).each { |b| queue_sine_wave args, b }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def bell_harmonics~
+- Inside source: true
+*** True Line Result
+ def bell_harmonics
+** Processing line: ~ [~
+- Inside source: true
+*** True Line Result
+ [
+** Processing line: ~ { frequency_ratio: 0.5, duration_ratio: 1.00 },~
+- Inside source: true
+*** True Line Result
+ { frequency_ratio: 0.5, duration_ratio: 1.00 },
+** Processing line: ~ { frequency_ratio: 1.0, duration_ratio: 0.80 },~
+- Inside source: true
+*** True Line Result
+ { frequency_ratio: 1.0, duration_ratio: 0.80 },
+** Processing line: ~ { frequency_ratio: 2.0, duration_ratio: 0.60 },~
+- Inside source: true
+*** True Line Result
+ { frequency_ratio: 2.0, duration_ratio: 0.60 },
+** Processing line: ~ { frequency_ratio: 3.0, duration_ratio: 0.40 },~
+- Inside source: true
+*** True Line Result
+ { frequency_ratio: 3.0, duration_ratio: 0.40 },
+** Processing line: ~ { frequency_ratio: 4.2, duration_ratio: 0.25 },~
+- Inside source: true
+*** True Line Result
+ { frequency_ratio: 4.2, duration_ratio: 0.25 },
+** Processing line: ~ { frequency_ratio: 5.4, duration_ratio: 0.20 },~
+- Inside source: true
+*** True Line Result
+ { frequency_ratio: 5.4, duration_ratio: 0.20 },
+** Processing line: ~ { frequency_ratio: 6.8, duration_ratio: 0.15 }~
+- Inside source: true
+*** True Line Result
+ { frequency_ratio: 6.8, duration_ratio: 0.15 }
+** Processing line: ~ ]~
+- Inside source: true
+*** True Line Result
+ ]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def bell_to_sine_waves opts~
+- Inside source: true
+*** True Line Result
+ def bell_to_sine_waves opts
+** Processing line: ~ bell_harmonics.map do |b|~
+- Inside source: true
+*** True Line Result
+ bell_harmonics.map do |b|
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ frequency: opts[:frequency] * b[:frequency_ratio],~
+- Inside source: true
+*** True Line Result
+ frequency: opts[:frequency] * b[:frequency_ratio],
+** Processing line: ~ duration: opts[:duration] * b[:duration_ratio],~
+- Inside source: true
+*** True Line Result
+ duration: opts[:duration] * b[:duration_ratio],
+** Processing line: ~ queue_in: opts[:queue_in],~
+- Inside source: true
+*** True Line Result
+ queue_in: opts[:queue_in],
+** Processing line: ~ gain: (1.fdiv bell_harmonics.length),~
+- Inside source: true
+*** True Line Result
+ gain: (1.fdiv bell_harmonics.length),
+** Processing line: ~ fade_out: true~
+- Inside source: true
+*** True Line Result
+ fade_out: true
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def defaults_frequency_for~
+- Inside source: true
+*** True Line Result
+ def defaults_frequency_for
+** Processing line: ~ { note: :a, octave: 5, sharp: false, flat: false }~
+- Inside source: true
+*** True Line Result
+ { note: :a, octave: 5, sharp: false, flat: false }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def frequency_for opts = {}~
+- Inside source: true
+*** True Line Result
+ def frequency_for opts = {}
+** Processing line: ~ opts = defaults_frequency_for.merge opts~
+- Inside source: true
+*** True Line Result
+ opts = defaults_frequency_for.merge opts
+** Processing line: ~ octave_offset_multiplier = opts[:octave] - 5~
+- Inside source: true
+*** True Line Result
+ octave_offset_multiplier = opts[:octave] - 5
+** Processing line: ~ note = note_frequencies_octave_5[opts[:note]]~
+- Inside source: true
+*** True Line Result
+ note = note_frequencies_octave_5[opts[:note]]
+** Processing line: ~ if octave_offset_multiplier < 0~
+- Inside source: true
+*** True Line Result
+ if octave_offset_multiplier < 0
+** Processing line: ~ note = note * 1 / (octave_offset_multiplier.abs + 1)~
+- Inside source: true
+*** True Line Result
+ note = note * 1 / (octave_offset_multiplier.abs + 1)
+** Processing line: ~ elsif octave_offset_multiplier > 0~
+- Inside source: true
+*** True Line Result
+ elsif octave_offset_multiplier > 0
+** Processing line: ~ note = note * (octave_offset_multiplier.abs + 1) / 1~
+- Inside source: true
+*** True Line Result
+ note = note * (octave_offset_multiplier.abs + 1) / 1
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ note~
+- Inside source: true
+*** True Line Result
+ note
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def note_frequencies_octave_5~
+- Inside source: true
+*** True Line Result
+ def note_frequencies_octave_5
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ a: 440.0,~
+- Inside source: true
+*** True Line Result
+ a: 440.0,
+** Processing line: ~ a_sharp: 466.16, b_flat: 466.16,~
+- Inside source: true
+*** True Line Result
+ a_sharp: 466.16, b_flat: 466.16,
+** Processing line: ~ b: 493.88,~
+- Inside source: true
+*** True Line Result
+ b: 493.88,
+** Processing line: ~ c: 523.25,~
+- Inside source: true
+*** True Line Result
+ c: 523.25,
+** Processing line: ~ c_sharp: 554.37, d_flat: 587.33,~
+- Inside source: true
+*** True Line Result
+ c_sharp: 554.37, d_flat: 587.33,
+** Processing line: ~ d: 587.33,~
+- Inside source: true
+*** True Line Result
+ d: 587.33,
+** Processing line: ~ d_sharp: 622.25, e_flat: 659.25,~
+- Inside source: true
+*** True Line Result
+ d_sharp: 622.25, e_flat: 659.25,
+** Processing line: ~ e: 659.25,~
+- Inside source: true
+*** True Line Result
+ e: 659.25,
+** Processing line: ~ f: 698.25,~
+- Inside source: true
+*** True Line Result
+ f: 698.25,
+** Processing line: ~ f_sharp: 739.99, g_flat: 739.99,~
+- Inside source: true
+*** True Line Result
+ f_sharp: 739.99, g_flat: 739.99,
+** Processing line: ~ g: 783.99,~
+- Inside source: true
+*** True Line Result
+ g: 783.99,
+** Processing line: ~ g_sharp: 830.61, a_flat: 830.61~
+- Inside source: true
+*** True Line Result
+ g_sharp: 830.61, a_flat: 830.61
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def new_id! args~
+- Inside source: true
+*** True Line Result
+ def new_id! args
+** Processing line: ~ args.state.audio_id ||= 0~
+- Inside source: true
+*** True Line Result
+ args.state.audio_id ||= 0
+** Processing line: ~ args.state.audio_id += 1~
+- Inside source: true
+*** True Line Result
+ args.state.audio_id += 1
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def button args, opts~
+- Inside source: true
+*** True Line Result
+ def button args, opts
+** Processing line: ~ button_def = opts.merge rect: (args.layout.rect (opts.merge w: 2, h: 1))~
+- Inside source: true
+*** True Line Result
+ button_def = opts.merge rect: (args.layout.rect (opts.merge w: 2, h: 1))
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ button_def[:border] = button_def[:rect].merge r: 0, g: 0, b: 0~
+- Inside source: true
+*** True Line Result
+ button_def[:border] = button_def[:rect].merge r: 0, g: 0, b: 0
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ font_size_enum = args.layout.font_relative_size_enum 0~
+- Inside source: true
+*** True Line Result
+ font_size_enum = args.layout.font_relative_size_enum 0
+** Processing line: ~ label_offset_x = 4~
+- Inside source: true
+*** True Line Result
+ label_offset_x = 4
+** Processing line: ~ label_offset_y = button_def[:rect].h.half + button_def[:rect].h.idiv(4)~
+- Inside source: true
+*** True Line Result
+ label_offset_y = button_def[:rect].h.half + button_def[:rect].h.idiv(4)
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ button_def[:label] = button_def[:rect].merge text: opts[:text],~
+- Inside source: true
+*** True Line Result
+ button_def[:label] = button_def[:rect].merge text: opts[:text],
+** Processing line: ~ size_enum: font_size_enum,~
+- Inside source: true
+*** True Line Result
+ size_enum: font_size_enum,
+** Processing line: ~ x: button_def[:rect].x + label_offset_x,~
+- Inside source: true
+*** True Line Result
+ x: button_def[:rect].x + label_offset_x,
+** Processing line: ~ y: button_def[:rect].y + label_offset_y~
+- Inside source: true
+*** True Line Result
+ y: button_def[:rect].y + label_offset_y
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ button_def~
+- Inside source: true
+*** True Line Result
+ button_def
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ $gtk.reset~
+- Inside source: true
+*** True Line Result
+ $gtk.reset
** Processing line: ~~
- Inside source: true
*** True Line Result
@@ -15699,6 +17211,202 @@ Follows is a source code listing for all files that have been open sourced. This
- End of paragraph detected.
*** True Line Result
+** Processing line: ~* Input Basics - Touch - main.rb~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* Input Basics - Touch - main.rb
+** Processing line: ~#+begin_src ruby~
+- Line was identified as the beginning of a code block.
+*** True Line Result
+
+*** True Line Result
+#+begin_src ruby
+** Processing line: ~ # ./samples/02_input_basics/06_touch/app/main.rb~
+- Inside source: true
+*** True Line Result
+ # ./samples/02_input_basics/06_touch/app/main.rb
+** Processing line: ~ def tick args~
+- Inside source: true
+*** True Line Result
+ def tick args
+** Processing line: ~ args.outputs.background_color = [ 0, 0, 0 ]~
+- Inside source: true
+*** True Line Result
+ args.outputs.background_color = [ 0, 0, 0 ]
+** Processing line: ~ args.outputs.primitives << [640, 700, "Touch your screen.", 5, 1, 255, 255, 255].label~
+- Inside source: true
+*** True Line Result
+ args.outputs.primitives << [640, 700, "Touch your screen.", 5, 1, 255, 255, 255].label
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # If you don't want to get fancy, you can just look for finger_one~
+- Inside source: true
+*** True Line Result
+ # If you don't want to get fancy, you can just look for finger_one
+** Processing line: ~ # (and _two, if you like), which are assigned in the order new touches hit~
+- Inside source: true
+*** True Line Result
+ # (and _two, if you like), which are assigned in the order new touches hit
+** Processing line: ~ # the screen. If not nil, they are touching right now, and are just~
+- Inside source: true
+*** True Line Result
+ # the screen. If not nil, they are touching right now, and are just
+** Processing line: ~ # references to specific items in the args.input.touch hash.~
+- Inside source: true
+*** True Line Result
+ # references to specific items in the args.input.touch hash.
+** Processing line: ~ # If finger_one lifts off, it will become nil, but finger_two, if it was~
+- Inside source: true
+*** True Line Result
+ # If finger_one lifts off, it will become nil, but finger_two, if it was
+** Processing line: ~ # touching, remains until it also lifts off. When all fingers lift off, the~
+- Inside source: true
+*** True Line Result
+ # touching, remains until it also lifts off. When all fingers lift off, the
+** Processing line: ~ # the next new touch will be finger_one again, but until then, new touches~
+- Inside source: true
+*** True Line Result
+ # the next new touch will be finger_one again, but until then, new touches
+** Processing line: ~ # don't fill in earlier slots.~
+- Inside source: true
+*** True Line Result
+ # don't fill in earlier slots.
+** Processing line: ~ if !args.inputs.finger_one.nil?~
+- Inside source: true
+*** True Line Result
+ if !args.inputs.finger_one.nil?
+** Processing line: ~ args.outputs.primitives << [640, 650, "Finger #1 is touching at (#{args.inputs.finger_one.x}, #{args.inputs.finger_one.y}).", 5, 1, 255, 255, 255].label~
+- Inside source: true
+*** True Line Result
+ args.outputs.primitives << [640, 650, "Finger #1 is touching at (#{args.inputs.finger_one.x}, #{args.inputs.finger_one.y}).", 5, 1, 255, 255, 255].label
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ if !args.inputs.finger_two.nil?~
+- Inside source: true
+*** True Line Result
+ if !args.inputs.finger_two.nil?
+** Processing line: ~ args.outputs.primitives << [640, 600, "Finger #2 is touching at (#{args.inputs.finger_two.x}, #{args.inputs.finger_two.y}).", 5, 1, 255, 255, 255].label~
+- Inside source: true
+*** True Line Result
+ args.outputs.primitives << [640, 600, "Finger #2 is touching at (#{args.inputs.finger_two.x}, #{args.inputs.finger_two.y}).", 5, 1, 255, 255, 255].label
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # Here's the more flexible interface: this will report as many simultaneous~
+- Inside source: true
+*** True Line Result
+ # Here's the more flexible interface: this will report as many simultaneous
+** Processing line: ~ # touches as the system can handle, but it's a little more effort to track~
+- Inside source: true
+*** True Line Result
+ # touches as the system can handle, but it's a little more effort to track
+** Processing line: ~ # them. Each item in the args.input.touch hash has a unique key (an~
+- Inside source: true
+*** True Line Result
+ # them. Each item in the args.input.touch hash has a unique key (an
+** Processing line: ~ # incrementing integer) that exists until the finger lifts off. You can~
+- Inside source: true
+*** True Line Result
+ # incrementing integer) that exists until the finger lifts off. You can
+** Processing line: ~ # tell which order the touches happened globally by the key value, or~
+- Inside source: true
+*** True Line Result
+ # tell which order the touches happened globally by the key value, or
+** Processing line: ~ # by the touch[id].touch_order field, which resets to zero each time all~
+- Inside source: true
+*** True Line Result
+ # by the touch[id].touch_order field, which resets to zero each time all
+** Processing line: ~ # touches have lifted.~
+- Inside source: true
+*** True Line Result
+ # touches have lifted.
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ args.state.colors ||= [~
+- Inside source: true
+*** True Line Result
+ args.state.colors ||= [
+** Processing line: ~ 0xFF0000, 0x00FF00, 0x1010FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF~
+- Inside source: true
+*** True Line Result
+ 0xFF0000, 0x00FF00, 0x1010FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF
+** Processing line: ~ ]~
+- Inside source: true
+*** True Line Result
+ ]
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ size = 100~
+- Inside source: true
+*** True Line Result
+ size = 100
+** Processing line: ~ args.inputs.touch.each { |k,v|~
+- Inside source: true
+*** True Line Result
+ args.inputs.touch.each { |k,v|
+** Processing line: ~ color = args.state.colors[v.touch_order % 7]~
+- Inside source: true
+*** True Line Result
+ color = args.state.colors[v.touch_order % 7]
+** Processing line: ~ r = (color & 0xFF0000) >> 16~
+- Inside source: true
+*** True Line Result
+ r = (color & 0xFF0000) >> 16
+** Processing line: ~ g = (color & 0x00FF00) >> 8~
+- Inside source: true
+*** True Line Result
+ g = (color & 0x00FF00) >> 8
+** Processing line: ~ b = (color & 0x0000FF)~
+- Inside source: true
+*** True Line Result
+ b = (color & 0x0000FF)
+** Processing line: ~ args.outputs.primitives << [v.x - (size / 2), v.y + (size / 2), size, size, r, g, b, 255].solid~
+- Inside source: true
+*** True Line Result
+ args.outputs.primitives << [v.x - (size / 2), v.y + (size / 2), size, size, r, g, b, 255].solid
+** Processing line: ~ args.outputs.primitives << [v.x, v.y + size, k.to_s, 0, 1, 0, 0, 0].label~
+- Inside source: true
+*** True Line Result
+ args.outputs.primitives << [v.x, v.y + size, k.to_s, 0, 1, 0, 0, 0].label
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~#+end_src~
+- Line was identified as the end of a code block.
+*** True Line Result
+#+end_src
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
** Processing line: ~* Rendering Sprites - Animation Using Separate Pngs - main.rb~
- Header detected.
*** True Line Result
@@ -33967,6 +35675,198 @@ Follows is a source code listing for all files that have been open sourced. This
- End of paragraph detected.
*** True Line Result
+** Processing line: ~* Advanced Rendering - Pixel Arrays - main.rb~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* Advanced Rendering - Pixel Arrays - main.rb
+** Processing line: ~#+begin_src ruby~
+- Line was identified as the beginning of a code block.
+*** True Line Result
+
+*** True Line Result
+#+begin_src ruby
+** Processing line: ~ # ./samples/07_advanced_rendering/06_pixel_arrays/app/main.rb~
+- Inside source: true
+*** True Line Result
+ # ./samples/07_advanced_rendering/06_pixel_arrays/app/main.rb
+** Processing line: ~ $gtk.reset~
+- Inside source: true
+*** True Line Result
+ $gtk.reset
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def tick args~
+- Inside source: true
+*** True Line Result
+ def tick args
+** Processing line: ~ args.state.posinc ||= 1~
+- Inside source: true
+*** True Line Result
+ args.state.posinc ||= 1
+** Processing line: ~ args.state.pos ||= 0~
+- Inside source: true
+*** True Line Result
+ args.state.pos ||= 0
+** Processing line: ~ args.state.rotation ||= 0~
+- Inside source: true
+*** True Line Result
+ args.state.rotation ||= 0
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ dimension = 10 # keep it small and let the GPU scale it when rendering the sprite.~
+- Inside source: true
+*** True Line Result
+ dimension = 10 # keep it small and let the GPU scale it when rendering the sprite.
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # Set up our "scanner" pixel array and fill it with black pixels.~
+- Inside source: true
+*** True Line Result
+ # Set up our "scanner" pixel array and fill it with black pixels.
+** Processing line: ~ args.pixel_array(:scanner).width = dimension~
+- Inside source: true
+*** True Line Result
+ args.pixel_array(:scanner).width = dimension
+** Processing line: ~ args.pixel_array(:scanner).height = dimension~
+- Inside source: true
+*** True Line Result
+ args.pixel_array(:scanner).height = dimension
+** Processing line: ~ args.pixel_array(:scanner).pixels.fill(0xFF000000, 0, dimension * dimension) # black, full alpha~
+- Inside source: true
+*** True Line Result
+ args.pixel_array(:scanner).pixels.fill(0xFF000000, 0, dimension * dimension) # black, full alpha
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # Draw a green line that bounces up and down the sprite.~
+- Inside source: true
+*** True Line Result
+ # Draw a green line that bounces up and down the sprite.
+** Processing line: ~ args.pixel_array(:scanner).pixels.fill(0xFF00FF00, dimension * args.state.pos, dimension) # green, full alpha~
+- Inside source: true
+*** True Line Result
+ args.pixel_array(:scanner).pixels.fill(0xFF00FF00, dimension * args.state.pos, dimension) # green, full alpha
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # Adjust position for next frame.~
+- Inside source: true
+*** True Line Result
+ # Adjust position for next frame.
+** Processing line: ~ args.state.pos += args.state.posinc~
+- Inside source: true
+*** True Line Result
+ args.state.pos += args.state.posinc
+** Processing line: ~ if args.state.posinc > 0 && args.state.pos >= dimension~
+- Inside source: true
+*** True Line Result
+ if args.state.posinc > 0 && args.state.pos >= dimension
+** Processing line: ~ args.state.posinc = -1~
+- Inside source: true
+*** True Line Result
+ args.state.posinc = -1
+** Processing line: ~ args.state.pos = dimension - 1~
+- Inside source: true
+*** True Line Result
+ args.state.pos = dimension - 1
+** Processing line: ~ elsif args.state.posinc < 0 && args.state.pos < 0~
+- Inside source: true
+*** True Line Result
+ elsif args.state.posinc < 0 && args.state.pos < 0
+** Processing line: ~ args.state.posinc = 1~
+- Inside source: true
+*** True Line Result
+ args.state.posinc = 1
+** Processing line: ~ args.state.pos = 1~
+- Inside source: true
+*** True Line Result
+ args.state.pos = 1
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # New/changed pixel arrays get uploaded to the GPU before we render~
+- Inside source: true
+*** True Line Result
+ # New/changed pixel arrays get uploaded to the GPU before we render
+** Processing line: ~ # anything. At that point, they can be scaled, rotated, and otherwise~
+- Inside source: true
+*** True Line Result
+ # anything. At that point, they can be scaled, rotated, and otherwise
+** Processing line: ~ # used like any other sprite.~
+- Inside source: true
+*** True Line Result
+ # used like any other sprite.
+** Processing line: ~ w = 100~
+- Inside source: true
+*** True Line Result
+ w = 100
+** Processing line: ~ h = 100~
+- Inside source: true
+*** True Line Result
+ h = 100
+** Processing line: ~ x = (1280 - w) / 2~
+- Inside source: true
+*** True Line Result
+ x = (1280 - w) / 2
+** Processing line: ~ y = (720 - h) / 2~
+- Inside source: true
+*** True Line Result
+ y = (720 - h) / 2
+** Processing line: ~ args.outputs.background_color = [64, 0, 128]~
+- Inside source: true
+*** True Line Result
+ args.outputs.background_color = [64, 0, 128]
+** Processing line: ~ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite~
+- Inside source: true
+*** True Line Result
+ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite
+** Processing line: ~ args.state.rotation += 1~
+- Inside source: true
+*** True Line Result
+ args.state.rotation += 1
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ args.outputs.primitives << args.gtk.current_framerate_primitives~
+- Inside source: true
+*** True Line Result
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~#+end_src~
+- Line was identified as the end of a code block.
+*** True Line Result
+#+end_src
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
** Processing line: ~* Tweening Lerping Easing Functions - Easing Functions - main.rb~
- Header detected.
*** True Line Result
@@ -40391,6 +42291,122 @@ Follows is a source code listing for all files that have been open sourced. This
- End of paragraph detected.
*** True Line Result
+** Processing line: ~* 12 C Extensions - Native Pixel Arrays - main.rb~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* 12 C Extensions - Native Pixel Arrays - main.rb
+** Processing line: ~#+begin_src ruby~
+- Line was identified as the beginning of a code block.
+*** True Line Result
+
+*** True Line Result
+#+begin_src ruby
+** Processing line: ~ # ./samples/12_c_extensions/03_native_pixel_arrays/app/main.rb~
+- Inside source: true
+*** True Line Result
+ # ./samples/12_c_extensions/03_native_pixel_arrays/app/main.rb
+** Processing line: ~ $gtk.ffi_misc.gtk_dlopen("ext")~
+- Inside source: true
+*** True Line Result
+ $gtk.ffi_misc.gtk_dlopen("ext")
+** Processing line: ~ include FFI::CExt~
+- Inside source: true
+*** True Line Result
+ include FFI::CExt
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def tick args~
+- Inside source: true
+*** True Line Result
+ def tick args
+** Processing line: ~ args.state.rotation ||= 0~
+- Inside source: true
+*** True Line Result
+ args.state.rotation ||= 0
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ update_scanner_texture # this calls into a C extension!~
+- Inside source: true
+*** True Line Result
+ update_scanner_texture # this calls into a C extension!
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # New/changed pixel arrays get uploaded to the GPU before we render~
+- Inside source: true
+*** True Line Result
+ # New/changed pixel arrays get uploaded to the GPU before we render
+** Processing line: ~ # anything. At that point, they can be scaled, rotated, and otherwise~
+- Inside source: true
+*** True Line Result
+ # anything. At that point, they can be scaled, rotated, and otherwise
+** Processing line: ~ # used like any other sprite.~
+- Inside source: true
+*** True Line Result
+ # used like any other sprite.
+** Processing line: ~ w = 100~
+- Inside source: true
+*** True Line Result
+ w = 100
+** Processing line: ~ h = 100~
+- Inside source: true
+*** True Line Result
+ h = 100
+** Processing line: ~ x = (1280 - w) / 2~
+- Inside source: true
+*** True Line Result
+ x = (1280 - w) / 2
+** Processing line: ~ y = (720 - h) / 2~
+- Inside source: true
+*** True Line Result
+ y = (720 - h) / 2
+** Processing line: ~ args.outputs.background_color = [64, 0, 128]~
+- Inside source: true
+*** True Line Result
+ args.outputs.background_color = [64, 0, 128]
+** Processing line: ~ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite~
+- Inside source: true
+*** True Line Result
+ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite
+** Processing line: ~ args.state.rotation += 1~
+- Inside source: true
+*** True Line Result
+ args.state.rotation += 1
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ args.outputs.primitives << args.gtk.current_framerate_primitives~
+- Inside source: true
+*** True Line Result
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~#+end_src~
+- Line was identified as the end of a code block.
+*** True Line Result
+#+end_src
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
** Processing line: ~* 3d - 3d Cube - main.rb~
- Header detected.
*** True Line Result
@@ -63175,102 +65191,6 @@ Follows is a source code listing for all files that have been open sourced. This
- End of paragraph detected.
*** True Line Result
-** Processing line: ~* Platformer - Gorillas Basic - repl.rb~
-- Header detected.
-*** True Line Result
-
-*** True Line Result
-* Platformer - Gorillas Basic - repl.rb
-** Processing line: ~#+begin_src ruby~
-- Line was identified as the beginning of a code block.
-*** True Line Result
-
-*** True Line Result
-#+begin_src ruby
-** Processing line: ~ # ./samples/99_genre_platformer/gorillas_basic/app/repl.rb~
-- Inside source: true
-*** True Line Result
- # ./samples/99_genre_platformer/gorillas_basic/app/repl.rb
-** Processing line: ~ begin~
-- Inside source: true
-*** True Line Result
- begin
-** Processing line: ~ if $gtk.args.state.current_turn == :player_1_angle~
-- Inside source: true
-*** True Line Result
- if $gtk.args.state.current_turn == :player_1_angle
-** Processing line: ~ $gtk.args.state.player_1_angle = "#{60 + 10.randomize(:ratio).to_i}"~
-- Inside source: true
-*** True Line Result
- $gtk.args.state.player_1_angle = "#{60 + 10.randomize(:ratio).to_i}"
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-- Inside source: true
-*** True Line Result
- $you_so_basic_gorillas.input_execute_turn
-** Processing line: ~ $gtk.args.state.player_1_velocity = "#{30 + 20.randomize(:ratio).to_i}"~
-- Inside source: true
-*** True Line Result
- $gtk.args.state.player_1_velocity = "#{30 + 20.randomize(:ratio).to_i}"
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-- Inside source: true
-*** True Line Result
- $you_so_basic_gorillas.input_execute_turn
-** Processing line: ~ elsif $gtk.args.state.current_turn == :player_2_angle~
-- Inside source: true
-*** True Line Result
- elsif $gtk.args.state.current_turn == :player_2_angle
-** Processing line: ~ $gtk.args.state.player_2_angle = "#{60 + 10.randomize(:ratio).to_i}"~
-- Inside source: true
-*** True Line Result
- $gtk.args.state.player_2_angle = "#{60 + 10.randomize(:ratio).to_i}"
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-- Inside source: true
-*** True Line Result
- $you_so_basic_gorillas.input_execute_turn
-** Processing line: ~ $gtk.args.state.player_2_velocity = "#{30 + 20.randomize(:ratio).to_i}"~
-- Inside source: true
-*** True Line Result
- $gtk.args.state.player_2_velocity = "#{30 + 20.randomize(:ratio).to_i}"
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-- Inside source: true
-*** True Line Result
- $you_so_basic_gorillas.input_execute_turn
-** Processing line: ~ else~
-- Inside source: true
-*** True Line Result
- else
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-- Inside source: true
-*** True Line Result
- $you_so_basic_gorillas.input_execute_turn
-** Processing line: ~ end~
-- Inside source: true
-*** True Line Result
- end
-** Processing line: ~ rescue Exception => e~
-- Inside source: true
-*** True Line Result
- rescue Exception => e
-** Processing line: ~ puts e~
-- Inside source: true
-*** True Line Result
- puts e
-** Processing line: ~ end~
-- Inside source: true
-*** True Line Result
- end
-** Processing line: ~~
-- Inside source: true
-*** True Line Result
-
-** Processing line: ~#+end_src~
-- Line was identified as the end of a code block.
-*** True Line Result
-#+end_src
-** Processing line: ~~
-- End of paragraph detected.
-*** True Line Result
-
** Processing line: ~* Platformer - Gorillas Basic - tests.rb~
- Header detected.
*** True Line Result
@@ -76935,38 +78855,6 @@ Follows is a source code listing for all files that have been open sourced. This
- End of paragraph detected.
*** True Line Result
-** Processing line: ~* Rpg Narrative - Return Of Serenity - repl.rb~
-- Header detected.
-*** True Line Result
-
-*** True Line Result
-* Rpg Narrative - Return Of Serenity - repl.rb
-** Processing line: ~#+begin_src ruby~
-- Line was identified as the beginning of a code block.
-*** True Line Result
-
-*** True Line Result
-#+begin_src ruby
-** Processing line: ~ # ./samples/99_genre_rpg_narrative/return_of_serenity/app/repl.rb~
-- Inside source: true
-*** True Line Result
- # ./samples/99_genre_rpg_narrative/return_of_serenity/app/repl.rb
-** Processing line: ~ puts $gtk.args.state.current_scene~
-- Inside source: true
-*** True Line Result
- puts $gtk.args.state.current_scene
-** Processing line: ~~
-- Inside source: true
-*** True Line Result
-
-** Processing line: ~#+end_src~
-- Line was identified as the end of a code block.
-*** True Line Result
-#+end_src
-** Processing line: ~~
-- End of paragraph detected.
-*** True Line Result
-
** Processing line: ~* Rpg Narrative - Return Of Serenity - require.rb~
- Header detected.
*** True Line Result
@@ -88375,6 +90263,14 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~ attr_accessor :layout~
+- Inside source: true
+*** True Line Result
+ attr_accessor :layout
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ def initialize runtime, recording~
- Inside source: true
*** True Line Result
@@ -88419,6 +90315,10 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
@render_targets = {}
+** Processing line: ~ @pixel_arrays = {}~
+- Inside source: true
+*** True Line Result
+ @pixel_arrays = {}
** Processing line: ~ @all_tests = []~
- Inside source: true
*** True Line Result
@@ -88431,6 +90331,10 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
@wizards = Wizards.new
+** Processing line: ~ @layout = GTK::Layout.new @grid.w, @grid.h~
+- Inside source: true
+*** True Line Result
+ @layout = GTK::Layout.new @grid.w, @grid.h
** Processing line: ~ end~
- Inside source: true
*** True Line Result
@@ -88543,6 +90447,86 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~ def clear_pixel_arrays~
+- Inside source: true
+*** True Line Result
+ def clear_pixel_arrays
+** Processing line: ~ pixel_arrays_clear~
+- Inside source: true
+*** True Line Result
+ pixel_arrays_clear
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def pixel_arrays_clear~
+- Inside source: true
+*** True Line Result
+ def pixel_arrays_clear
+** Processing line: ~ @pixel_arrays = {}~
+- Inside source: true
+*** True Line Result
+ @pixel_arrays = {}
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def pixel_arrays~
+- Inside source: true
+*** True Line Result
+ def pixel_arrays
+** Processing line: ~ @pixel_arrays~
+- Inside source: true
+*** True Line Result
+ @pixel_arrays
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def pixel_array name~
+- Inside source: true
+*** True Line Result
+ def pixel_array name
+** Processing line: ~ name = name.to_s~
+- Inside source: true
+*** True Line Result
+ name = name.to_s
+** Processing line: ~ if !@pixel_arrays[name]~
+- Inside source: true
+*** True Line Result
+ if !@pixel_arrays[name]
+** Processing line: ~ @pixel_arrays[name] = PixelArray.new~
+- Inside source: true
+*** True Line Result
+ @pixel_arrays[name] = PixelArray.new
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ @pixel_arrays[name]~
+- Inside source: true
+*** True Line Result
+ @pixel_arrays[name]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ def clear_render_targets~
- Inside source: true
*** True Line Result
@@ -89667,6 +91651,22 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~ def pixel_arrays~
+- Inside source: true
+*** True Line Result
+ def pixel_arrays
+** Processing line: ~ args.pixel_arrays~
+- Inside source: true
+*** True Line Result
+ args.pixel_arrays
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ def geometry~
- Inside source: true
*** True Line Result
@@ -89999,6 +91999,14 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
class Console
+** Processing line: ~ include ConsoleDeprecated~
+- Inside source: true
+*** True Line Result
+ include ConsoleDeprecated
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ attr_accessor :show_reason, :log, :logo, :background_color,~
- Inside source: true
*** True Line Result
@@ -90279,10 +92287,10 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
-** Processing line: ~ def addsprite obj~
+** Processing line: ~ def add_sprite obj~
- Inside source: true
*** True Line Result
- def addsprite obj
+ def add_sprite obj
** Processing line: ~ @log_invocation_count += 1~
- Inside source: true
*** True Line Result
@@ -90359,18 +92367,18 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
if obj.is_a? Hash
-** Processing line: ~ addsprite obj~
+** Processing line: ~ add_sprite obj~
- Inside source: true
*** True Line Result
- addsprite obj
+ add_sprite obj
** Processing line: ~ else~
- Inside source: true
*** True Line Result
else
-** Processing line: ~ addtext obj~
+** Processing line: ~ add_text obj~
- Inside source: true
*** True Line Result
- addtext obj
+ add_text obj
** Processing line: ~ end~
- Inside source: true
*** True Line Result
@@ -90387,10 +92395,10 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
-** Processing line: ~ def addtext obj~
+** Processing line: ~ def add_text obj~
- Inside source: true
*** True Line Result
- def addtext obj
+ def add_text obj
** Processing line: ~ @last_log_lines_count ||= 1~
- Inside source: true
*** True Line Result
@@ -90883,10 +92891,10 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
dwim_duration = 5.seconds
-** Processing line: ~ addtext "* toast :#{id}"~
+** Processing line: ~ add_text "* toast :#{id}"~
- Inside source: true
*** True Line Result
- addtext "* toast :#{id}"
+ add_text "* toast :#{id}"
** Processing line: ~ puts "* TOAST: :#{id}"~
- Inside source: true
*** True Line Result
@@ -90903,10 +92911,10 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
dwim_duration += lines.length.seconds
-** Processing line: ~ addtext "** #{message}"~
+** Processing line: ~ add_text "** #{message}"~
- Inside source: true
*** True Line Result
- addtext "** #{message}"
+ add_text "** #{message}"
** Processing line: ~ puts "** #{message}"~
- Inside source: true
*** True Line Result
@@ -91775,6 +93783,22 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
end
+** Processing line: ~ elsif args.inputs.keyboard.key_down.left~
+- Inside source: true
+*** True Line Result
+ elsif args.inputs.keyboard.key_down.left
+** Processing line: ~ prompt.move_cursor_left~
+- Inside source: true
+*** True Line Result
+ prompt.move_cursor_left
+** Processing line: ~ elsif args.inputs.keyboard.key_down.right~
+- Inside source: true
+*** True Line Result
+ elsif args.inputs.keyboard.key_down.right
+** Processing line: ~ prompt.move_cursor_right~
+- Inside source: true
+*** True Line Result
+ prompt.move_cursor_right
** Processing line: ~ elsif inputs_scroll_up_full? args~
- Inside source: true
*** True Line Result
@@ -94059,6 +96083,18 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~ @cursor_position = 0~
+- Inside source: true
+*** True Line Result
+ @cursor_position = 0
+** Processing line: ~ update_cursor_position_px~
+- Inside source: true
+*** True Line Result
+ update_cursor_position_px
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ @last_autocomplete_prefix = nil~
- Inside source: true
*** True Line Result
@@ -94075,14 +96111,58 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~ def update_cursor_position_px~
+- Inside source: true
+*** True Line Result
+ def update_cursor_position_px
+** Processing line: ~ @cursor_position_px = ($gtk.calcstringbox (@prompt + @current_input_str[0...@cursor_position]), @font_style.size_enum, @font_style.font).x~
+- Inside source: true
+*** True Line Result
+ @cursor_position_px = ($gtk.calcstringbox (@prompt + @current_input_str[0...@cursor_position]), @font_style.size_enum, @font_style.font).x
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def current_input_str=(str)~
+- Inside source: true
+*** True Line Result
+ def current_input_str=(str)
+** Processing line: ~ @current_input_str = str~
+- Inside source: true
+*** True Line Result
+ @current_input_str = str
+** Processing line: ~ @cursor_position = str.length~
+- Inside source: true
+*** True Line Result
+ @cursor_position = str.length
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ def <<(str)~
- Inside source: true
*** True Line Result
def <<(str)
-** Processing line: ~ @current_input_str << str~
+** Processing line: ~ @current_input_str = @current_input_str[0...@cursor_position] + str + @current_input_str[@cursor_position..-1]~
+- Inside source: true
+*** True Line Result
+ @current_input_str = @current_input_str[0...@cursor_position] + str + @current_input_str[@cursor_position..-1]
+** Processing line: ~ @cursor_position += str.length~
- Inside source: true
*** True Line Result
- @current_input_str << str
+ @cursor_position += str.length
+** Processing line: ~ update_cursor_position_px~
+- Inside source: true
+*** True Line Result
+ update_cursor_position_px
** Processing line: ~ @current_input_changed_at = Kernel.global_tick_count~
- Inside source: true
*** True Line Result
@@ -94103,10 +96183,26 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
def backspace
-** Processing line: ~ @current_input_str.chop!~
+** Processing line: ~ return if current_input_str.length.zero? || @cursor_position.zero?~
- Inside source: true
*** True Line Result
- @current_input_str.chop!
+ return if current_input_str.length.zero? || @cursor_position.zero?
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @current_input_str = @current_input_str[0...(@cursor_position - 1)] + @current_input_str[@cursor_position..-1]~
+- Inside source: true
+*** True Line Result
+ @current_input_str = @current_input_str[0...(@cursor_position - 1)] + @current_input_str[@cursor_position..-1]
+** Processing line: ~ @cursor_position -= 1~
+- Inside source: true
+*** True Line Result
+ @cursor_position -= 1
+** Processing line: ~ update_cursor_position_px~
+- Inside source: true
+*** True Line Result
+ update_cursor_position_px
** Processing line: ~ reset_autocomplete~
- Inside source: true
*** True Line Result
@@ -94119,6 +96215,46 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~ def move_cursor_left~
+- Inside source: true
+*** True Line Result
+ def move_cursor_left
+** Processing line: ~ @cursor_position -= 1 if @cursor_position > 0~
+- Inside source: true
+*** True Line Result
+ @cursor_position -= 1 if @cursor_position > 0
+** Processing line: ~ update_cursor_position_px~
+- Inside source: true
+*** True Line Result
+ update_cursor_position_px
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def move_cursor_right~
+- Inside source: true
+*** True Line Result
+ def move_cursor_right
+** Processing line: ~ @cursor_position += 1 if @cursor_position < current_input_str.length~
+- Inside source: true
+*** True Line Result
+ @cursor_position += 1 if @cursor_position < current_input_str.length
+** Processing line: ~ update_cursor_position_px~
+- Inside source: true
+*** True Line Result
+ update_cursor_position_px
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ def clear~
- Inside source: true
*** True Line Result
@@ -94127,6 +96263,14 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
@current_input_str = ''
+** Processing line: ~ @cursor_position = 0~
+- Inside source: true
+*** True Line Result
+ @cursor_position = 0
+** Processing line: ~ update_cursor_position_px~
+- Inside source: true
+*** True Line Result
+ update_cursor_position_px
** Processing line: ~ reset_autocomplete~
- Inside source: true
*** True Line Result
@@ -94199,10 +96343,22 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
self.current_input_str = display_autocomplete_candidate(candidate)
+** Processing line: ~ update_cursor_position_px~
+- Inside source: true
+*** True Line Result
+ update_cursor_position_px
** Processing line: ~ end~
- Inside source: true
*** True Line Result
end
+** Processing line: ~ rescue Exception => e~
+- Inside source: true
+*** True Line Result
+ rescue Exception => e
+** Processing line: ~ puts "* BUG: Tab autocompletion failed. Let us know about this.\n#{e}"~
+- Inside source: true
+*** True Line Result
+ puts "* BUG: Tab autocompletion failed. Let us know about this.\n#{e}"
** Processing line: ~ end~
- Inside source: true
*** True Line Result
@@ -94435,10 +96591,66 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
args.outputs.reserved << font_style.label(x: x, y: y, text: "#{@prompt}#{current_input_str}", color: @text_color)
-** Processing line: ~ args.outputs.reserved << font_style.label(x: x - 2, y: y + 3, text: (" " * (@prompt.length + current_input_str.length)) + "|", color: @cursor_color)~
+** Processing line: ~ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 0.5,~
+- Inside source: true
+*** True Line Result
+ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 0.5,
+** Processing line: ~ y: y + 5,~
+- Inside source: true
+*** True Line Result
+ y: y + 5,
+** Processing line: ~ x2: x + @cursor_position_px + 0.5,~
+- Inside source: true
+*** True Line Result
+ x2: x + @cursor_position_px + 0.5,
+** Processing line: ~ y2: y + @font_style.letter_size.y + 5)~
+- Inside source: true
+*** True Line Result
+ y2: y + @font_style.letter_size.y + 5)
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 1,~
+- Inside source: true
+*** True Line Result
+ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 1,
+** Processing line: ~ y: y + 5,~
- Inside source: true
*** True Line Result
- args.outputs.reserved << font_style.label(x: x - 2, y: y + 3, text: (" " * (@prompt.length + current_input_str.length)) + "|", color: @cursor_color)
+ y: y + 5,
+** Processing line: ~ x2: x + @cursor_position_px + 1,~
+- Inside source: true
+*** True Line Result
+ x2: x + @cursor_position_px + 1,
+** Processing line: ~ y2: y + @font_style.letter_size.y + 5)~
+- Inside source: true
+*** True Line Result
+ y2: y + @font_style.letter_size.y + 5)
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # debugging rectangle for string~
+- Inside source: true
+*** True Line Result
+ # debugging rectangle for string
+** Processing line: ~ # args.outputs.reserved << (@cursor_color.to_h.merge x: x,~
+- Inside source: true
+*** True Line Result
+ # args.outputs.reserved << (@cursor_color.to_h.merge x: x,
+** Processing line: ~ # y: y + 5,~
+- Inside source: true
+*** True Line Result
+ # y: y + 5,
+** Processing line: ~ # w: @cursor_position_px,~
+- Inside source: true
+*** True Line Result
+ # w: @cursor_position_px,
+** Processing line: ~ # h: @font_style.letter_size.y).border~
+- Inside source: true
+*** True Line Result
+ # h: @font_style.letter_size.y).border
** Processing line: ~ end~
- Inside source: true
*** True Line Result
@@ -102319,6 +104531,218 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # Provides access to multitouch input~
+- Inside source: true
+*** True Line Result
+ # Provides access to multitouch input
+** Processing line: ~ #~
+- Inside source: true
+*** True Line Result
+ #
+** Processing line: ~ # @gtk~
+- Inside source: true
+*** True Line Result
+ # @gtk
+** Processing line: ~ class FingerTouch~
+- Inside source: true
+*** True Line Result
+ class FingerTouch
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # @gtk~
+- Inside source: true
+*** True Line Result
+ # @gtk
+** Processing line: ~ attr_accessor :moved,~
+- Inside source: true
+*** True Line Result
+ attr_accessor :moved,
+** Processing line: ~ :moved_at,~
+- Inside source: true
+*** True Line Result
+ :moved_at,
+** Processing line: ~ :global_moved_at,~
+- Inside source: true
+*** True Line Result
+ :global_moved_at,
+** Processing line: ~ :touch_order,~
+- Inside source: true
+*** True Line Result
+ :touch_order,
+** Processing line: ~ :x, :y~
+- Inside source: true
+*** True Line Result
+ :x, :y
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ @moved = false~
+- Inside source: true
+*** True Line Result
+ @moved = false
+** Processing line: ~ @moved_at = 0~
+- Inside source: true
+*** True Line Result
+ @moved_at = 0
+** Processing line: ~ @global_moved_at = 0~
+- Inside source: true
+*** True Line Result
+ @global_moved_at = 0
+** Processing line: ~ @touch_order = 0~
+- Inside source: true
+*** True Line Result
+ @touch_order = 0
+** Processing line: ~ @x = 0~
+- Inside source: true
+*** True Line Result
+ @x = 0
+** Processing line: ~ @y = 0~
+- Inside source: true
+*** True Line Result
+ @y = 0
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def point~
+- Inside source: true
+*** True Line Result
+ def point
+** Processing line: ~ [@x, @y].point~
+- Inside source: true
+*** True Line Result
+ [@x, @y].point
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def inside_rect? rect~
+- Inside source: true
+*** True Line Result
+ def inside_rect? rect
+** Processing line: ~ point.inside_rect? rect~
+- Inside source: true
+*** True Line Result
+ point.inside_rect? rect
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def inside_circle? center, radius~
+- Inside source: true
+*** True Line Result
+ def inside_circle? center, radius
+** Processing line: ~ point.point_inside_circle? center, radius~
+- Inside source: true
+*** True Line Result
+ point.point_inside_circle? center, radius
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ alias_method :position, :point~
+- Inside source: true
+*** True Line Result
+ alias_method :position, :point
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def serialize~
+- Inside source: true
+*** True Line Result
+ def serialize
+** Processing line: ~ result = {}~
+- Inside source: true
+*** True Line Result
+ result = {}
+** Processing line: ~ result[:x] = @x~
+- Inside source: true
+*** True Line Result
+ result[:x] = @x
+** Processing line: ~ result[:y] = @y~
+- Inside source: true
+*** True Line Result
+ result[:y] = @y
+** Processing line: ~ result[:touch_order] = @touch_order~
+- Inside source: true
+*** True Line Result
+ result[:touch_order] = @touch_order
+** Processing line: ~ result[:moved] = @moved~
+- Inside source: true
+*** True Line Result
+ result[:moved] = @moved
+** Processing line: ~ result[:moved_at] = @moved_at~
+- Inside source: true
+*** True Line Result
+ result[:moved_at] = @moved_at
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ result~
+- Inside source: true
+*** True Line Result
+ result
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def to_s~
+- Inside source: true
+*** True Line Result
+ def to_s
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ alias_method :inspect, :to_s~
+- Inside source: true
+*** True Line Result
+ alias_method :inspect, :to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
** Processing line: ~ end~
- Inside source: true
*** True Line Result
@@ -102399,6 +104823,26 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~ # @return {FingerTouch}~
+- Inside source: true
+*** True Line Result
+ # @return {FingerTouch}
+** Processing line: ~ # @gtk~
+- Inside source: true
+*** True Line Result
+ # @gtk
+** Processing line: ~ attr_reader :touch~
+- Inside source: true
+*** True Line Result
+ attr_reader :touch
+** Processing line: ~ attr_accessor :finger_one, :finger_two~
+- Inside source: true
+*** True Line Result
+ attr_accessor :finger_one, :finger_two
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ # @gtk~
- Inside source: true
*** True Line Result
@@ -102427,6 +104871,18 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
@mouse = Mouse.new
+** Processing line: ~ @touch = {}~
+- Inside source: true
+*** True Line Result
+ @touch = {}
+** Processing line: ~ @finger_one = nil~
+- Inside source: true
+*** True Line Result
+ @finger_one = nil
+** Processing line: ~ @finger_two = nil~
+- Inside source: true
+*** True Line Result
+ @finger_two = nil
** Processing line: ~ @text = []~
- Inside source: true
*** True Line Result
@@ -102727,6 +105183,18 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
@controllers.each(&:clear)
+** Processing line: ~ @touch.clear~
+- Inside source: true
+*** True Line Result
+ @touch.clear
+** Processing line: ~ @finger_one = nil~
+- Inside source: true
+*** True Line Result
+ @finger_one = nil
+** Processing line: ~ @finger_two = nil~
+- Inside source: true
+*** True Line Result
+ @finger_two = nil
** Processing line: ~ end~
- Inside source: true
*** True Line Result
@@ -102795,6 +105263,5546 @@ Follows is a source code listing for all files that have been open sourced. This
- End of paragraph detected.
*** True Line Result
+** Processing line: ~* ios_wizard.rb~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* ios_wizard.rb
+** Processing line: ~#+begin_src ruby~
+- Line was identified as the beginning of a code block.
+*** True Line Result
+
+*** True Line Result
+#+begin_src ruby
+** Processing line: ~ # ./dragon/ios_wizard.rb~
+- Inside source: true
+*** True Line Result
+ # ./dragon/ios_wizard.rb
+** Processing line: ~ # Copyright 2019 DragonRuby LLC~
+- Inside source: true
+*** True Line Result
+ # Copyright 2019 DragonRuby LLC
+** Processing line: ~ # MIT License~
+- Inside source: true
+*** True Line Result
+ # MIT License
+** Processing line: ~ # ios_wizard.rb has been released under MIT (*only this file*).~
+- Inside source: true
+*** True Line Result
+ # ios_wizard.rb has been released under MIT (*only this file*).
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class WizardException < Exception~
+- Inside source: true
+*** True Line Result
+ class WizardException < Exception
+** Processing line: ~ attr_accessor :console_primitives~
+- Inside source: true
+*** True Line Result
+ attr_accessor :console_primitives
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize *console_primitives~
+- Inside source: true
+*** True Line Result
+ def initialize *console_primitives
+** Processing line: ~ @console_primitives = console_primitives~
+- Inside source: true
+*** True Line Result
+ @console_primitives = console_primitives
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class IOSWizard~
+- Inside source: true
+*** True Line Result
+ class IOSWizard
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ @doctor_executed_at = 0~
+- Inside source: true
+*** True Line Result
+ @doctor_executed_at = 0
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def relative_path~
+- Inside source: true
+*** True Line Result
+ def relative_path
+** Processing line: ~ (File.dirname $gtk.binary_path)~
+- Inside source: true
+*** True Line Result
+ (File.dirname $gtk.binary_path)
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def steps~
+- Inside source: true
+*** True Line Result
+ def steps
+** Processing line: ~ [~
+- Inside source: true
+*** True Line Result
+ [
+** Processing line: ~ :check_for_xcode,~
+- Inside source: true
+*** True Line Result
+ :check_for_xcode,
+** Processing line: ~ :check_for_brew,~
+- Inside source: true
+*** True Line Result
+ :check_for_brew,
+** Processing line: ~ :check_for_certs,~
+- Inside source: true
+*** True Line Result
+ :check_for_certs,
+** Processing line: ~ :check_for_device,~
+- Inside source: true
+*** True Line Result
+ :check_for_device,
+** Processing line: ~ :check_for_dev_profile,~
+- Inside source: true
+*** True Line Result
+ :check_for_dev_profile,
+** Processing line: ~ :determine_app_name,~
+- Inside source: true
+*** True Line Result
+ :determine_app_name,
+** Processing line: ~ :determine_app_id,~
+- Inside source: true
+*** True Line Result
+ :determine_app_id,
+** Processing line: ~ :blow_away_temp,~
+- Inside source: true
+*** True Line Result
+ :blow_away_temp,
+** Processing line: ~ :stage_app,~
+- Inside source: true
+*** True Line Result
+ :stage_app,
+** Processing line: ~ :write_info_plist,~
+- Inside source: true
+*** True Line Result
+ :write_info_plist,
+** Processing line: ~ :write_entitlements_plist,~
+- Inside source: true
+*** True Line Result
+ :write_entitlements_plist,
+** Processing line: ~ :code_sign,~
+- Inside source: true
+*** True Line Result
+ :code_sign,
+** Processing line: ~ :create_ipa,~
+- Inside source: true
+*** True Line Result
+ :create_ipa,
+** Processing line: ~ :deploy,~
+- Inside source: true
+*** True Line Result
+ :deploy,
+** Processing line: ~ ]~
+- Inside source: true
+*** True Line Result
+ ]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def get_reserved_sprite png~
+- Inside source: true
+*** True Line Result
+ def get_reserved_sprite png
+** Processing line: ~ sprite_path = ".dragonruby/sprites/wizards/ios/#{png}"~
+- Inside source: true
+*** True Line Result
+ sprite_path = ".dragonruby/sprites/wizards/ios/#{png}"
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if !$gtk.ivar :rcb_release_mode~
+- Inside source: true
+*** True Line Result
+ if !$gtk.ivar :rcb_release_mode
+** Processing line: ~ sprite_path = "deploy_template/#{sprite_path}"~
+- Inside source: true
+*** True Line Result
+ sprite_path = "deploy_template/#{sprite_path}"
+** Processing line: ~ $gtk.reset_sprite sprite_path~
+- Inside source: true
+*** True Line Result
+ $gtk.reset_sprite sprite_path
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if !$gtk.read_file sprite_path~
+- Inside source: true
+*** True Line Result
+ if !$gtk.read_file sprite_path
+** Processing line: ~ log_error "png #{png} not found."~
+- Inside source: true
+*** True Line Result
+ log_error "png #{png} not found."
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ sprite_path~
+- Inside source: true
+*** True Line Result
+ sprite_path
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def start~
+- Inside source: true
+*** True Line Result
+ def start
+** Processing line: ~ @certificate_name = nil~
+- Inside source: true
+*** True Line Result
+ @certificate_name = nil
+** Processing line: ~ init_wizard_status~
+- Inside source: true
+*** True Line Result
+ init_wizard_status
+** Processing line: ~ log_info "Starting iOS Wizard so we can deploy to your device."~
+- Inside source: true
+*** True Line Result
+ log_info "Starting iOS Wizard so we can deploy to your device."
+** Processing line: ~ @start_at = Kernel.global_tick_count~
+- Inside source: true
+*** True Line Result
+ @start_at = Kernel.global_tick_count
+** Processing line: ~ steps.each do |m|~
+- Inside source: true
+*** True Line Result
+ steps.each do |m|
+** Processing line: ~ begin~
+- Inside source: true
+*** True Line Result
+ begin
+** Processing line: ~ result = (send m) || :success if @wizard_status[m][:result] != :success~
+- Inside source: true
+*** True Line Result
+ result = (send m) || :success if @wizard_status[m][:result] != :success
+** Processing line: ~ @wizard_status[m][:result] = result~
+- Inside source: true
+*** True Line Result
+ @wizard_status[m][:result] = result
+** Processing line: ~ rescue Exception => e~
+- Inside source: true
+*** True Line Result
+ rescue Exception => e
+** Processing line: ~ if e.is_a? WizardException~
+- Inside source: true
+*** True Line Result
+ if e.is_a? WizardException
+** Processing line: ~ $console.log.clear~
+- Inside source: true
+*** True Line Result
+ $console.log.clear
+** Processing line: ~ $console.archived_log.clear~
+- Inside source: true
+*** True Line Result
+ $console.archived_log.clear
+** Processing line: ~ log "=" * $console.console_text_width~
+- Inside source: true
+*** True Line Result
+ log "=" * $console.console_text_width
+** Processing line: ~ e.console_primitives.each do |p|~
+- Inside source: true
+*** True Line Result
+ e.console_primitives.each do |p|
+** Processing line: ~ $console.add_primitive p~
+- Inside source: true
+*** True Line Result
+ $console.add_primitive p
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ log "=" * $console.console_text_width~
+- Inside source: true
+*** True Line Result
+ log "=" * $console.console_text_width
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ log_error "Step #{m} failed."~
+- Inside source: true
+*** True Line Result
+ log_error "Step #{m} failed."
+** Processing line: ~ log_error e.to_s~
+- Inside source: true
+*** True Line Result
+ log_error e.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ $console.set_command "$wizards.ios.start"~
+- Inside source: true
+*** True Line Result
+ $console.set_command "$wizards.ios.start"
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ break~
+- Inside source: true
+*** True Line Result
+ break
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ return nil~
+- Inside source: true
+*** True Line Result
+ return nil
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def always_fail~
+- Inside source: true
+*** True Line Result
+ def always_fail
+** Processing line: ~ return false if $gtk.ivar :rcb_release_mode~
+- Inside source: true
+*** True Line Result
+ return false if $gtk.ivar :rcb_release_mode
+** Processing line: ~ return true~
+- Inside source: true
+*** True Line Result
+ return true
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def check_for_xcode~
+- Inside source: true
+*** True Line Result
+ def check_for_xcode
+** Processing line: ~ if !cli_app_exist?(xcodebuild_cli_app)~
+- Inside source: true
+*** True Line Result
+ if !cli_app_exist?(xcodebuild_cli_app)
+** Processing line: ~ raise WizardException.new(~
+- Inside source: true
+*** True Line Result
+ raise WizardException.new(
+** Processing line: ~ "* You need Xcode to use $wizards.ios.start.",~
+- Inside source: true
+*** True Line Result
+ "* You need Xcode to use $wizards.ios.start.",
+** Processing line: ~ { w: 75, h: 75, path: get_reserved_sprite("xcode.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 75, h: 75, path: get_reserved_sprite("xcode.png") },
+** Processing line: ~ "** 1. Go to http://developer.apple.com and register.",~
+- Inside source: true
+*** True Line Result
+ "** 1. Go to http://developer.apple.com and register.",
+** Processing line: ~ "** 2. Download Xcode 11.3+ from http://developer.apple.com/downloads.",~
+- Inside source: true
+*** True Line Result
+ "** 2. Download Xcode 11.3+ from http://developer.apple.com/downloads.",
+** Processing line: ~ " NOTE: DO NOT install Xcode from the App Store. Use the link above.",~
+- Inside source: true
+*** True Line Result
+ " NOTE: DO NOT install Xcode from the App Store. Use the link above.",
+** Processing line: ~ { w: 700, h: 359, path: get_reserved_sprite("xcode-downloads.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 700, h: 359, path: get_reserved_sprite("xcode-downloads.png") },
+** Processing line: ~ "** 3. After installing. Open up Xcode to accept the EULA."~
+- Inside source: true
+*** True Line Result
+ "** 3. After installing. Open up Xcode to accept the EULA."
+** Processing line: ~ )~
+- Inside source: true
+*** True Line Result
+ )
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def check_for_brew~
+- Inside source: true
+*** True Line Result
+ def check_for_brew
+** Processing line: ~ if !cli_app_exist?('brew')~
+- Inside source: true
+*** True Line Result
+ if !cli_app_exist?('brew')
+** Processing line: ~ raise WizardException.new(~
+- Inside source: true
+*** True Line Result
+ raise WizardException.new(
+** Processing line: ~ "* You need to install Brew.",~
+- Inside source: true
+*** True Line Result
+ "* You need to install Brew.",
+** Processing line: ~ { w: 700, h: 388, path: get_reserved_sprite("brew.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 700, h: 388, path: get_reserved_sprite("brew.png") },
+** Processing line: ~ "** 1. Go to http://brew.sh.",~
+- Inside source: true
+*** True Line Result
+ "** 1. Go to http://brew.sh.",
+** Processing line: ~ "** 2. Copy the command that starts with `/bin/bash -c` on the site.",~
+- Inside source: true
+*** True Line Result
+ "** 2. Copy the command that starts with `/bin/bash -c` on the site.",
+** Processing line: ~ "** 3. Open Terminal and run the command you copied from the website.",~
+- Inside source: true
+*** True Line Result
+ "** 3. Open Terminal and run the command you copied from the website.",
+** Processing line: ~ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },
+** Processing line: ~ )~
+- Inside source: true
+*** True Line Result
+ )
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def init_wizard_status~
+- Inside source: true
+*** True Line Result
+ def init_wizard_status
+** Processing line: ~ @wizard_status = {}~
+- Inside source: true
+*** True Line Result
+ @wizard_status = {}
+** Processing line: ~ steps.each do |m|~
+- Inside source: true
+*** True Line Result
+ steps.each do |m|
+** Processing line: ~ @wizard_status[m] = { result: :not_started }~
+- Inside source: true
+*** True Line Result
+ @wizard_status[m] = { result: :not_started }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ previous_step = nil~
+- Inside source: true
+*** True Line Result
+ previous_step = nil
+** Processing line: ~ next_step = nil~
+- Inside source: true
+*** True Line Result
+ next_step = nil
+** Processing line: ~ steps.each_cons(2) do |current_step, next_step|~
+- Inside source: true
+*** True Line Result
+ steps.each_cons(2) do |current_step, next_step|
+** Processing line: ~ @wizard_status[current_step][:next_step] = next_step~
+- Inside source: true
+*** True Line Result
+ @wizard_status[current_step][:next_step] = next_step
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ steps.reverse.each_cons(2) do |current_step, previous_step|~
+- Inside source: true
+*** True Line Result
+ steps.reverse.each_cons(2) do |current_step, previous_step|
+** Processing line: ~ @wizard_status[current_step][:previous_step] = previous_step~
+- Inside source: true
+*** True Line Result
+ @wizard_status[current_step][:previous_step] = previous_step
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def restart~
+- Inside source: true
+*** True Line Result
+ def restart
+** Processing line: ~ init_wizard_status~
+- Inside source: true
+*** True Line Result
+ init_wizard_status
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def check_for_dev_profile~
+- Inside source: true
+*** True Line Result
+ def check_for_dev_profile
+** Processing line: ~ if !($gtk.read_file 'profiles/development.mobileprovision')~
+- Inside source: true
+*** True Line Result
+ if !($gtk.read_file 'profiles/development.mobileprovision')
+** Processing line: ~ $gtk.system "mkdir -p #{relative_path}/profiles"~
+- Inside source: true
+*** True Line Result
+ $gtk.system "mkdir -p #{relative_path}/profiles"
+** Processing line: ~ $gtk.system "open #{relative_path}/profiles"~
+- Inside source: true
+*** True Line Result
+ $gtk.system "open #{relative_path}/profiles"
+** Processing line: ~ $gtk.system "echo Download the mobile provisioning profile and place it here with the name development.mobileprovision > #{relative_path}/profiles/README.txt"~
+- Inside source: true
+*** True Line Result
+ $gtk.system "echo Download the mobile provisioning profile and place it here with the name development.mobileprovision > #{relative_path}/profiles/README.txt"
+** Processing line: ~ raise WizardException.new(~
+- Inside source: true
+*** True Line Result
+ raise WizardException.new(
+** Processing line: ~ "* I didn't find a mobile provision.",~
+- Inside source: true
+*** True Line Result
+ "* I didn't find a mobile provision.",
+** Processing line: ~ "** 1. Go to http://developer.apple.com and click \"Certificates, IDs & Profiles\".",~
+- Inside source: true
+*** True Line Result
+ "** 1. Go to http://developer.apple.com and click \"Certificates, IDs & Profiles\".",
+** Processing line: ~ "** 2. Add an App Identifier.",~
+- Inside source: true
+*** True Line Result
+ "** 2. Add an App Identifier.",
+** Processing line: ~ "** 3. Select the App IDs option from the list.",~
+- Inside source: true
+*** True Line Result
+ "** 3. Select the App IDs option from the list.",
+** Processing line: ~ { w: 700, h: 75, path: get_reserved_sprite("identifiers.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 700, h: 75, path: get_reserved_sprite("identifiers.png") },
+** Processing line: ~ "** 4. Add your Device next. You can use idevice_id -l to get the UUID of your device.",~
+- Inside source: true
+*** True Line Result
+ "** 4. Add your Device next. You can use idevice_id -l to get the UUID of your device.",
+** Processing line: ~ { w: 365, h: 69, path: get_reserved_sprite("device-link.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 365, h: 69, path: get_reserved_sprite("device-link.png") },
+** Processing line: ~ "** 5. Create a Profile. Associate your certs, id, and device.",~
+- Inside source: true
+*** True Line Result
+ "** 5. Create a Profile. Associate your certs, id, and device.",
+** Processing line: ~ { w: 300, h: 122, path: get_reserved_sprite("profiles.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 300, h: 122, path: get_reserved_sprite("profiles.png") },
+** Processing line: ~ "** 6. Download the mobile provision and save it to 'profiles/development.mobileprovision'.",~
+- Inside source: true
+*** True Line Result
+ "** 6. Download the mobile provision and save it to 'profiles/development.mobileprovision'.",
+** Processing line: ~ { w: 200, h: 124, path: get_reserved_sprite("profiles-folder.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 200, h: 124, path: get_reserved_sprite("profiles-folder.png") },
+** Processing line: ~ )~
+- Inside source: true
+*** True Line Result
+ )
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def determine_app_name~
+- Inside source: true
+*** True Line Result
+ def determine_app_name
+** Processing line: ~ @app_name = dev_profile_xml[:children].first[:children].first[:children][1][:children].first[:data]~
+- Inside source: true
+*** True Line Result
+ @app_name = dev_profile_xml[:children].first[:children].first[:children][1][:children].first[:data]
+** Processing line: ~ log_info "App name is: #{@app_name}."~
+- Inside source: true
+*** True Line Result
+ log_info "App name is: #{@app_name}."
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def dev_profile_xml~
+- Inside source: true
+*** True Line Result
+ def dev_profile_xml
+** Processing line: ~ xml = $gtk.read_file 'profiles/development.mobileprovision'~
+- Inside source: true
+*** True Line Result
+ xml = $gtk.read_file 'profiles/development.mobileprovision'
+** Processing line: ~ scrubbed = xml.each_line.map do |l|~
+- Inside source: true
+*** True Line Result
+ scrubbed = xml.each_line.map do |l|
+** Processing line: ~ if l.strip.start_with? "<"~
+- Inside source: true
+*** True Line Result
+ if l.strip.start_with? "<"
+** Processing line: ~ if l.start_with? '</plist>'~
+- Inside source: true
+*** True Line Result
+ if l.start_with? '</plist>'
+** Processing line: ~ '</plist>'~
+- Inside source: true
+*** True Line Result
+ '</plist>'
+** Processing line: ~ elsif l.include? "Apple Inc."~
+- Inside source: true
+*** True Line Result
+ elsif l.include? "Apple Inc."
+** Processing line: ~ nil~
+- Inside source: true
+*** True Line Result
+ nil
+** Processing line: ~ elsif l.include? '<data>'~
+- Inside source: true
+*** True Line Result
+ elsif l.include? '<data>'
+** Processing line: ~ nil~
+- Inside source: true
+*** True Line Result
+ nil
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ l~
+- Inside source: true
+*** True Line Result
+ l
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ nil~
+- Inside source: true
+*** True Line Result
+ nil
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end.reject { |l| !l }.join~
+- Inside source: true
+*** True Line Result
+ end.reject { |l| !l }.join
+** Processing line: ~ $gtk.parse_xml scrubbed~
+- Inside source: true
+*** True Line Result
+ $gtk.parse_xml scrubbed
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def determine_app_id~
+- Inside source: true
+*** True Line Result
+ def determine_app_id
+** Processing line: ~ # lol~
+- Inside source: true
+*** True Line Result
+ # lol
+** Processing line: ~ @app_id = dev_profile_xml[:children].first[:children].first[:children][13][:children][1][:children].first[:data]~
+- Inside source: true
+*** True Line Result
+ @app_id = dev_profile_xml[:children].first[:children].first[:children][13][:children][1][:children].first[:data]
+** Processing line: ~ log_info "App Identifier is set to : #{@app_id}"~
+- Inside source: true
+*** True Line Result
+ log_info "App Identifier is set to : #{@app_id}"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def set_app_name name~
+- Inside source: true
+*** True Line Result
+ def set_app_name name
+** Processing line: ~ @app_name = name~
+- Inside source: true
+*** True Line Result
+ @app_name = name
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def set_dev_profile path~
+- Inside source: true
+*** True Line Result
+ def set_dev_profile path
+** Processing line: ~ if !$gtk.read_file path~
+- Inside source: true
+*** True Line Result
+ if !$gtk.read_file path
+** Processing line: ~ log_error "I couldn't find a development profile at #{path}."~
+- Inside source: true
+*** True Line Result
+ log_error "I couldn't find a development profile at #{path}."
+** Processing line: ~ ask_for_dev_profile~
+- Inside source: true
+*** True Line Result
+ ask_for_dev_profile
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ @dev_profile_path = path~
+- Inside source: true
+*** True Line Result
+ @dev_profile_path = path
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def blow_away_temp~
+- Inside source: true
+*** True Line Result
+ def blow_away_temp
+** Processing line: ~ sh "rm -rf #{tmp_directory}"~
+- Inside source: true
+*** True Line Result
+ sh "rm -rf #{tmp_directory}"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def stage_app~
+- Inside source: true
+*** True Line Result
+ def stage_app
+** Processing line: ~ log_info "Staging."~
+- Inside source: true
+*** True Line Result
+ log_info "Staging."
+** Processing line: ~ sh "mkdir -p #{tmp_directory}"~
+- Inside source: true
+*** True Line Result
+ sh "mkdir -p #{tmp_directory}"
+** Processing line: ~ sh "cp -R #{relative_path}/dragonruby-ios.app \"#{tmp_directory}/#{@app_name}.app\""~
+- Inside source: true
+*** True Line Result
+ sh "cp -R #{relative_path}/dragonruby-ios.app \"#{tmp_directory}/#{@app_name}.app\""
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def set_app_id id~
+- Inside source: true
+*** True Line Result
+ def set_app_id id
+** Processing line: ~ log_info = "App Id set to: #{id}"~
+- Inside source: true
+*** True Line Result
+ log_info = "App Id set to: #{id}"
+** Processing line: ~ @app_id = id~
+- Inside source: true
+*** True Line Result
+ @app_id = id
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def check_for_device~
+- Inside source: true
+*** True Line Result
+ def check_for_device
+** Processing line: ~ log_info "Looking for device."~
+- Inside source: true
+*** True Line Result
+ log_info "Looking for device."
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if !cli_app_exist?(idevice_id_cli_app)~
+- Inside source: true
+*** True Line Result
+ if !cli_app_exist?(idevice_id_cli_app)
+** Processing line: ~ raise WizardException.new(~
+- Inside source: true
+*** True Line Result
+ raise WizardException.new(
+** Processing line: ~ "* It doesn't look like you have the libimobiledevice iOS protocol library installed.",~
+- Inside source: true
+*** True Line Result
+ "* It doesn't look like you have the libimobiledevice iOS protocol library installed.",
+** Processing line: ~ "** 1. Open Terminal.",~
+- Inside source: true
+*** True Line Result
+ "** 1. Open Terminal.",
+** Processing line: ~ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },
+** Processing line: ~ "** 2. Run: `brew install libimobiledevice`.",~
+- Inside source: true
+*** True Line Result
+ "** 2. Run: `brew install libimobiledevice`.",
+** Processing line: ~ { w: 500, h: 93, path: get_reserved_sprite("brew-install-libimobiledevice.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 500, h: 93, path: get_reserved_sprite("brew-install-libimobiledevice.png") },
+** Processing line: ~ )~
+- Inside source: true
+*** True Line Result
+ )
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if connected_devices.length == 0~
+- Inside source: true
+*** True Line Result
+ if connected_devices.length == 0
+** Processing line: ~ raise WizardException.new("* I couldn't find any connected devices. Connect your iOS device to your Mac and try again.")~
+- Inside source: true
+*** True Line Result
+ raise WizardException.new("* I couldn't find any connected devices. Connect your iOS device to your Mac and try again.")
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @device_id = connected_devices.first~
+- Inside source: true
+*** True Line Result
+ @device_id = connected_devices.first
+** Processing line: ~ log_info "I will be using device with UUID #{@device_id}"~
+- Inside source: true
+*** True Line Result
+ log_info "I will be using device with UUID #{@device_id}"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def check_for_certs~
+- Inside source: true
+*** True Line Result
+ def check_for_certs
+** Processing line: ~ log_info "Attempting to find certificates on your computer."~
+- Inside source: true
+*** True Line Result
+ log_info "Attempting to find certificates on your computer."
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if !cli_app_exist?(security_cli_app)~
+- Inside source: true
+*** True Line Result
+ if !cli_app_exist?(security_cli_app)
+** Processing line: ~ raise WizardException.new(~
+- Inside source: true
+*** True Line Result
+ raise WizardException.new(
+** Processing line: ~ "* It doesn't look like you have #{security_cli_app}.",~
+- Inside source: true
+*** True Line Result
+ "* It doesn't look like you have #{security_cli_app}.",
+** Processing line: ~ "** 1. Open Disk Utility and run First Aid.",~
+- Inside source: true
+*** True Line Result
+ "** 1. Open Disk Utility and run First Aid.",
+** Processing line: ~ { w: 700, h: 148, path: get_reserved_sprite("disk-utility.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 700, h: 148, path: get_reserved_sprite("disk-utility.png") },
+** Processing line: ~ )~
+- Inside source: true
+*** True Line Result
+ )
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if valid_certs.length == 0~
+- Inside source: true
+*** True Line Result
+ if valid_certs.length == 0
+** Processing line: ~ raise WizardException.new(~
+- Inside source: true
+*** True Line Result
+ raise WizardException.new(
+** Processing line: ~ "* It doesn't look like you have any valid certs installed.",~
+- Inside source: true
+*** True Line Result
+ "* It doesn't look like you have any valid certs installed.",
+** Processing line: ~ "** 1. Open Xcode.",~
+- Inside source: true
+*** True Line Result
+ "** 1. Open Xcode.",
+** Processing line: ~ "** 2. Log into your developer account. Xcode -> Preferences -> Accounts.",~
+- Inside source: true
+*** True Line Result
+ "** 2. Log into your developer account. Xcode -> Preferences -> Accounts.",
+** Processing line: ~ { w: 700, h: 98, path: get_reserved_sprite("login-xcode.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 700, h: 98, path: get_reserved_sprite("login-xcode.png") },
+** Processing line: ~ "** 3. After loggin in, select Manage Certificates...",~
+- Inside source: true
+*** True Line Result
+ "** 3. After loggin in, select Manage Certificates...",
+** Processing line: ~ { w: 700, h: 115, path: get_reserved_sprite("manage-certificates.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 700, h: 115, path: get_reserved_sprite("manage-certificates.png") },
+** Processing line: ~ "** 4. Add a certificate for Apple Development.",~
+- Inside source: true
+*** True Line Result
+ "** 4. Add a certificate for Apple Development.",
+** Processing line: ~ { w: 700, h: 217, path: get_reserved_sprite("add-cert.png") },~
+- Inside source: true
+*** True Line Result
+ { w: 700, h: 217, path: get_reserved_sprite("add-cert.png") },
+** Processing line: ~ )~
+- Inside source: true
+*** True Line Result
+ )
+** Processing line: ~ raise "You do not have any Apple development certs on this computer."~
+- Inside source: true
+*** True Line Result
+ raise "You do not have any Apple development certs on this computer."
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @certificate_name = valid_certs.first[:name]~
+- Inside source: true
+*** True Line Result
+ @certificate_name = valid_certs.first[:name]
+** Processing line: ~ log_info "I will be using '#{@certificate_name}' to deploy to your device."~
+- Inside source: true
+*** True Line Result
+ log_info "I will be using '#{@certificate_name}' to deploy to your device."
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def idevice_id_cli_app~
+- Inside source: true
+*** True Line Result
+ def idevice_id_cli_app
+** Processing line: ~ "idevice_id"~
+- Inside source: true
+*** True Line Result
+ "idevice_id"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def security_cli_app~
+- Inside source: true
+*** True Line Result
+ def security_cli_app
+** Processing line: ~ "/usr/bin/security"~
+- Inside source: true
+*** True Line Result
+ "/usr/bin/security"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def xcodebuild_cli_app~
+- Inside source: true
+*** True Line Result
+ def xcodebuild_cli_app
+** Processing line: ~ "xcodebuild"~
+- Inside source: true
+*** True Line Result
+ "xcodebuild"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def valid_certs~
+- Inside source: true
+*** True Line Result
+ def valid_certs
+** Processing line: ~ certs = sh("#{security_cli_app} -q find-identity -p codesigning -v").each_line.map do |l|~
+- Inside source: true
+*** True Line Result
+ certs = sh("#{security_cli_app} -q find-identity -p codesigning -v").each_line.map do |l|
+** Processing line: ~ if l.include?(")") && !l.include?("Developer ID") && l.include?("Development")~
+- Inside source: true
+*** True Line Result
+ if l.include?(")") && !l.include?("Developer ID") && l.include?("Development")
+** Processing line: ~ l.strip~
+- Inside source: true
+*** True Line Result
+ l.strip
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ nil~
+- Inside source: true
+*** True Line Result
+ nil
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end.reject_nil.map do |l|~
+- Inside source: true
+*** True Line Result
+ end.reject_nil.map do |l|
+** Processing line: ~ number, id, name = l.split(' ', 3)~
+- Inside source: true
+*** True Line Result
+ number, id, name = l.split(' ', 3)
+** Processing line: ~ name = name.gsub("\"", "") if name~
+- Inside source: true
+*** True Line Result
+ name = name.gsub("\"", "") if name
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ number: 1,~
+- Inside source: true
+*** True Line Result
+ number: 1,
+** Processing line: ~ id: id,~
+- Inside source: true
+*** True Line Result
+ id: id,
+** Processing line: ~ name: name~
+- Inside source: true
+*** True Line Result
+ name: name
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def connected_devices~
+- Inside source: true
+*** True Line Result
+ def connected_devices
+** Processing line: ~ sh("idevice_id -l").strip.each_line.map do |l|~
+- Inside source: true
+*** True Line Result
+ sh("idevice_id -l").strip.each_line.map do |l|
+** Processing line: ~ l.strip~
+- Inside source: true
+*** True Line Result
+ l.strip
+** Processing line: ~ end.reject { |l| l.length == 0 }~
+- Inside source: true
+*** True Line Result
+ end.reject { |l| l.length == 0 }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def cli_app_exist? app~
+- Inside source: true
+*** True Line Result
+ def cli_app_exist? app
+** Processing line: ~ `which #{app}`.strip.length != 0~
+- Inside source: true
+*** True Line Result
+ `which #{app}`.strip.length != 0
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def write_entitlements_plist~
+- Inside source: true
+*** True Line Result
+ def write_entitlements_plist
+** Processing line: ~ entitlement_plist_string = <<-XML~
+- Inside source: true
+*** True Line Result
+ entitlement_plist_string = <<-XML
+** Processing line: ~ <?xml version="1.0" encoding="UTF-8"?>~
+- Inside source: true
+*** True Line Result
+ <?xml version="1.0" encoding="UTF-8"?>
+** Processing line: ~ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">~
+- Inside source: true
+*** True Line Result
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+** Processing line: ~ <plist version="1.0">~
+- Inside source: true
+*** True Line Result
+ <plist version="1.0">
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>application-identifier</key>~
+- Inside source: true
+*** True Line Result
+ <key>application-identifier</key>
+** Processing line: ~ <string>:app_id</string>~
+- Inside source: true
+*** True Line Result
+ <string>:app_id</string>
+** Processing line: ~ <key>get-task-allow</key>~
+- Inside source: true
+*** True Line Result
+ <key>get-task-allow</key>
+** Processing line: ~ <true/>~
+- Inside source: true
+*** True Line Result
+ <true/>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ </plist>~
+- Inside source: true
+*** True Line Result
+ </plist>
+** Processing line: ~ XML~
+- Inside source: true
+*** True Line Result
+ XML
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ log_info "Creating Entitlements.plist"~
+- Inside source: true
+*** True Line Result
+ log_info "Creating Entitlements.plist"
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ $gtk.write_file_root "tmp/ios/Entitlements.plist", entitlement_plist_string.gsub(":app_id", @app_id).strip~
+- Inside source: true
+*** True Line Result
+ $gtk.write_file_root "tmp/ios/Entitlements.plist", entitlement_plist_string.gsub(":app_id", @app_id).strip
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ sh "/usr/bin/plutil -convert binary1 \"#{tmp_directory}/Entitlements.plist\""~
+- Inside source: true
+*** True Line Result
+ sh "/usr/bin/plutil -convert binary1 \"#{tmp_directory}/Entitlements.plist\""
+** Processing line: ~ sh "/usr/bin/plutil -convert xml1 \"#{tmp_directory}/Entitlements.plist\""~
+- Inside source: true
+*** True Line Result
+ sh "/usr/bin/plutil -convert xml1 \"#{tmp_directory}/Entitlements.plist\""
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @entitlement_plist_written = true~
+- Inside source: true
+*** True Line Result
+ @entitlement_plist_written = true
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def code_sign~
+- Inside source: true
+*** True Line Result
+ def code_sign
+** Processing line: ~ sh "cp #{@dev_profile_path} \"#{app_path}/embedded.mobileprovision\""~
+- Inside source: true
+*** True Line Result
+ sh "cp #{@dev_profile_path} \"#{app_path}/embedded.mobileprovision\""
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ log_info "Signing app with #{@certificate_name}."~
+- Inside source: true
+*** True Line Result
+ log_info "Signing app with #{@certificate_name}."
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ sh "/usr/bin/plutil -convert binary1 \"#{app_path}/Info.plist\""~
+- Inside source: true
+*** True Line Result
+ sh "/usr/bin/plutil -convert binary1 \"#{app_path}/Info.plist\""
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ sh "CODESIGN_ALLOCATE=\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate\" /usr/bin/codesign -f -s \"#{@certificate_name}\" --entitlements #{tmp_directory}/Entitlements.plist \"#{tmp_directory}/#{@app_name}.app\""~
+- Inside source: true
+*** True Line Result
+ sh "CODESIGN_ALLOCATE=\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate\" /usr/bin/codesign -f -s \"#{@certificate_name}\" --entitlements #{tmp_directory}/Entitlements.plist \"#{tmp_directory}/#{@app_name}.app\""
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @code_sign_completed = true~
+- Inside source: true
+*** True Line Result
+ @code_sign_completed = true
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def write_info_plist~
+- Inside source: true
+*** True Line Result
+ def write_info_plist
+** Processing line: ~ log_info "Adding Info.plist."~
+- Inside source: true
+*** True Line Result
+ log_info "Adding Info.plist."
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ info_plist_string = <<-XML~
+- Inside source: true
+*** True Line Result
+ info_plist_string = <<-XML
+** Processing line: ~ <?xml version="1.0" encoding="UTF-8"?>~
+- Inside source: true
+*** True Line Result
+ <?xml version="1.0" encoding="UTF-8"?>
+** Processing line: ~ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">~
+- Inside source: true
+*** True Line Result
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+** Processing line: ~ <plist version="1.0">~
+- Inside source: true
+*** True Line Result
+ <plist version="1.0">
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>NSAppTransportSecurity</key>~
+- Inside source: true
+*** True Line Result
+ <key>NSAppTransportSecurity</key>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>NSAllowsArbitraryLoads</key>~
+- Inside source: true
+*** True Line Result
+ <key>NSAllowsArbitraryLoads</key>
+** Processing line: ~ <true/>~
+- Inside source: true
+*** True Line Result
+ <true/>
+** Processing line: ~ <key>NSExceptionDomains</key>~
+- Inside source: true
+*** True Line Result
+ <key>NSExceptionDomains</key>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>google.com</key>~
+- Inside source: true
+*** True Line Result
+ <key>google.com</key>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>NSExceptionAllowsInsecureHTTPLoads</key>~
+- Inside source: true
+*** True Line Result
+ <key>NSExceptionAllowsInsecureHTTPLoads</key>
+** Processing line: ~ <true/>~
+- Inside source: true
+*** True Line Result
+ <true/>
+** Processing line: ~ <key>NSIncludesSubdomains</key>~
+- Inside source: true
+*** True Line Result
+ <key>NSIncludesSubdomains</key>
+** Processing line: ~ <true/>~
+- Inside source: true
+*** True Line Result
+ <true/>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ <key>BuildMachineOSBuild</key>~
+- Inside source: true
+*** True Line Result
+ <key>BuildMachineOSBuild</key>
+** Processing line: ~ <string>19C57</string>~
+- Inside source: true
+*** True Line Result
+ <string>19C57</string>
+** Processing line: ~ <key>CFBundleDevelopmentRegion</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleDevelopmentRegion</key>
+** Processing line: ~ <string>en</string>~
+- Inside source: true
+*** True Line Result
+ <string>en</string>
+** Processing line: ~ <key>CFBundleDisplayName</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleDisplayName</key>
+** Processing line: ~ <string>:app_name</string>~
+- Inside source: true
+*** True Line Result
+ <string>:app_name</string>
+** Processing line: ~ <key>CFBundleExecutable</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleExecutable</key>
+** Processing line: ~ <string>Runtime</string>~
+- Inside source: true
+*** True Line Result
+ <string>Runtime</string>
+** Processing line: ~ <key>CFBundleIconFiles</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleIconFiles</key>
+** Processing line: ~ <array>~
+- Inside source: true
+*** True Line Result
+ <array>
+** Processing line: ~ <string>AppIcon60x60</string>~
+- Inside source: true
+*** True Line Result
+ <string>AppIcon60x60</string>
+** Processing line: ~ </array>~
+- Inside source: true
+*** True Line Result
+ </array>
+** Processing line: ~ <key>CFBundleIcons</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleIcons</key>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>CFBundlePrimaryIcon</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundlePrimaryIcon</key>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>CFBundleIconFiles</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleIconFiles</key>
+** Processing line: ~ <array>~
+- Inside source: true
+*** True Line Result
+ <array>
+** Processing line: ~ <string>AppIcon60x60</string>~
+- Inside source: true
+*** True Line Result
+ <string>AppIcon60x60</string>
+** Processing line: ~ </array>~
+- Inside source: true
+*** True Line Result
+ </array>
+** Processing line: ~ <key>CFBundleIconName</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleIconName</key>
+** Processing line: ~ <string>AppIcon</string>~
+- Inside source: true
+*** True Line Result
+ <string>AppIcon</string>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ <key>CFBundleIcons~ipad</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleIcons~ipad</key>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>CFBundlePrimaryIcon</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundlePrimaryIcon</key>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>CFBundleIconFiles</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleIconFiles</key>
+** Processing line: ~ <array>~
+- Inside source: true
+*** True Line Result
+ <array>
+** Processing line: ~ <string>AppIcon60x60</string>~
+- Inside source: true
+*** True Line Result
+ <string>AppIcon60x60</string>
+** Processing line: ~ <string>AppIcon76x76</string>~
+- Inside source: true
+*** True Line Result
+ <string>AppIcon76x76</string>
+** Processing line: ~ </array>~
+- Inside source: true
+*** True Line Result
+ </array>
+** Processing line: ~ <key>CFBundleIconName</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleIconName</key>
+** Processing line: ~ <string>AppIcon</string>~
+- Inside source: true
+*** True Line Result
+ <string>AppIcon</string>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ <key>CFBundleIdentifier</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleIdentifier</key>
+** Processing line: ~ <string>com.carlile.swisscheese</string>~
+- Inside source: true
+*** True Line Result
+ <string>com.carlile.swisscheese</string>
+** Processing line: ~ <key>CFBundleInfoDictionaryVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleInfoDictionaryVersion</key>
+** Processing line: ~ <string>6.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>6.0</string>
+** Processing line: ~ <key>CFBundleName</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleName</key>
+** Processing line: ~ <string>:app_name</string>~
+- Inside source: true
+*** True Line Result
+ <string>:app_name</string>
+** Processing line: ~ <key>CFBundlePackageType</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundlePackageType</key>
+** Processing line: ~ <string>APPL</string>~
+- Inside source: true
+*** True Line Result
+ <string>APPL</string>
+** Processing line: ~ <key>CFBundleShortVersionString</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleShortVersionString</key>
+** Processing line: ~ <string>1.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>1.0</string>
+** Processing line: ~ <key>CFBundleSignature</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleSignature</key>
+** Processing line: ~ <string>????</string>~
+- Inside source: true
+*** True Line Result
+ <string>????</string>
+** Processing line: ~ <key>CFBundleSupportedPlatforms</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleSupportedPlatforms</key>
+** Processing line: ~ <array>~
+- Inside source: true
+*** True Line Result
+ <array>
+** Processing line: ~ <string>iPhoneOS</string>~
+- Inside source: true
+*** True Line Result
+ <string>iPhoneOS</string>
+** Processing line: ~ </array>~
+- Inside source: true
+*** True Line Result
+ </array>
+** Processing line: ~ <key>CFBundleVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>CFBundleVersion</key>
+** Processing line: ~ <string>1.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>1.0</string>
+** Processing line: ~ <key>DTCompiler</key>~
+- Inside source: true
+*** True Line Result
+ <key>DTCompiler</key>
+** Processing line: ~ <string>com.apple.compilers.llvm.clang.1_0</string>~
+- Inside source: true
+*** True Line Result
+ <string>com.apple.compilers.llvm.clang.1_0</string>
+** Processing line: ~ <key>DTPlatformBuild</key>~
+- Inside source: true
+*** True Line Result
+ <key>DTPlatformBuild</key>
+** Processing line: ~ <string>17B102</string>~
+- Inside source: true
+*** True Line Result
+ <string>17B102</string>
+** Processing line: ~ <key>DTPlatformName</key>~
+- Inside source: true
+*** True Line Result
+ <key>DTPlatformName</key>
+** Processing line: ~ <string>iphoneos</string>~
+- Inside source: true
+*** True Line Result
+ <string>iphoneos</string>
+** Processing line: ~ <key>DTPlatformVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>DTPlatformVersion</key>
+** Processing line: ~ <string>13.2</string>~
+- Inside source: true
+*** True Line Result
+ <string>13.2</string>
+** Processing line: ~ <key>DTSDKBuild</key>~
+- Inside source: true
+*** True Line Result
+ <key>DTSDKBuild</key>
+** Processing line: ~ <string>17B102</string>~
+- Inside source: true
+*** True Line Result
+ <string>17B102</string>
+** Processing line: ~ <key>DTSDKName</key>~
+- Inside source: true
+*** True Line Result
+ <key>DTSDKName</key>
+** Processing line: ~ <string>iphoneos13.2</string>~
+- Inside source: true
+*** True Line Result
+ <string>iphoneos13.2</string>
+** Processing line: ~ <key>DTXcode</key>~
+- Inside source: true
+*** True Line Result
+ <key>DTXcode</key>
+** Processing line: ~ <string>01131</string>~
+- Inside source: true
+*** True Line Result
+ <string>01131</string>
+** Processing line: ~ <key>DTXcodeBuild</key>~
+- Inside source: true
+*** True Line Result
+ <key>DTXcodeBuild</key>
+** Processing line: ~ <string>11C505</string>~
+- Inside source: true
+*** True Line Result
+ <string>11C505</string>
+** Processing line: ~ <key>ITSAppUsesNonExemptEncryption</key>~
+- Inside source: true
+*** True Line Result
+ <key>ITSAppUsesNonExemptEncryption</key>
+** Processing line: ~ <false/>~
+- Inside source: true
+*** True Line Result
+ <false/>
+** Processing line: ~ <key>MinimumOSVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>MinimumOSVersion</key>
+** Processing line: ~ <string>11.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>11.0</string>
+** Processing line: ~ <key>UIAppFonts</key>~
+- Inside source: true
+*** True Line Result
+ <key>UIAppFonts</key>
+** Processing line: ~ <array/>~
+- Inside source: true
+*** True Line Result
+ <array/>
+** Processing line: ~ <key>UIBackgroundModes</key>~
+- Inside source: true
+*** True Line Result
+ <key>UIBackgroundModes</key>
+** Processing line: ~ <array/>~
+- Inside source: true
+*** True Line Result
+ <array/>
+** Processing line: ~ <key>UIDeviceFamily</key>~
+- Inside source: true
+*** True Line Result
+ <key>UIDeviceFamily</key>
+** Processing line: ~ <array>~
+- Inside source: true
+*** True Line Result
+ <array>
+** Processing line: ~ <integer>1</integer>~
+- Inside source: true
+*** True Line Result
+ <integer>1</integer>
+** Processing line: ~ <integer>2</integer>~
+- Inside source: true
+*** True Line Result
+ <integer>2</integer>
+** Processing line: ~ </array>~
+- Inside source: true
+*** True Line Result
+ </array>
+** Processing line: ~ <key>UILaunchImages</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImages</key>
+** Processing line: ~ <array>~
+- Inside source: true
+*** True Line Result
+ <array>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageMinimumOSVersion</key>
+** Processing line: ~ <string>11.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>11.0</string>
+** Processing line: ~ <key>UILaunchImageName</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageName</key>
+** Processing line: ~ <string>LaunchImage-1100-Portrait-2436h</string>~
+- Inside source: true
+*** True Line Result
+ <string>LaunchImage-1100-Portrait-2436h</string>
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageOrientation</key>
+** Processing line: ~ <string>Portrait</string>~
+- Inside source: true
+*** True Line Result
+ <string>Portrait</string>
+** Processing line: ~ <key>UILaunchImageSize</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageSize</key>
+** Processing line: ~ <string>{375, 812}</string>~
+- Inside source: true
+*** True Line Result
+ <string>{375, 812}</string>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageMinimumOSVersion</key>
+** Processing line: ~ <string>8.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>8.0</string>
+** Processing line: ~ <key>UILaunchImageName</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageName</key>
+** Processing line: ~ <string>LaunchImage-800-Portrait-736h</string>~
+- Inside source: true
+*** True Line Result
+ <string>LaunchImage-800-Portrait-736h</string>
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageOrientation</key>
+** Processing line: ~ <string>Portrait</string>~
+- Inside source: true
+*** True Line Result
+ <string>Portrait</string>
+** Processing line: ~ <key>UILaunchImageSize</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageSize</key>
+** Processing line: ~ <string>{414, 736}</string>~
+- Inside source: true
+*** True Line Result
+ <string>{414, 736}</string>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageMinimumOSVersion</key>
+** Processing line: ~ <string>8.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>8.0</string>
+** Processing line: ~ <key>UILaunchImageName</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageName</key>
+** Processing line: ~ <string>LaunchImage-800-667h</string>~
+- Inside source: true
+*** True Line Result
+ <string>LaunchImage-800-667h</string>
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageOrientation</key>
+** Processing line: ~ <string>Portrait</string>~
+- Inside source: true
+*** True Line Result
+ <string>Portrait</string>
+** Processing line: ~ <key>UILaunchImageSize</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageSize</key>
+** Processing line: ~ <string>{375, 667}</string>~
+- Inside source: true
+*** True Line Result
+ <string>{375, 667}</string>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageMinimumOSVersion</key>
+** Processing line: ~ <string>7.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>7.0</string>
+** Processing line: ~ <key>UILaunchImageName</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageName</key>
+** Processing line: ~ <string>LaunchImage-700</string>~
+- Inside source: true
+*** True Line Result
+ <string>LaunchImage-700</string>
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageOrientation</key>
+** Processing line: ~ <string>Portrait</string>~
+- Inside source: true
+*** True Line Result
+ <string>Portrait</string>
+** Processing line: ~ <key>UILaunchImageSize</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageSize</key>
+** Processing line: ~ <string>{320, 480}</string>~
+- Inside source: true
+*** True Line Result
+ <string>{320, 480}</string>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageMinimumOSVersion</key>
+** Processing line: ~ <string>7.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>7.0</string>
+** Processing line: ~ <key>UILaunchImageName</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageName</key>
+** Processing line: ~ <string>LaunchImage-700-568h</string>~
+- Inside source: true
+*** True Line Result
+ <string>LaunchImage-700-568h</string>
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageOrientation</key>
+** Processing line: ~ <string>Portrait</string>~
+- Inside source: true
+*** True Line Result
+ <string>Portrait</string>
+** Processing line: ~ <key>UILaunchImageSize</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageSize</key>
+** Processing line: ~ <string>{320, 568}</string>~
+- Inside source: true
+*** True Line Result
+ <string>{320, 568}</string>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ <dict>~
+- Inside source: true
+*** True Line Result
+ <dict>
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageMinimumOSVersion</key>
+** Processing line: ~ <string>7.0</string>~
+- Inside source: true
+*** True Line Result
+ <string>7.0</string>
+** Processing line: ~ <key>UILaunchImageName</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageName</key>
+** Processing line: ~ <string>LaunchImage-700-Portrait</string>~
+- Inside source: true
+*** True Line Result
+ <string>LaunchImage-700-Portrait</string>
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageOrientation</key>
+** Processing line: ~ <string>Portrait</string>~
+- Inside source: true
+*** True Line Result
+ <string>Portrait</string>
+** Processing line: ~ <key>UILaunchImageSize</key>~
+- Inside source: true
+*** True Line Result
+ <key>UILaunchImageSize</key>
+** Processing line: ~ <string>{768, 1024}</string>~
+- Inside source: true
+*** True Line Result
+ <string>{768, 1024}</string>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ </array>~
+- Inside source: true
+*** True Line Result
+ </array>
+** Processing line: ~ <key>UIRequiredDeviceCapabilities</key>~
+- Inside source: true
+*** True Line Result
+ <key>UIRequiredDeviceCapabilities</key>
+** Processing line: ~ <array>~
+- Inside source: true
+*** True Line Result
+ <array>
+** Processing line: ~ <string>arm64</string>~
+- Inside source: true
+*** True Line Result
+ <string>arm64</string>
+** Processing line: ~ </array>~
+- Inside source: true
+*** True Line Result
+ </array>
+** Processing line: ~ <key>UIRequiresFullScreen</key>~
+- Inside source: true
+*** True Line Result
+ <key>UIRequiresFullScreen</key>
+** Processing line: ~ <true/>~
+- Inside source: true
+*** True Line Result
+ <true/>
+** Processing line: ~ <key>UIStatusBarStyle</key>~
+- Inside source: true
+*** True Line Result
+ <key>UIStatusBarStyle</key>
+** Processing line: ~ <string>UIStatusBarStyleDefault</string>~
+- Inside source: true
+*** True Line Result
+ <string>UIStatusBarStyleDefault</string>
+** Processing line: ~ <key>UISupportedInterfaceOrientations</key>~
+- Inside source: true
+*** True Line Result
+ <key>UISupportedInterfaceOrientations</key>
+** Processing line: ~ <array>~
+- Inside source: true
+*** True Line Result
+ <array>
+** Processing line: ~ <string>#{device_orientation_xml}</string>~
+- Inside source: true
+*** True Line Result
+ <string>#{device_orientation_xml}</string>
+** Processing line: ~ </array>~
+- Inside source: true
+*** True Line Result
+ </array>
+** Processing line: ~ </dict>~
+- Inside source: true
+*** True Line Result
+ </dict>
+** Processing line: ~ </plist>~
+- Inside source: true
+*** True Line Result
+ </plist>
+** Processing line: ~ XML~
+- Inside source: true
+*** True Line Result
+ XML
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ # <string>UIInterfaceOrientationPortrait</string>~
+- Inside source: true
+*** True Line Result
+ # <string>UIInterfaceOrientationPortrait</string>
+** Processing line: ~ # <string>UIInterfaceOrientationLandscapeRight</string>~
+- Inside source: true
+*** True Line Result
+ # <string>UIInterfaceOrientationLandscapeRight</string>
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ $gtk.write_file_root "tmp/ios/#{@app_name}.app/Info.plist", info_plist_string.gsub(":app_name", @app_name).strip~
+- Inside source: true
+*** True Line Result
+ $gtk.write_file_root "tmp/ios/#{@app_name}.app/Info.plist", info_plist_string.gsub(":app_name", @app_name).strip
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @info_plist_written = true~
+- Inside source: true
+*** True Line Result
+ @info_plist_written = true
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def device_orientation_xml~
+- Inside source: true
+*** True Line Result
+ def device_orientation_xml
+** Processing line: ~ return "UIInterfaceOrientationLandscapeRight" if $gtk.logical_width > $gtk.logical_height~
+- Inside source: true
+*** True Line Result
+ return "UIInterfaceOrientationLandscapeRight" if $gtk.logical_width > $gtk.logical_height
+** Processing line: ~ return "UIInterfaceOrientationPortrait"~
+- Inside source: true
+*** True Line Result
+ return "UIInterfaceOrientationPortrait"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def tmp_directory~
+- Inside source: true
+*** True Line Result
+ def tmp_directory
+** Processing line: ~ "#{relative_path}/tmp/ios"~
+- Inside source: true
+*** True Line Result
+ "#{relative_path}/tmp/ios"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def app_path~
+- Inside source: true
+*** True Line Result
+ def app_path
+** Processing line: ~ "#{tmp_directory}/#{@app_name}.app"~
+- Inside source: true
+*** True Line Result
+ "#{tmp_directory}/#{@app_name}.app"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def root_folder~
+- Inside source: true
+*** True Line Result
+ def root_folder
+** Processing line: ~ "#{relative_path}/#{$gtk.cli_arguments[:dragonruby]}"~
+- Inside source: true
+*** True Line Result
+ "#{relative_path}/#{$gtk.cli_arguments[:dragonruby]}"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def write_ip_address~
+- Inside source: true
+*** True Line Result
+ def write_ip_address
+** Processing line: ~ $gtk.write_file "app/server_ip_address.txt", $gtk.ffi_misc.get_local_ip_address.strip~
+- Inside source: true
+*** True Line Result
+ $gtk.write_file "app/server_ip_address.txt", $gtk.ffi_misc.get_local_ip_address.strip
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def create_ipa~
+- Inside source: true
+*** True Line Result
+ def create_ipa
+** Processing line: ~ write_ip_address~
+- Inside source: true
+*** True Line Result
+ write_ip_address
+** Processing line: ~ sh "rm \"#{@app_name}\".ipa"~
+- Inside source: true
+*** True Line Result
+ sh "rm \"#{@app_name}\".ipa"
+** Processing line: ~ sh "rm -rf \"#{app_path}/app\""~
+- Inside source: true
+*** True Line Result
+ sh "rm -rf \"#{app_path}/app\""
+** Processing line: ~ sh "rm -rf \"#{app_path}/sounds\""~
+- Inside source: true
+*** True Line Result
+ sh "rm -rf \"#{app_path}/sounds\""
+** Processing line: ~ sh "rm -rf \"#{app_path}/sprites\""~
+- Inside source: true
+*** True Line Result
+ sh "rm -rf \"#{app_path}/sprites\""
+** Processing line: ~ sh "rm -rf \"#{app_path}/data\""~
+- Inside source: true
+*** True Line Result
+ sh "rm -rf \"#{app_path}/data\""
+** Processing line: ~ sh "rm -rf \"#{app_path}/fonts\""~
+- Inside source: true
+*** True Line Result
+ sh "rm -rf \"#{app_path}/fonts\""
+** Processing line: ~ sh "cp -r \"#{root_folder}/app/\" \"#{app_path}/app/\""~
+- Inside source: true
+*** True Line Result
+ sh "cp -r \"#{root_folder}/app/\" \"#{app_path}/app/\""
+** Processing line: ~ sh "cp -r \"#{root_folder}/sounds/\" \"#{app_path}/sounds/\""~
+- Inside source: true
+*** True Line Result
+ sh "cp -r \"#{root_folder}/sounds/\" \"#{app_path}/sounds/\""
+** Processing line: ~ sh "cp -r \"#{root_folder}/sprites/\" \"#{app_path}/sprites/\""~
+- Inside source: true
+*** True Line Result
+ sh "cp -r \"#{root_folder}/sprites/\" \"#{app_path}/sprites/\""
+** Processing line: ~ sh "cp -r \"#{root_folder}/data/\" \"#{app_path}/data/\""~
+- Inside source: true
+*** True Line Result
+ sh "cp -r \"#{root_folder}/data/\" \"#{app_path}/data/\""
+** Processing line: ~ sh "cp -r \"#{root_folder}/fonts/\" \"#{app_path}/fonts/\""~
+- Inside source: true
+*** True Line Result
+ sh "cp -r \"#{root_folder}/fonts/\" \"#{app_path}/fonts/\""
+** Processing line: ~ sh "mkdir -p #{tmp_directory}/ipa_root/Payload"~
+- Inside source: true
+*** True Line Result
+ sh "mkdir -p #{tmp_directory}/ipa_root/Payload"
+** Processing line: ~ sh "cp -r \"#{app_path}\" \"#{tmp_directory}/ipa_root/Payload\""~
+- Inside source: true
+*** True Line Result
+ sh "cp -r \"#{app_path}\" \"#{tmp_directory}/ipa_root/Payload\""
+** Processing line: ~ sh "chmod -R 755 \"#{tmp_directory}/ipa_root/Payload\""~
+- Inside source: true
+*** True Line Result
+ sh "chmod -R 755 \"#{tmp_directory}/ipa_root/Payload\""
+** Processing line: ~ do_zip~
+- Inside source: true
+*** True Line Result
+ do_zip
+** Processing line: ~ sh "cp \"#{tmp_directory}/ipa_root/archive.zip\" \"#{tmp_directory}/#{@app_name}.ipa\""~
+- Inside source: true
+*** True Line Result
+ sh "cp \"#{tmp_directory}/ipa_root/archive.zip\" \"#{tmp_directory}/#{@app_name}.ipa\""
+** Processing line: ~ sh "XCODE_DIR=\"/Applications/Xcode.app/Contents/Developer\" \"#{relative_path}/dragonruby-deploy-ios\" -d \"#{@device_id}\" \"#{tmp_directory}/#{@app_name}.ipa\""~
+- Inside source: true
+*** True Line Result
+ sh "XCODE_DIR=\"/Applications/Xcode.app/Contents/Developer\" \"#{relative_path}/dragonruby-deploy-ios\" -d \"#{@device_id}\" \"#{tmp_directory}/#{@app_name}.ipa\""
+** Processing line: ~ cmd_result = `ps -e | grep civetweb`~
+- Inside source: true
+*** True Line Result
+ cmd_result = `ps -e | grep civetweb`
+** Processing line: ~ is_civet_running = (`ps -e | grep civetweb`).strip.each_line.to_a.length > 2~
+- Inside source: true
+*** True Line Result
+ is_civet_running = (`ps -e | grep civetweb`).strip.each_line.to_a.length > 2
+** Processing line: ~ if !is_civet_running~
+- Inside source: true
+*** True Line Result
+ if !is_civet_running
+** Processing line: ~ $gtk.system "cp \"#{relative_path}/civetweb\" \"#{tmp_directory}/../src_backup/civetweb\""~
+- Inside source: true
+*** True Line Result
+ $gtk.system "cp \"#{relative_path}/civetweb\" \"#{tmp_directory}/../src_backup/civetweb\""
+** Processing line: ~ $gtk.system "open \"#{tmp_directory}/../src_backup/civetweb\" -g"~
+- Inside source: true
+*** True Line Result
+ $gtk.system "open \"#{tmp_directory}/../src_backup/civetweb\" -g"
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ log "* INFO: civetweb is running already running. No need to start another instance."~
+- Inside source: true
+*** True Line Result
+ log "* INFO: civetweb is running already running. No need to start another instance."
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ log_info "Check your device!!"~
+- Inside source: true
+*** True Line Result
+ log_info "Check your device!!"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def do_zip~
+- Inside source: true
+*** True Line Result
+ def do_zip
+** Processing line: ~ $gtk.write_file_root "tmp/ios/do_zip.sh", <<-SCRIPT~
+- Inside source: true
+*** True Line Result
+ $gtk.write_file_root "tmp/ios/do_zip.sh", <<-SCRIPT
+** Processing line: ~ pushd #{tmp_directory}/ipa_root/~
+- Inside source: true
+*** True Line Result
+ pushd #{tmp_directory}/ipa_root/
+** Processing line: ~ zip -q -r archive.zip Payload~
+- Inside source: true
+*** True Line Result
+ zip -q -r archive.zip Payload
+** Processing line: ~ popd~
+- Inside source: true
+*** True Line Result
+ popd
+** Processing line: ~ SCRIPT~
+- Inside source: true
+*** True Line Result
+ SCRIPT
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ sh "sh #{tmp_directory}/do_zip.sh"~
+- Inside source: true
+*** True Line Result
+ sh "sh #{tmp_directory}/do_zip.sh"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def sh cmd~
+- Inside source: true
+*** True Line Result
+ def sh cmd
+** Processing line: ~ log_info cmd.strip~
+- Inside source: true
+*** True Line Result
+ log_info cmd.strip
+** Processing line: ~ result = `#{cmd}`~
+- Inside source: true
+*** True Line Result
+ result = `#{cmd}`
+** Processing line: ~ if result.strip.length > 0~
+- Inside source: true
+*** True Line Result
+ if result.strip.length > 0
+** Processing line: ~ log_info result.strip.each_line.map(&:strip).join("\n")~
+- Inside source: true
+*** True Line Result
+ log_info result.strip.each_line.map(&:strip).join("\n")
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ result~
+- Inside source: true
+*** True Line Result
+ result
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def deploy~
+- Inside source: true
+*** True Line Result
+ def deploy
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~#+end_src~
+- Line was identified as the end of a code block.
+*** True Line Result
+#+end_src
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
+** Processing line: ~* itch_wizard.rb~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* itch_wizard.rb
+** Processing line: ~#+begin_src ruby~
+- Line was identified as the beginning of a code block.
+*** True Line Result
+
+*** True Line Result
+#+begin_src ruby
+** Processing line: ~ # ./dragon/itch_wizard.rb~
+- Inside source: true
+*** True Line Result
+ # ./dragon/itch_wizard.rb
+** Processing line: ~ # Copyright 2019 DragonRuby LLC~
+- Inside source: true
+*** True Line Result
+ # Copyright 2019 DragonRuby LLC
+** Processing line: ~ # MIT License~
+- Inside source: true
+*** True Line Result
+ # MIT License
+** Processing line: ~ # itch_wizard.rb has been released under MIT (*only this file*).~
+- Inside source: true
+*** True Line Result
+ # itch_wizard.rb has been released under MIT (*only this file*).
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class ItchWizard~
+- Inside source: true
+*** True Line Result
+ class ItchWizard
+** Processing line: ~ def steps~
+- Inside source: true
+*** True Line Result
+ def steps
+** Processing line: ~ [~
+- Inside source: true
+*** True Line Result
+ [
+** Processing line: ~ :check_metadata,~
+- Inside source: true
+*** True Line Result
+ :check_metadata,
+** Processing line: ~ :deploy~
+- Inside source: true
+*** True Line Result
+ :deploy
+** Processing line: ~ ]~
+- Inside source: true
+*** True Line Result
+ ]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def metadata_file_path~
+- Inside source: true
+*** True Line Result
+ def metadata_file_path
+** Processing line: ~ "metadata/game_metadata.txt"~
+- Inside source: true
+*** True Line Result
+ "metadata/game_metadata.txt"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def get_metadata~
+- Inside source: true
+*** True Line Result
+ def get_metadata
+** Processing line: ~ metadata = $gtk.read_file metadata_file_path~
+- Inside source: true
+*** True Line Result
+ metadata = $gtk.read_file metadata_file_path
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if !metadata~
+- Inside source: true
+*** True Line Result
+ if !metadata
+** Processing line: ~ write_blank_metadata~
+- Inside source: true
+*** True Line Result
+ write_blank_metadata
+** Processing line: ~ metadata = $gtk.read_file metadata_file_path~
+- Inside source: true
+*** True Line Result
+ metadata = $gtk.read_file metadata_file_path
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ dev_id, dev_title, game_id, game_title, version, icon = *metadata.each_line.to_a~
+- Inside source: true
+*** True Line Result
+ dev_id, dev_title, game_id, game_title, version, icon = *metadata.each_line.to_a
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ dev_id: dev_id.strip,~
+- Inside source: true
+*** True Line Result
+ dev_id: dev_id.strip,
+** Processing line: ~ dev_title: dev_title.strip,~
+- Inside source: true
+*** True Line Result
+ dev_title: dev_title.strip,
+** Processing line: ~ game_id: game_id.strip,~
+- Inside source: true
+*** True Line Result
+ game_id: game_id.strip,
+** Processing line: ~ game_title: game_title.strip,~
+- Inside source: true
+*** True Line Result
+ game_title: game_title.strip,
+** Processing line: ~ version: version.strip,~
+- Inside source: true
+*** True Line Result
+ version: version.strip,
+** Processing line: ~ icon: icon.strip~
+- Inside source: true
+*** True Line Result
+ icon: icon.strip
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def write_blank_metadata~
+- Inside source: true
+*** True Line Result
+ def write_blank_metadata
+** Processing line: ~ $gtk.write_file metadata_file_path, <<-S.strip~
+- Inside source: true
+*** True Line Result
+ $gtk.write_file metadata_file_path, <<-S.strip
+** Processing line: ~ #devid=myname~
+- Inside source: true
+*** True Line Result
+ #devid=myname
+** Processing line: ~ #devtitle=My Name~
+- Inside source: true
+*** True Line Result
+ #devtitle=My Name
+** Processing line: ~ #gameid=mygame~
+- Inside source: true
+*** True Line Result
+ #gameid=mygame
+** Processing line: ~ #gametitle=My Game~
+- Inside source: true
+*** True Line Result
+ #gametitle=My Game
+** Processing line: ~ #version=0.1~
+- Inside source: true
+*** True Line Result
+ #version=0.1
+** Processing line: ~ #icon=metadata/icon.png~
+- Inside source: true
+*** True Line Result
+ #icon=metadata/icon.png
+** Processing line: ~ S~
+- Inside source: true
+*** True Line Result
+ S
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def check_metadata~
+- Inside source: true
+*** True Line Result
+ def check_metadata
+** Processing line: ~ metadata_text = $gtk.read_file metadata_file_path~
+- Inside source: true
+*** True Line Result
+ metadata_text = $gtk.read_file metadata_file_path
+** Processing line: ~ if !metadata_text~
+- Inside source: true
+*** True Line Result
+ if !metadata_text
+** Processing line: ~ write_blank_metadata~
+- Inside source: true
+*** True Line Result
+ write_blank_metadata
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if metadata_text.each_line.to_a.length != 6~
+- Inside source: true
+*** True Line Result
+ if metadata_text.each_line.to_a.length != 6
+** Processing line: ~ write_blank_metadata~
+- Inside source: true
+*** True Line Result
+ write_blank_metadata
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ log "* INFO: Contents of #{metadata_file_path}:"~
+- Inside source: true
+*** True Line Result
+ log "* INFO: Contents of #{metadata_file_path}:"
+** Processing line: ~ log "#+begin_src txt"~
+- Inside source: true
+*** True Line Result
+ log "#+begin_src txt"
+** Processing line: ~ metadata_text.each_line { |l| log " #{l}" }~
+- Inside source: true
+*** True Line Result
+ metadata_text.each_line { |l| log " #{l}" }
+** Processing line: ~ log "#+end_src"~
+- Inside source: true
+*** True Line Result
+ log "#+end_src"
+** Processing line: ~ metadata = get_metadata~
+- Inside source: true
+*** True Line Result
+ metadata = get_metadata
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if metadata[:dev_id].start_with?("#") || !@dev_id~
+- Inside source: true
+*** True Line Result
+ if metadata[:dev_id].start_with?("#") || !@dev_id
+** Processing line: ~ log "* PROMPT: Please provide your username for Itch."~
+- Inside source: true
+*** True Line Result
+ log "* PROMPT: Please provide your username for Itch."
+** Processing line: ~ $console.set_command "$wizards.itch.set_dev_id \"your-itch-username\""~
+- Inside source: true
+*** True Line Result
+ $console.set_command "$wizards.itch.set_dev_id \"your-itch-username\""
+** Processing line: ~ return :need_dev_id~
+- Inside source: true
+*** True Line Result
+ return :need_dev_id
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if metadata[:dev_title].start_with?("#") || !@dev_title~
+- Inside source: true
+*** True Line Result
+ if metadata[:dev_title].start_with?("#") || !@dev_title
+** Processing line: ~ log "* PROMPT: Please provide developer's/company's name that you want displayed."~
+- Inside source: true
+*** True Line Result
+ log "* PROMPT: Please provide developer's/company's name that you want displayed."
+** Processing line: ~ $console.set_command "$wizards.itch.set_dev_title \"Your Name\""~
+- Inside source: true
+*** True Line Result
+ $console.set_command "$wizards.itch.set_dev_title \"Your Name\""
+** Processing line: ~ return :need_dev_title~
+- Inside source: true
+*** True Line Result
+ return :need_dev_title
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if metadata[:game_id].start_with?("#") || !@game_id~
+- Inside source: true
+*** True Line Result
+ if metadata[:game_id].start_with?("#") || !@game_id
+** Processing line: ~ log "* PROMPT: Please provide the id for you game. This is the id you specified when you set up a new game page on Itch."~
+- Inside source: true
+*** True Line Result
+ log "* PROMPT: Please provide the id for you game. This is the id you specified when you set up a new game page on Itch."
+** Processing line: ~ $console.set_command "$wizards.itch.set_game_id \"your-game-id\""~
+- Inside source: true
+*** True Line Result
+ $console.set_command "$wizards.itch.set_game_id \"your-game-id\""
+** Processing line: ~ return :need_game_id~
+- Inside source: true
+*** True Line Result
+ return :need_game_id
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if metadata[:game_title].start_with?("#") || !@game_title~
+- Inside source: true
+*** True Line Result
+ if metadata[:game_title].start_with?("#") || !@game_title
+** Processing line: ~ log "* PROMPT: Please provide the display name for your game. (This can include spaces)"~
+- Inside source: true
+*** True Line Result
+ log "* PROMPT: Please provide the display name for your game. (This can include spaces)"
+** Processing line: ~ $console.set_command "$wizards.itch.set_game_title \"Your Game\""~
+- Inside source: true
+*** True Line Result
+ $console.set_command "$wizards.itch.set_game_title \"Your Game\""
+** Processing line: ~ return :need_game_title~
+- Inside source: true
+*** True Line Result
+ return :need_game_title
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if metadata[:version].start_with?("#") || !@version~
+- Inside source: true
+*** True Line Result
+ if metadata[:version].start_with?("#") || !@version
+** Processing line: ~ log "* PROMPT: Please provide the version for your game."~
+- Inside source: true
+*** True Line Result
+ log "* PROMPT: Please provide the version for your game."
+** Processing line: ~ $console.set_command "$wizards.itch.set_version \"1.0\""~
+- Inside source: true
+*** True Line Result
+ $console.set_command "$wizards.itch.set_version \"1.0\""
+** Processing line: ~ return :need_version~
+- Inside source: true
+*** True Line Result
+ return :need_version
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if metadata[:icon].start_with?("#") || !@icon~
+- Inside source: true
+*** True Line Result
+ if metadata[:icon].start_with?("#") || !@icon
+** Processing line: ~ log "* PROPT: Please provide icon path for your game."~
+- Inside source: true
+*** True Line Result
+ log "* PROPT: Please provide icon path for your game."
+** Processing line: ~ $console.set_command "$wizards.itch.set_icon \"icon.png\""~
+- Inside source: true
+*** True Line Result
+ $console.set_command "$wizards.itch.set_icon \"icon.png\""
+** Processing line: ~ return :need_icon~
+- Inside source: true
+*** True Line Result
+ return :need_icon
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ return :success~
+- Inside source: true
+*** True Line Result
+ return :success
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def set_dev_id value~
+- Inside source: true
+*** True Line Result
+ def set_dev_id value
+** Processing line: ~ @dev_id = value~
+- Inside source: true
+*** True Line Result
+ @dev_id = value
+** Processing line: ~ write_metadata~
+- Inside source: true
+*** True Line Result
+ write_metadata
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def set_dev_title value~
+- Inside source: true
+*** True Line Result
+ def set_dev_title value
+** Processing line: ~ @dev_title = value~
+- Inside source: true
+*** True Line Result
+ @dev_title = value
+** Processing line: ~ write_metadata~
+- Inside source: true
+*** True Line Result
+ write_metadata
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def set_game_id value~
+- Inside source: true
+*** True Line Result
+ def set_game_id value
+** Processing line: ~ @game_id = value~
+- Inside source: true
+*** True Line Result
+ @game_id = value
+** Processing line: ~ write_metadata~
+- Inside source: true
+*** True Line Result
+ write_metadata
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def set_game_title value~
+- Inside source: true
+*** True Line Result
+ def set_game_title value
+** Processing line: ~ @game_title = value~
+- Inside source: true
+*** True Line Result
+ @game_title = value
+** Processing line: ~ write_metadata~
+- Inside source: true
+*** True Line Result
+ write_metadata
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def set_version value~
+- Inside source: true
+*** True Line Result
+ def set_version value
+** Processing line: ~ @version = value~
+- Inside source: true
+*** True Line Result
+ @version = value
+** Processing line: ~ write_metadata~
+- Inside source: true
+*** True Line Result
+ write_metadata
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def set_icon value~
+- Inside source: true
+*** True Line Result
+ def set_icon value
+** Processing line: ~ @icon = value~
+- Inside source: true
+*** True Line Result
+ @icon = value
+** Processing line: ~ write_metadata~
+- Inside source: true
+*** True Line Result
+ write_metadata
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def write_metadata~
+- Inside source: true
+*** True Line Result
+ def write_metadata
+** Processing line: ~ text = ""~
+- Inside source: true
+*** True Line Result
+ text = ""
+** Processing line: ~ if @dev_id~
+- Inside source: true
+*** True Line Result
+ if @dev_id
+** Processing line: ~ text += "devid=#{@dev_id}\n"~
+- Inside source: true
+*** True Line Result
+ text += "devid=#{@dev_id}\n"
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ text += "#devid=myname\n"~
+- Inside source: true
+*** True Line Result
+ text += "#devid=myname\n"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if @dev_title~
+- Inside source: true
+*** True Line Result
+ if @dev_title
+** Processing line: ~ text += "devtitle=#{@dev_title}\n"~
+- Inside source: true
+*** True Line Result
+ text += "devtitle=#{@dev_title}\n"
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ text += "#devtitle=My Name\n"~
+- Inside source: true
+*** True Line Result
+ text += "#devtitle=My Name\n"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if @game_id~
+- Inside source: true
+*** True Line Result
+ if @game_id
+** Processing line: ~ text += "gameid=#{@game_id}\n"~
+- Inside source: true
+*** True Line Result
+ text += "gameid=#{@game_id}\n"
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ text += "#gameid=gameid\n"~
+- Inside source: true
+*** True Line Result
+ text += "#gameid=gameid\n"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if @game_title~
+- Inside source: true
+*** True Line Result
+ if @game_title
+** Processing line: ~ text += "gametitle=#{@game_title}\n"~
+- Inside source: true
+*** True Line Result
+ text += "gametitle=#{@game_title}\n"
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ text += "#gametitle=Game Name\n"~
+- Inside source: true
+*** True Line Result
+ text += "#gametitle=Game Name\n"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if @version~
+- Inside source: true
+*** True Line Result
+ if @version
+** Processing line: ~ text += "version=#{@version}\n"~
+- Inside source: true
+*** True Line Result
+ text += "version=#{@version}\n"
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ text += "#version=0.1\n"~
+- Inside source: true
+*** True Line Result
+ text += "#version=0.1\n"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if @icon~
+- Inside source: true
+*** True Line Result
+ if @icon
+** Processing line: ~ text += "icon=metadata/#{@icon}\n"~
+- Inside source: true
+*** True Line Result
+ text += "icon=metadata/#{@icon}\n"
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ text += "#icon=metadata/icon.png\n"~
+- Inside source: true
+*** True Line Result
+ text += "#icon=metadata/icon.png\n"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ $gtk.write_file metadata_file_path, text~
+- Inside source: true
+*** True Line Result
+ $gtk.write_file metadata_file_path, text
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def relative_path~
+- Inside source: true
+*** True Line Result
+ def relative_path
+** Processing line: ~ (File.dirname $gtk.binary_path)~
+- Inside source: true
+*** True Line Result
+ (File.dirname $gtk.binary_path)
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def package_command~
+- Inside source: true
+*** True Line Result
+ def package_command
+** Processing line: ~ "#{File.join $gtk.get_base_dir, 'dragonruby-publish'}"~
+- Inside source: true
+*** True Line Result
+ "#{File.join $gtk.get_base_dir, 'dragonruby-publish'}"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def deploy~
+- Inside source: true
+*** True Line Result
+ def deploy
+** Processing line: ~ log_info "* Running dragonruby-publish: #{package_command}"~
+- Inside source: true
+*** True Line Result
+ log_info "* Running dragonruby-publish: #{package_command}"
+** Processing line: ~ results = $gtk.exec package_command~
+- Inside source: true
+*** True Line Result
+ results = $gtk.exec package_command
+** Processing line: ~ log "#+begin_src"~
+- Inside source: true
+*** True Line Result
+ log "#+begin_src"
+** Processing line: ~ log results~
+- Inside source: true
+*** True Line Result
+ log results
+** Processing line: ~ log "#+end_src"~
+- Inside source: true
+*** True Line Result
+ log "#+end_src"
+** Processing line: ~ :success~
+- Inside source: true
+*** True Line Result
+ :success
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def start~
+- Inside source: true
+*** True Line Result
+ def start
+** Processing line: ~ log "================"~
+- Inside source: true
+*** True Line Result
+ log "================"
+** Processing line: ~ log "* INFO: Starting Itch Wizard."~
+- Inside source: true
+*** True Line Result
+ log "* INFO: Starting Itch Wizard."
+** Processing line: ~ @start_at = Kernel.global_tick_count~
+- Inside source: true
+*** True Line Result
+ @start_at = Kernel.global_tick_count
+** Processing line: ~ steps.each do |m|~
+- Inside source: true
+*** True Line Result
+ steps.each do |m|
+** Processing line: ~ begin~
+- Inside source: true
+*** True Line Result
+ begin
+** Processing line: ~ log_info "Running Itch Wizard Step: ~$wizards.itch.#{m}~"~
+- Inside source: true
+*** True Line Result
+ log_info "Running Itch Wizard Step: ~$wizards.itch.#{m}~"
+** Processing line: ~ result = (send m) || :success if @wizard_status[m][:result] != :success~
+- Inside source: true
+*** True Line Result
+ result = (send m) || :success if @wizard_status[m][:result] != :success
+** Processing line: ~ @wizard_status[m][:result] = result~
+- Inside source: true
+*** True Line Result
+ @wizard_status[m][:result] = result
+** Processing line: ~ if result != :success~
+- Inside source: true
+*** True Line Result
+ if result != :success
+** Processing line: ~ log_info "Exiting wizard. :#{result}"~
+- Inside source: true
+*** True Line Result
+ log_info "Exiting wizard. :#{result}"
+** Processing line: ~ break~
+- Inside source: true
+*** True Line Result
+ break
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ rescue Exception => e~
+- Inside source: true
+*** True Line Result
+ rescue Exception => e
+** Processing line: ~ if e.is_a? WizardException~
+- Inside source: true
+*** True Line Result
+ if e.is_a? WizardException
+** Processing line: ~ $console.log.clear~
+- Inside source: true
+*** True Line Result
+ $console.log.clear
+** Processing line: ~ $console.archived_log.clear~
+- Inside source: true
+*** True Line Result
+ $console.archived_log.clear
+** Processing line: ~ log "=" * $console.console_text_width~
+- Inside source: true
+*** True Line Result
+ log "=" * $console.console_text_width
+** Processing line: ~ e.console_primitives.each do |p|~
+- Inside source: true
+*** True Line Result
+ e.console_primitives.each do |p|
+** Processing line: ~ $console.add_primitive p~
+- Inside source: true
+*** True Line Result
+ $console.add_primitive p
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ log "=" * $console.console_text_width~
+- Inside source: true
+*** True Line Result
+ log "=" * $console.console_text_width
+** Processing line: ~ $console.set_command (e.console_command || "$wizards.itch.start")~
+- Inside source: true
+*** True Line Result
+ $console.set_command (e.console_command || "$wizards.itch.start")
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ log_error "Step #{m} failed."~
+- Inside source: true
+*** True Line Result
+ log_error "Step #{m} failed."
+** Processing line: ~ log_error e.to_s~
+- Inside source: true
+*** True Line Result
+ log_error e.to_s
+** Processing line: ~ $console.set_command "$wizards.itch.start"~
+- Inside source: true
+*** True Line Result
+ $console.set_command "$wizards.itch.start"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ break~
+- Inside source: true
+*** True Line Result
+ break
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def reset~
+- Inside source: true
+*** True Line Result
+ def reset
+** Processing line: ~ @dev_id = nil~
+- Inside source: true
+*** True Line Result
+ @dev_id = nil
+** Processing line: ~ @dev_title = nil~
+- Inside source: true
+*** True Line Result
+ @dev_title = nil
+** Processing line: ~ @game_id = nil~
+- Inside source: true
+*** True Line Result
+ @game_id = nil
+** Processing line: ~ @game_title = nil~
+- Inside source: true
+*** True Line Result
+ @game_title = nil
+** Processing line: ~ @version = nil~
+- Inside source: true
+*** True Line Result
+ @version = nil
+** Processing line: ~ @icon = nil~
+- Inside source: true
+*** True Line Result
+ @icon = nil
+** Processing line: ~ init_wizard_status~
+- Inside source: true
+*** True Line Result
+ init_wizard_status
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def restart~
+- Inside source: true
+*** True Line Result
+ def restart
+** Processing line: ~ reset~
+- Inside source: true
+*** True Line Result
+ reset
+** Processing line: ~ start~
+- Inside source: true
+*** True Line Result
+ start
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ reset~
+- Inside source: true
+*** True Line Result
+ reset
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def init_wizard_status~
+- Inside source: true
+*** True Line Result
+ def init_wizard_status
+** Processing line: ~ @wizard_status = {}~
+- Inside source: true
+*** True Line Result
+ @wizard_status = {}
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ steps.each do |m|~
+- Inside source: true
+*** True Line Result
+ steps.each do |m|
+** Processing line: ~ @wizard_status[m] = { result: :not_started }~
+- Inside source: true
+*** True Line Result
+ @wizard_status[m] = { result: :not_started }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ previous_step = nil~
+- Inside source: true
+*** True Line Result
+ previous_step = nil
+** Processing line: ~ next_step = nil~
+- Inside source: true
+*** True Line Result
+ next_step = nil
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ steps.each_cons(2) do |current_step, next_step|~
+- Inside source: true
+*** True Line Result
+ steps.each_cons(2) do |current_step, next_step|
+** Processing line: ~ @wizard_status[current_step][:next_step] = next_step~
+- Inside source: true
+*** True Line Result
+ @wizard_status[current_step][:next_step] = next_step
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ steps.reverse.each_cons(2) do |current_step, previous_step|~
+- Inside source: true
+*** True Line Result
+ steps.reverse.each_cons(2) do |current_step, previous_step|
+** Processing line: ~ @wizard_status[current_step][:previous_step] = previous_step~
+- Inside source: true
+*** True Line Result
+ @wizard_status[current_step][:previous_step] = previous_step
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~#+end_src~
+- Line was identified as the end of a code block.
+*** True Line Result
+#+end_src
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
+** Processing line: ~* layout.rb~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* layout.rb
+** Processing line: ~#+begin_src ruby~
+- Line was identified as the beginning of a code block.
+*** True Line Result
+
+*** True Line Result
+#+begin_src ruby
+** Processing line: ~ # ./dragon/layout.rb~
+- Inside source: true
+*** True Line Result
+ # ./dragon/layout.rb
+** Processing line: ~ # Copyright 2019 DragonRuby LLC~
+- Inside source: true
+*** True Line Result
+ # Copyright 2019 DragonRuby LLC
+** Processing line: ~ # MIT License~
+- Inside source: true
+*** True Line Result
+ # MIT License
+** Processing line: ~ # layout.rb has been released under MIT (*only this file*).~
+- Inside source: true
+*** True Line Result
+ # layout.rb has been released under MIT (*only this file*).
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ module GTK~
+- Inside source: true
+*** True Line Result
+ module GTK
+** Processing line: ~ class Margin~
+- Inside source: true
+*** True Line Result
+ class Margin
+** Processing line: ~ attr :left, :right, :top, :bottom~
+- Inside source: true
+*** True Line Result
+ attr :left, :right, :top, :bottom
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ @left = 0~
+- Inside source: true
+*** True Line Result
+ @left = 0
+** Processing line: ~ @right = 0~
+- Inside source: true
+*** True Line Result
+ @right = 0
+** Processing line: ~ @top = 0~
+- Inside source: true
+*** True Line Result
+ @top = 0
+** Processing line: ~ @bottom = 0~
+- Inside source: true
+*** True Line Result
+ @bottom = 0
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def serialize~
+- Inside source: true
+*** True Line Result
+ def serialize
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ left: @left,~
+- Inside source: true
+*** True Line Result
+ left: @left,
+** Processing line: ~ right: @right,~
+- Inside source: true
+*** True Line Result
+ right: @right,
+** Processing line: ~ top: @top,~
+- Inside source: true
+*** True Line Result
+ top: @top,
+** Processing line: ~ bottom: @bottom,~
+- Inside source: true
+*** True Line Result
+ bottom: @bottom,
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def inspect~
+- Inside source: true
+*** True Line Result
+ def inspect
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def to_s~
+- Inside source: true
+*** True Line Result
+ def to_s
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class SafeArea~
+- Inside source: true
+*** True Line Result
+ class SafeArea
+** Processing line: ~ attr :w, :h, :margin~
+- Inside source: true
+*** True Line Result
+ attr :w, :h, :margin
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ @w = 0~
+- Inside source: true
+*** True Line Result
+ @w = 0
+** Processing line: ~ @h = 0~
+- Inside source: true
+*** True Line Result
+ @h = 0
+** Processing line: ~ @margin = Margin.new~
+- Inside source: true
+*** True Line Result
+ @margin = Margin.new
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def serialize~
+- Inside source: true
+*** True Line Result
+ def serialize
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ w: @w,~
+- Inside source: true
+*** True Line Result
+ w: @w,
+** Processing line: ~ h: @h,~
+- Inside source: true
+*** True Line Result
+ h: @h,
+** Processing line: ~ margin: @margin.serialize~
+- Inside source: true
+*** True Line Result
+ margin: @margin.serialize
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def inspect~
+- Inside source: true
+*** True Line Result
+ def inspect
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def to_s~
+- Inside source: true
+*** True Line Result
+ def to_s
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class GridArea~
+- Inside source: true
+*** True Line Result
+ class GridArea
+** Processing line: ~ attr :w, :h, :margin, :gutter, :col_count, :row_count, :cell_w, :cell_h, :outer_gutter~
+- Inside source: true
+*** True Line Result
+ attr :w, :h, :margin, :gutter, :col_count, :row_count, :cell_w, :cell_h, :outer_gutter
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ @w = 0~
+- Inside source: true
+*** True Line Result
+ @w = 0
+** Processing line: ~ @h = 0~
+- Inside source: true
+*** True Line Result
+ @h = 0
+** Processing line: ~ @gutter = 0~
+- Inside source: true
+*** True Line Result
+ @gutter = 0
+** Processing line: ~ @outer_gutter = 0~
+- Inside source: true
+*** True Line Result
+ @outer_gutter = 0
+** Processing line: ~ @col_count = 0~
+- Inside source: true
+*** True Line Result
+ @col_count = 0
+** Processing line: ~ @row_count = 0~
+- Inside source: true
+*** True Line Result
+ @row_count = 0
+** Processing line: ~ @margin = Margin.new~
+- Inside source: true
+*** True Line Result
+ @margin = Margin.new
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def serialize~
+- Inside source: true
+*** True Line Result
+ def serialize
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ w: @w,~
+- Inside source: true
+*** True Line Result
+ w: @w,
+** Processing line: ~ h: @h,~
+- Inside source: true
+*** True Line Result
+ h: @h,
+** Processing line: ~ gutter: @gutter,~
+- Inside source: true
+*** True Line Result
+ gutter: @gutter,
+** Processing line: ~ outer_gutter: @outer_gutter,~
+- Inside source: true
+*** True Line Result
+ outer_gutter: @outer_gutter,
+** Processing line: ~ col_count: @col_count,~
+- Inside source: true
+*** True Line Result
+ col_count: @col_count,
+** Processing line: ~ row_count: @row_count,~
+- Inside source: true
+*** True Line Result
+ row_count: @row_count,
+** Processing line: ~ margin: @margin.serialize~
+- Inside source: true
+*** True Line Result
+ margin: @margin.serialize
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def inspect~
+- Inside source: true
+*** True Line Result
+ def inspect
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def to_s~
+- Inside source: true
+*** True Line Result
+ def to_s
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class ControlArea~
+- Inside source: true
+*** True Line Result
+ class ControlArea
+** Processing line: ~ attr :cell_size, :w, :h, :margin~
+- Inside source: true
+*** True Line Result
+ attr :cell_size, :w, :h, :margin
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ @margin = Margin.new~
+- Inside source: true
+*** True Line Result
+ @margin = Margin.new
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def serialize~
+- Inside source: true
+*** True Line Result
+ def serialize
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ cell_size: @cell_size,~
+- Inside source: true
+*** True Line Result
+ cell_size: @cell_size,
+** Processing line: ~ w: @w,~
+- Inside source: true
+*** True Line Result
+ w: @w,
+** Processing line: ~ h: @h,~
+- Inside source: true
+*** True Line Result
+ h: @h,
+** Processing line: ~ margin: @margin.serialize,~
+- Inside source: true
+*** True Line Result
+ margin: @margin.serialize,
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def inspect~
+- Inside source: true
+*** True Line Result
+ def inspect
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def to_s~
+- Inside source: true
+*** True Line Result
+ def to_s
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class Device~
+- Inside source: true
+*** True Line Result
+ class Device
+** Processing line: ~ attr :w, :h, :safe_area, :grid_area, :control_area, :name, :aspect~
+- Inside source: true
+*** True Line Result
+ attr :w, :h, :safe_area, :grid_area, :control_area, :name, :aspect
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ @name = ""~
+- Inside source: true
+*** True Line Result
+ @name = ""
+** Processing line: ~ @w = 0~
+- Inside source: true
+*** True Line Result
+ @w = 0
+** Processing line: ~ @h = 0~
+- Inside source: true
+*** True Line Result
+ @h = 0
+** Processing line: ~ @safe_area = SafeArea.new~
+- Inside source: true
+*** True Line Result
+ @safe_area = SafeArea.new
+** Processing line: ~ @grid_area = GridArea.new~
+- Inside source: true
+*** True Line Result
+ @grid_area = GridArea.new
+** Processing line: ~ @control_area = ControlArea.new~
+- Inside source: true
+*** True Line Result
+ @control_area = ControlArea.new
+** Processing line: ~ @aspect = AspectRatio.new~
+- Inside source: true
+*** True Line Result
+ @aspect = AspectRatio.new
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def assert! result, message~
+- Inside source: true
+*** True Line Result
+ def assert! result, message
+** Processing line: ~ return if result~
+- Inside source: true
+*** True Line Result
+ return if result
+** Processing line: ~ raise message~
+- Inside source: true
+*** True Line Result
+ raise message
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def check_math!~
+- Inside source: true
+*** True Line Result
+ def check_math!
+** Processing line: ~ assert! (@control_area.w + @control_area.margin.left + @control_area.margin.right) == @w, "Math for Width didn't pan out."~
+- Inside source: true
+*** True Line Result
+ assert! (@control_area.w + @control_area.margin.left + @control_area.margin.right) == @w, "Math for Width didn't pan out."
+** Processing line: ~ assert! (@control_area.h + @control_area.margin.top + @control_area.margin.bottom) == @h, "Math for Height didn't pan out."~
+- Inside source: true
+*** True Line Result
+ assert! (@control_area.h + @control_area.margin.top + @control_area.margin.bottom) == @h, "Math for Height didn't pan out."
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def serialize~
+- Inside source: true
+*** True Line Result
+ def serialize
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ name: @name,~
+- Inside source: true
+*** True Line Result
+ name: @name,
+** Processing line: ~ w: @w,~
+- Inside source: true
+*** True Line Result
+ w: @w,
+** Processing line: ~ h: @h,~
+- Inside source: true
+*** True Line Result
+ h: @h,
+** Processing line: ~ aspect: @aspect.serialize,~
+- Inside source: true
+*** True Line Result
+ aspect: @aspect.serialize,
+** Processing line: ~ safe_area: @safe_area.serialize,~
+- Inside source: true
+*** True Line Result
+ safe_area: @safe_area.serialize,
+** Processing line: ~ grid_area: @grid_area.serialize,~
+- Inside source: true
+*** True Line Result
+ grid_area: @grid_area.serialize,
+** Processing line: ~ control_area: @control_area.serialize~
+- Inside source: true
+*** True Line Result
+ control_area: @control_area.serialize
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def inspect~
+- Inside source: true
+*** True Line Result
+ def inspect
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def to_s~
+- Inside source: true
+*** True Line Result
+ def to_s
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class AspectRatio~
+- Inside source: true
+*** True Line Result
+ class AspectRatio
+** Processing line: ~ attr :w, :h, :u~
+- Inside source: true
+*** True Line Result
+ attr :w, :h, :u
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ @w = 0~
+- Inside source: true
+*** True Line Result
+ @w = 0
+** Processing line: ~ @h = 0~
+- Inside source: true
+*** True Line Result
+ @h = 0
+** Processing line: ~ @u = 0~
+- Inside source: true
+*** True Line Result
+ @u = 0
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def serialize~
+- Inside source: true
+*** True Line Result
+ def serialize
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ w: @w,~
+- Inside source: true
+*** True Line Result
+ w: @w,
+** Processing line: ~ h: @h,~
+- Inside source: true
+*** True Line Result
+ h: @h,
+** Processing line: ~ u: @u~
+- Inside source: true
+*** True Line Result
+ u: @u
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def inspect~
+- Inside source: true
+*** True Line Result
+ def inspect
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def to_s~
+- Inside source: true
+*** True Line Result
+ def to_s
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class Layout~
+- Inside source: true
+*** True Line Result
+ class Layout
+** Processing line: ~ attr :w, :h, :rect_cache~
+- Inside source: true
+*** True Line Result
+ attr :w, :h, :rect_cache
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize w, h~
+- Inside source: true
+*** True Line Result
+ def initialize w, h
+** Processing line: ~ @w = w~
+- Inside source: true
+*** True Line Result
+ @w = w
+** Processing line: ~ @h = h~
+- Inside source: true
+*** True Line Result
+ @h = h
+** Processing line: ~ @rect_cache = {}~
+- Inside source: true
+*** True Line Result
+ @rect_cache = {}
+** Processing line: ~ init_device @w, @h~
+- Inside source: true
+*** True Line Result
+ init_device @w, @h
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def u_for_16x9 w, h~
+- Inside source: true
+*** True Line Result
+ def u_for_16x9 w, h
+** Processing line: ~ u = (w.fdiv 16).floor~
+- Inside source: true
+*** True Line Result
+ u = (w.fdiv 16).floor
+** Processing line: ~ u = (h.fdiv 9).floor if (u * 9) > h~
+- Inside source: true
+*** True Line Result
+ u = (h.fdiv 9).floor if (u * 9) > h
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ u: u,~
+- Inside source: true
+*** True Line Result
+ u: u,
+** Processing line: ~ w: u * 16,~
+- Inside source: true
+*** True Line Result
+ w: u * 16,
+** Processing line: ~ h: u * 9~
+- Inside source: true
+*** True Line Result
+ h: u * 9
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_relative_size_enum size_enum~
+- Inside source: true
+*** True Line Result
+ def font_relative_size_enum size_enum
+** Processing line: ~ base_line_logical = 22~
+- Inside source: true
+*** True Line Result
+ base_line_logical = 22
+** Processing line: ~ base_line_actual = font_size_med~
+- Inside source: true
+*** True Line Result
+ base_line_actual = font_size_med
+** Processing line: ~ target_logical = size_enum~
+- Inside source: true
+*** True Line Result
+ target_logical = size_enum
+** Processing line: ~ target_logical = 1 if target_logical <= 0~
+- Inside source: true
+*** True Line Result
+ target_logical = 1 if target_logical <= 0
+** Processing line: ~ (base_line_actual / base_line_logical) * target_logical~
+- Inside source: true
+*** True Line Result
+ (base_line_actual / base_line_logical) * target_logical
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_px_to_pt px~
+- Inside source: true
+*** True Line Result
+ def font_px_to_pt px
+** Processing line: ~ (px / 1.33333).floor~
+- Inside source: true
+*** True Line Result
+ (px / 1.33333).floor
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_pt_to_px pt~
+- Inside source: true
+*** True Line Result
+ def font_pt_to_px pt
+** Processing line: ~ pt * 1.333333~
+- Inside source: true
+*** True Line Result
+ pt * 1.333333
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_size_cell~
+- Inside source: true
+*** True Line Result
+ def font_size_cell
+** Processing line: ~ (cell_height / 1.33333)~
+- Inside source: true
+*** True Line Result
+ (cell_height / 1.33333)
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_size_xl~
+- Inside source: true
+*** True Line Result
+ def font_size_xl
+** Processing line: ~ font_size_cell~
+- Inside source: true
+*** True Line Result
+ font_size_cell
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_size_lg~
+- Inside source: true
+*** True Line Result
+ def font_size_lg
+** Processing line: ~ font_size_cell * 0.8~
+- Inside source: true
+*** True Line Result
+ font_size_cell * 0.8
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_size_med~
+- Inside source: true
+*** True Line Result
+ def font_size_med
+** Processing line: ~ font_size_cell * 0.7~
+- Inside source: true
+*** True Line Result
+ font_size_cell * 0.7
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_size_sm~
+- Inside source: true
+*** True Line Result
+ def font_size_sm
+** Processing line: ~ font_size_cell * 0.6~
+- Inside source: true
+*** True Line Result
+ font_size_cell * 0.6
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_size_xs~
+- Inside source: true
+*** True Line Result
+ def font_size_xs
+** Processing line: ~ font_size_cell * 0.5~
+- Inside source: true
+*** True Line Result
+ font_size_cell * 0.5
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def font_size~
+- Inside source: true
+*** True Line Result
+ def font_size
+** Processing line: ~ font_size_cell * 0.7~
+- Inside source: true
+*** True Line Result
+ font_size_cell * 0.7
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def logical_rect~
+- Inside source: true
+*** True Line Result
+ def logical_rect
+** Processing line: ~ @logical_rect ||= { x: 0,~
+- Inside source: true
+*** True Line Result
+ @logical_rect ||= { x: 0,
+** Processing line: ~ y: 0,~
+- Inside source: true
+*** True Line Result
+ y: 0,
+** Processing line: ~ w: @w,~
+- Inside source: true
+*** True Line Result
+ w: @w,
+** Processing line: ~ h: @h }~
+- Inside source: true
+*** True Line Result
+ h: @h }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def safe_rect~
+- Inside source: true
+*** True Line Result
+ def safe_rect
+** Processing line: ~ @safe_rect ||= { x: 0,~
+- Inside source: true
+*** True Line Result
+ @safe_rect ||= { x: 0,
+** Processing line: ~ y: 0,~
+- Inside source: true
+*** True Line Result
+ y: 0,
+** Processing line: ~ w: @w,~
+- Inside source: true
+*** True Line Result
+ w: @w,
+** Processing line: ~ h: @h }~
+- Inside source: true
+*** True Line Result
+ h: @h }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def control_rect~
+- Inside source: true
+*** True Line Result
+ def control_rect
+** Processing line: ~ @control_rect ||= { x: device.control_area.margin.left,~
+- Inside source: true
+*** True Line Result
+ @control_rect ||= { x: device.control_area.margin.left,
+** Processing line: ~ y: device.control_area.margin.top,~
+- Inside source: true
+*** True Line Result
+ y: device.control_area.margin.top,
+** Processing line: ~ w: device.control_area.w,~
+- Inside source: true
+*** True Line Result
+ w: device.control_area.w,
+** Processing line: ~ h: device.control_area.h }~
+- Inside source: true
+*** True Line Result
+ h: device.control_area.h }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def row_count~
+- Inside source: true
+*** True Line Result
+ def row_count
+** Processing line: ~ device.grid_area.row_count~
+- Inside source: true
+*** True Line Result
+ device.grid_area.row_count
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def col_count~
+- Inside source: true
+*** True Line Result
+ def col_count
+** Processing line: ~ device.grid_area.col_count~
+- Inside source: true
+*** True Line Result
+ device.grid_area.col_count
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def gutter_height~
+- Inside source: true
+*** True Line Result
+ def gutter_height
+** Processing line: ~ device.grid_area.gutter~
+- Inside source: true
+*** True Line Result
+ device.grid_area.gutter
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def gutter_width~
+- Inside source: true
+*** True Line Result
+ def gutter_width
+** Processing line: ~ device.grid_area.gutter~
+- Inside source: true
+*** True Line Result
+ device.grid_area.gutter
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def outer_gutter~
+- Inside source: true
+*** True Line Result
+ def outer_gutter
+** Processing line: ~ device.grid_area.outer_gutter~
+- Inside source: true
+*** True Line Result
+ device.grid_area.outer_gutter
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def cell_height~
+- Inside source: true
+*** True Line Result
+ def cell_height
+** Processing line: ~ device.control_area.cell_size~
+- Inside source: true
+*** True Line Result
+ device.control_area.cell_size
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def cell_width~
+- Inside source: true
+*** True Line Result
+ def cell_width
+** Processing line: ~ device.control_area.cell_size~
+- Inside source: true
+*** True Line Result
+ device.control_area.cell_size
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def rect_defaults~
+- Inside source: true
+*** True Line Result
+ def rect_defaults
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ row: nil,~
+- Inside source: true
+*** True Line Result
+ row: nil,
+** Processing line: ~ col: nil,~
+- Inside source: true
+*** True Line Result
+ col: nil,
+** Processing line: ~ h: 1,~
+- Inside source: true
+*** True Line Result
+ h: 1,
+** Processing line: ~ w: 1,~
+- Inside source: true
+*** True Line Result
+ w: 1,
+** Processing line: ~ dx: 0,~
+- Inside source: true
+*** True Line Result
+ dx: 0,
+** Processing line: ~ dy: 0,~
+- Inside source: true
+*** True Line Result
+ dy: 0,
+** Processing line: ~ rect: :control_rect~
+- Inside source: true
+*** True Line Result
+ rect: :control_rect
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def rect opts~
+- Inside source: true
+*** True Line Result
+ def rect opts
+** Processing line: ~ opts = rect_defaults.merge opts~
+- Inside source: true
+*** True Line Result
+ opts = rect_defaults.merge opts
+** Processing line: ~ result = send opts[:rect]~
+- Inside source: true
+*** True Line Result
+ result = send opts[:rect]
+** Processing line: ~ if opts[:row] && opts[:col] && opts[:w] && opts[:h]~
+- Inside source: true
+*** True Line Result
+ if opts[:row] && opts[:col] && opts[:w] && opts[:h]
+** Processing line: ~ col = rect_col opts[:col], opts[:w]~
+- Inside source: true
+*** True Line Result
+ col = rect_col opts[:col], opts[:w]
+** Processing line: ~ row = rect_row opts[:row], opts[:h]~
+- Inside source: true
+*** True Line Result
+ row = rect_row opts[:row], opts[:h]
+** Processing line: ~ result = control_rect.merge x: col.x,~
+- Inside source: true
+*** True Line Result
+ result = control_rect.merge x: col.x,
+** Processing line: ~ y: row.y,~
+- Inside source: true
+*** True Line Result
+ y: row.y,
+** Processing line: ~ w: col.w,~
+- Inside source: true
+*** True Line Result
+ w: col.w,
+** Processing line: ~ h: row.h~
+- Inside source: true
+*** True Line Result
+ h: row.h
+** Processing line: ~ elsif opts[:row] && !opts[:col]~
+- Inside source: true
+*** True Line Result
+ elsif opts[:row] && !opts[:col]
+** Processing line: ~ result = rect_row opts[:row], opts[:h]~
+- Inside source: true
+*** True Line Result
+ result = rect_row opts[:row], opts[:h]
+** Processing line: ~ elsif !opts[:row] && opts[:col]~
+- Inside source: true
+*** True Line Result
+ elsif !opts[:row] && opts[:col]
+** Processing line: ~ result = rect_col opts[:col], opts[:w]~
+- Inside source: true
+*** True Line Result
+ result = rect_col opts[:col], opts[:w]
+** Processing line: ~ else~
+- Inside source: true
+*** True Line Result
+ else
+** Processing line: ~ raise "LayoutTheory::rect unable to process opts #{opts}."~
+- Inside source: true
+*** True Line Result
+ raise "LayoutTheory::rect unable to process opts #{opts}."
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if opts[:max_height] && opts[:max_height] >= 0~
+- Inside source: true
+*** True Line Result
+ if opts[:max_height] && opts[:max_height] >= 0
+** Processing line: ~ if result[:h] > opts[:max_height]~
+- Inside source: true
+*** True Line Result
+ if result[:h] > opts[:max_height]
+** Processing line: ~ delta = (result[:h] - opts[:max_height]) * 2~
+- Inside source: true
+*** True Line Result
+ delta = (result[:h] - opts[:max_height]) * 2
+** Processing line: ~ result[:y] += delta~
+- Inside source: true
+*** True Line Result
+ result[:y] += delta
+** Processing line: ~ result[:h] = opts[:max_height]~
+- Inside source: true
+*** True Line Result
+ result[:h] = opts[:max_height]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if opts[:max_width] && opts[:max_width] >= 0~
+- Inside source: true
+*** True Line Result
+ if opts[:max_width] && opts[:max_width] >= 0
+** Processing line: ~ if result[:w] > opts[:max_width]~
+- Inside source: true
+*** True Line Result
+ if result[:w] > opts[:max_width]
+** Processing line: ~ delta = (result[:w] - opts[:max_width]) * 2~
+- Inside source: true
+*** True Line Result
+ delta = (result[:w] - opts[:max_width]) * 2
+** Processing line: ~ result[:x] += delta~
+- Inside source: true
+*** True Line Result
+ result[:x] += delta
+** Processing line: ~ result[:w] = opts[:max_width]~
+- Inside source: true
+*** True Line Result
+ result[:w] = opts[:max_width]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ result[:x] += opts[:dx]~
+- Inside source: true
+*** True Line Result
+ result[:x] += opts[:dx]
+** Processing line: ~ result[:y] += opts[:dy]~
+- Inside source: true
+*** True Line Result
+ result[:y] += opts[:dy]
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if opts[:include_row_gutter]~
+- Inside source: true
+*** True Line Result
+ if opts[:include_row_gutter]
+** Processing line: ~ result[:x] -= device.grid_area.gutter~
+- Inside source: true
+*** True Line Result
+ result[:x] -= device.grid_area.gutter
+** Processing line: ~ result[:w] += device.grid_area.gutter * 2~
+- Inside source: true
+*** True Line Result
+ result[:w] += device.grid_area.gutter * 2
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ if opts[:include_col_gutter]~
+- Inside source: true
+*** True Line Result
+ if opts[:include_col_gutter]
+** Processing line: ~ result[:y] -= device.grid_area.gutter~
+- Inside source: true
+*** True Line Result
+ result[:y] -= device.grid_area.gutter
+** Processing line: ~ result[:h] += device.grid_area.gutter * 2~
+- Inside source: true
+*** True Line Result
+ result[:h] += device.grid_area.gutter * 2
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ result~
+- Inside source: true
+*** True Line Result
+ result
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def rect_center reference, target~
+- Inside source: true
+*** True Line Result
+ def rect_center reference, target
+** Processing line: ~ delta_x = (reference.w - target.w).fdiv 2~
+- Inside source: true
+*** True Line Result
+ delta_x = (reference.w - target.w).fdiv 2
+** Processing line: ~ delta_y = (reference.h - target.h).fdiv 2~
+- Inside source: true
+*** True Line Result
+ delta_y = (reference.h - target.h).fdiv 2
+** Processing line: ~ [target.x - delta_x, target.y - delta_y, target.w, target.h]~
+- Inside source: true
+*** True Line Result
+ [target.x - delta_x, target.y - delta_y, target.w, target.h]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def rect_row index, h~
+- Inside source: true
+*** True Line Result
+ def rect_row index, h
+** Processing line: ~ @rect_cache[:row] ||= {}~
+- Inside source: true
+*** True Line Result
+ @rect_cache[:row] ||= {}
+** Processing line: ~ @rect_cache[:row][index] ||= {}~
+- Inside source: true
+*** True Line Result
+ @rect_cache[:row][index] ||= {}
+** Processing line: ~ return @rect_cache[:row][index][h] if @rect_cache[:row][index][h]~
+- Inside source: true
+*** True Line Result
+ return @rect_cache[:row][index][h] if @rect_cache[:row][index][h]
+** Processing line: ~ row_h = (device.grid_area.gutter * (h - 1)) +~
+- Inside source: true
+*** True Line Result
+ row_h = (device.grid_area.gutter * (h - 1)) +
+** Processing line: ~ (device.control_area.cell_size * h)~
+- Inside source: true
+*** True Line Result
+ (device.control_area.cell_size * h)
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ row_h = row_h.to_i~
+- Inside source: true
+*** True Line Result
+ row_h = row_h.to_i
+** Processing line: ~ row_h -= 1 if row_h.odd?~
+- Inside source: true
+*** True Line Result
+ row_h -= 1 if row_h.odd?
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ row_y = (control_rect.y) +~
+- Inside source: true
+*** True Line Result
+ row_y = (control_rect.y) +
+** Processing line: ~ (device.grid_area.gutter * index) +~
+- Inside source: true
+*** True Line Result
+ (device.grid_area.gutter * index) +
+** Processing line: ~ (device.control_area.cell_size * index)~
+- Inside source: true
+*** True Line Result
+ (device.control_area.cell_size * index)
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ row_y = row_y.to_i~
+- Inside source: true
+*** True Line Result
+ row_y = row_y.to_i
+** Processing line: ~ row_y += 1 if row_y.odd? && (index + 1) > @device.grid_area.row_count.half~
+- Inside source: true
+*** True Line Result
+ row_y += 1 if row_y.odd? && (index + 1) > @device.grid_area.row_count.half
+** Processing line: ~ row_y += 1 if row_y.odd? && (index + 1) <= @device.grid_area.row_count.half~
+- Inside source: true
+*** True Line Result
+ row_y += 1 if row_y.odd? && (index + 1) <= @device.grid_area.row_count.half
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ row_y = device.h - row_y - row_h~
+- Inside source: true
+*** True Line Result
+ row_y = device.h - row_y - row_h
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ result = control_rect.merge y: row_y, h: row_h~
+- Inside source: true
+*** True Line Result
+ result = control_rect.merge y: row_y, h: row_h
+** Processing line: ~ @rect_cache[:row][index][h] = result~
+- Inside source: true
+*** True Line Result
+ @rect_cache[:row][index][h] = result
+** Processing line: ~ @rect_cache[:row][index][h]~
+- Inside source: true
+*** True Line Result
+ @rect_cache[:row][index][h]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def rect_col index, w~
+- Inside source: true
+*** True Line Result
+ def rect_col index, w
+** Processing line: ~ @rect_cache[:col] ||= {}~
+- Inside source: true
+*** True Line Result
+ @rect_cache[:col] ||= {}
+** Processing line: ~ @rect_cache[:col][index] ||= {}~
+- Inside source: true
+*** True Line Result
+ @rect_cache[:col][index] ||= {}
+** Processing line: ~ return @rect_cache[:col][index][w] if @rect_cache[:col][index][w]~
+- Inside source: true
+*** True Line Result
+ return @rect_cache[:col][index][w] if @rect_cache[:col][index][w]
+** Processing line: ~ col_x = (control_rect.x) +~
+- Inside source: true
+*** True Line Result
+ col_x = (control_rect.x) +
+** Processing line: ~ (device.grid_area.gutter * index) +~
+- Inside source: true
+*** True Line Result
+ (device.grid_area.gutter * index) +
+** Processing line: ~ (device.control_area.cell_size * index)~
+- Inside source: true
+*** True Line Result
+ (device.control_area.cell_size * index)
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ col_x = col_x.to_i~
+- Inside source: true
+*** True Line Result
+ col_x = col_x.to_i
+** Processing line: ~ col_x -= 1 if col_x.odd? && (index + 1) < @device.grid_area.col_count.half~
+- Inside source: true
+*** True Line Result
+ col_x -= 1 if col_x.odd? && (index + 1) < @device.grid_area.col_count.half
+** Processing line: ~ col_x += 1 if col_x.odd? && (index + 1) >= @device.grid_area.col_count.half~
+- Inside source: true
+*** True Line Result
+ col_x += 1 if col_x.odd? && (index + 1) >= @device.grid_area.col_count.half
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ col_w = (device.grid_area.gutter * (w - 1)) +~
+- Inside source: true
+*** True Line Result
+ col_w = (device.grid_area.gutter * (w - 1)) +
+** Processing line: ~ (device.control_area.cell_size * w)~
+- Inside source: true
+*** True Line Result
+ (device.control_area.cell_size * w)
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ col_w = col_w.to_i~
+- Inside source: true
+*** True Line Result
+ col_w = col_w.to_i
+** Processing line: ~ col_w -= 1 if col_w.odd?~
+- Inside source: true
+*** True Line Result
+ col_w -= 1 if col_w.odd?
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ result = control_rect.merge x: col_x, w: col_w~
+- Inside source: true
+*** True Line Result
+ result = control_rect.merge x: col_x, w: col_w
+** Processing line: ~ @rect_cache[:col][index][w] = result~
+- Inside source: true
+*** True Line Result
+ @rect_cache[:col][index][w] = result
+** Processing line: ~ @rect_cache[:col][index][w]~
+- Inside source: true
+*** True Line Result
+ @rect_cache[:col][index][w]
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def device~
+- Inside source: true
+*** True Line Result
+ def device
+** Processing line: ~ @device~
+- Inside source: true
+*** True Line Result
+ @device
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def init_device w, h~
+- Inside source: true
+*** True Line Result
+ def init_device w, h
+** Processing line: ~ @device = Device.new~
+- Inside source: true
+*** True Line Result
+ @device = Device.new
+** Processing line: ~ @device.w = w~
+- Inside source: true
+*** True Line Result
+ @device.w = w
+** Processing line: ~ @device.h = h~
+- Inside source: true
+*** True Line Result
+ @device.h = h
+** Processing line: ~ @device.name = "Device"~
+- Inside source: true
+*** True Line Result
+ @device.name = "Device"
+** Processing line: ~ @device.aspect.w = (u_for_16x9 w, h)[:w]~
+- Inside source: true
+*** True Line Result
+ @device.aspect.w = (u_for_16x9 w, h)[:w]
+** Processing line: ~ @device.aspect.h = (u_for_16x9 w, h)[:h]~
+- Inside source: true
+*** True Line Result
+ @device.aspect.h = (u_for_16x9 w, h)[:h]
+** Processing line: ~ @device.aspect.u = (u_for_16x9 w, h)[:u]~
+- Inside source: true
+*** True Line Result
+ @device.aspect.u = (u_for_16x9 w, h)[:u]
+** Processing line: ~ @device.safe_area.w = @device.aspect.u * 16~
+- Inside source: true
+*** True Line Result
+ @device.safe_area.w = @device.aspect.u * 16
+** Processing line: ~ @device.safe_area.h = @device.aspect.u * 9~
+- Inside source: true
+*** True Line Result
+ @device.safe_area.h = @device.aspect.u * 9
+** Processing line: ~ @device.safe_area.margin.left = ((@device.w - @device.safe_area.w).fdiv 2).floor~
+- Inside source: true
+*** True Line Result
+ @device.safe_area.margin.left = ((@device.w - @device.safe_area.w).fdiv 2).floor
+** Processing line: ~ @device.safe_area.margin.right = ((@device.w - @device.safe_area.w).fdiv 2).floor~
+- Inside source: true
+*** True Line Result
+ @device.safe_area.margin.right = ((@device.w - @device.safe_area.w).fdiv 2).floor
+** Processing line: ~ @device.safe_area.margin.top = ((@device.h - @device.safe_area.h).fdiv 2).floor~
+- Inside source: true
+*** True Line Result
+ @device.safe_area.margin.top = ((@device.h - @device.safe_area.h).fdiv 2).floor
+** Processing line: ~ @device.safe_area.margin.bottom = ((@device.h - @device.safe_area.h).fdiv 2).floor~
+- Inside source: true
+*** True Line Result
+ @device.safe_area.margin.bottom = ((@device.h - @device.safe_area.h).fdiv 2).floor
+** Processing line: ~ @device.grid_area.outer_gutter = @device.w / 80~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.outer_gutter = @device.w / 80
+** Processing line: ~ @device.grid_area.gutter = @device.w / 160~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.gutter = @device.w / 160
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @device.grid_area.w = @device.safe_area.w - (@device.grid_area.outer_gutter * 2)~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.w = @device.safe_area.w - (@device.grid_area.outer_gutter * 2)
+** Processing line: ~ @device.grid_area.h = @device.safe_area.h - (@device.grid_area.outer_gutter * 2)~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.h = @device.safe_area.h - (@device.grid_area.outer_gutter * 2)
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @device.grid_area.margin.left = ((@device.w - @device.grid_area.w).fdiv 2).floor~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.margin.left = ((@device.w - @device.grid_area.w).fdiv 2).floor
+** Processing line: ~ @device.grid_area.margin.right = ((@device.w - @device.grid_area.w).fdiv 2).floor~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.margin.right = ((@device.w - @device.grid_area.w).fdiv 2).floor
+** Processing line: ~ @device.grid_area.margin.top = ((@device.h - @device.grid_area.h).fdiv 2).floor~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.margin.top = ((@device.h - @device.grid_area.h).fdiv 2).floor
+** Processing line: ~ @device.grid_area.margin.bottom = ((@device.h - @device.grid_area.h).fdiv 2).floor~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.margin.bottom = ((@device.h - @device.grid_area.h).fdiv 2).floor
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @device.grid_area.col_count = 24~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.col_count = 24
+** Processing line: ~ @device.grid_area.row_count = 12~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.row_count = 12
+** Processing line: ~ @device.grid_area.cell_w = ((@device.aspect.w - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.col_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.col_count~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.cell_w = ((@device.aspect.w - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.col_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.col_count
+** Processing line: ~ @device.grid_area.cell_h = ((@device.aspect.h - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.row_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.row_count~
+- Inside source: true
+*** True Line Result
+ @device.grid_area.cell_h = ((@device.aspect.h - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.row_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.row_count
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ @device.control_area.cell_size = @device.grid_area.cell_w~
+- Inside source: true
+*** True Line Result
+ @device.control_area.cell_size = @device.grid_area.cell_w
+** Processing line: ~ @device.control_area.cell_size = @device.grid_area.cell_h if @device.grid_area.cell_h < @device.grid_area.cell_w && @device.grid_area.cell_h > 0~
+- Inside source: true
+*** True Line Result
+ @device.control_area.cell_size = @device.grid_area.cell_h if @device.grid_area.cell_h < @device.grid_area.cell_w && @device.grid_area.cell_h > 0
+** Processing line: ~ @device.control_area.cell_size = @device.control_area.cell_size.floor~
+- Inside source: true
+*** True Line Result
+ @device.control_area.cell_size = @device.control_area.cell_size.floor
+** Processing line: ~ @device.control_area.w = (@device.control_area.cell_size * @device.grid_area.col_count) + (@device.grid_area.gutter * (@device.grid_area.col_count - 1))~
+- Inside source: true
+*** True Line Result
+ @device.control_area.w = (@device.control_area.cell_size * @device.grid_area.col_count) + (@device.grid_area.gutter * (@device.grid_area.col_count - 1))
+** Processing line: ~ @device.control_area.h = (@device.control_area.cell_size * @device.grid_area.row_count) + (@device.grid_area.gutter * (@device.grid_area.row_count - 1))~
+- Inside source: true
+*** True Line Result
+ @device.control_area.h = (@device.control_area.cell_size * @device.grid_area.row_count) + (@device.grid_area.gutter * (@device.grid_area.row_count - 1))
+** Processing line: ~ @device.control_area.margin.left = (@device.w - @device.control_area.w).fdiv 2~
+- Inside source: true
+*** True Line Result
+ @device.control_area.margin.left = (@device.w - @device.control_area.w).fdiv 2
+** Processing line: ~ @device.control_area.margin.right = (@device.w - @device.control_area.w).fdiv 2~
+- Inside source: true
+*** True Line Result
+ @device.control_area.margin.right = (@device.w - @device.control_area.w).fdiv 2
+** Processing line: ~ @device.control_area.margin.top = (@device.h - @device.control_area.h).fdiv 2~
+- Inside source: true
+*** True Line Result
+ @device.control_area.margin.top = (@device.h - @device.control_area.h).fdiv 2
+** Processing line: ~ @device.control_area.margin.bottom = (@device.h - @device.control_area.h).fdiv 2~
+- Inside source: true
+*** True Line Result
+ @device.control_area.margin.bottom = (@device.h - @device.control_area.h).fdiv 2
+** Processing line: ~ @device~
+- Inside source: true
+*** True Line Result
+ @device
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def serialize~
+- Inside source: true
+*** True Line Result
+ def serialize
+** Processing line: ~ {~
+- Inside source: true
+*** True Line Result
+ {
+** Processing line: ~ device: @device.serialize,~
+- Inside source: true
+*** True Line Result
+ device: @device.serialize,
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def inspect~
+- Inside source: true
+*** True Line Result
+ def inspect
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def to_s~
+- Inside source: true
+*** True Line Result
+ def to_s
+** Processing line: ~ serialize.to_s~
+- Inside source: true
+*** True Line Result
+ serialize.to_s
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~#+end_src~
+- Line was identified as the end of a code block.
+*** True Line Result
+#+end_src
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
** Processing line: ~* log.rb~
- Header detected.
*** True Line Result
@@ -105891,6 +113899,26 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def from_right~
+- Inside source: true
+*** True Line Result
+ def from_right
+** Processing line: ~ return 1280 - self unless $gtk~
+- Inside source: true
+*** True Line Result
+ return 1280 - self unless $gtk
+** Processing line: ~ $gtk.args.grid.w - self~
+- Inside source: true
+*** True Line Result
+ $gtk.args.grid.w - self
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
** Processing line: ~ end~
- Inside source: true
*** True Line Result
@@ -107379,6 +115407,54 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def pixel_arrays~
+- Inside source: true
+*** True Line Result
+ def pixel_arrays
+** Processing line: ~ @args.pixel_arrays.each { |k,v|~
+- Inside source: true
+*** True Line Result
+ @args.pixel_arrays.each { |k,v|
+** Processing line: ~ if v.pixels.length == (v.width * v.height) # !!! FIXME: warning? exception? Different API?~
+- Inside source: true
+*** True Line Result
+ if v.pixels.length == (v.width * v.height) # !!! FIXME: warning? exception? Different API?
+** Processing line: ~ @ffi_draw.upload_pixel_array k.to_s, v.width.to_i, v.height.to_i, v.pixels~
+- Inside source: true
+*** True Line Result
+ @ffi_draw.upload_pixel_array k.to_s, v.width.to_i, v.height.to_i, v.pixels
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ rescue Exception => e~
+- Inside source: true
+*** True Line Result
+ rescue Exception => e
+** Processing line: ~ pause!~
+- Inside source: true
+*** True Line Result
+ pause!
+** Processing line: ~ pretty_print_exception_and_export! e~
+- Inside source: true
+*** True Line Result
+ pretty_print_exception_and_export! e
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ end~
- Inside source: true
*** True Line Result
@@ -109179,6 +117255,18 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~ # Contributors outside of DragonRuby who also hold Copyright:~
+- Inside source: true
+*** True Line Result
+ # Contributors outside of DragonRuby who also hold Copyright:
+** Processing line: ~ # - Dan Healy: https://github.com/danhealy~
+- Inside source: true
+*** True Line Result
+ # - Dan Healy: https://github.com/danhealy
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ module GTK~
- Inside source: true
*** True Line Result
@@ -109495,6 +117583,38 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
+** Processing line: ~ def self.trace_times_string~
+- Inside source: true
+*** True Line Result
+ def self.trace_times_string
+** Processing line: ~ str = []~
+- Inside source: true
+*** True Line Result
+ str = []
+** Processing line: ~ $trace_performance.sort_by {|method_name, times| -times[:avg] }.each do |method_name, times|~
+- Inside source: true
+*** True Line Result
+ $trace_performance.sort_by {|method_name, times| -times[:avg] }.each do |method_name, times|
+** Processing line: ~ str << "#{method_name}: #{times[:sum].round(2)}/#{times[:count]} #{times[:min]}ms min, #{times[:avg].round(2)}ms avg, #{times[:max]}ms max"~
+- Inside source: true
+*** True Line Result
+ str << "#{method_name}: #{times[:sum].round(2)}/#{times[:count]} #{times[:min]}ms min, #{times[:avg].round(2)}ms avg, #{times[:max]}ms max"
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ str.join("\n")~
+- Inside source: true
+*** True Line Result
+ str.join("\n")
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ def self.flush_trace pad_with_newline = false~
- Inside source: true
*** True Line Result
@@ -109503,14 +117623,18 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
$trace_puts ||= []
+** Processing line: ~ puts "(Trace info flushed!)"~
+- Inside source: true
+*** True Line Result
+ puts "(Trace info flushed!)"
** Processing line: ~ if $trace_puts.length > 0~
- Inside source: true
*** True Line Result
if $trace_puts.length > 0
-** Processing line: ~ text = $trace_puts.join("")~
+** Processing line: ~ text = $trace_puts.join("").strip + "\n" + self.trace_times_string + "\n"~
- Inside source: true
*** True Line Result
- text = $trace_puts.join("")
+ text = $trace_puts.join("").strip + "\n" + self.trace_times_string + "\n"
** Processing line: ~ if pad_with_newline~
- Inside source: true
*** True Line Result
@@ -109567,6 +117691,42 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
$trace_call_depth ||=0
+** Processing line: ~ $trace_performance = Hash.new {|h,k|~
+- Inside source: true
+*** True Line Result
+ $trace_performance = Hash.new {|h,k|
+** Processing line: ~ h[k] = {~
+- Inside source: true
+*** True Line Result
+ h[k] = {
+** Processing line: ~ min: 100000,~
+- Inside source: true
+*** True Line Result
+ min: 100000,
+** Processing line: ~ max: 0,~
+- Inside source: true
+*** True Line Result
+ max: 0,
+** Processing line: ~ avg: 0,~
+- Inside source: true
+*** True Line Result
+ avg: 0,
+** Processing line: ~ sum: 0,~
+- Inside source: true
+*** True Line Result
+ sum: 0,
+** Processing line: ~ count: 0~
+- Inside source: true
+*** True Line Result
+ count: 0
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
+** Processing line: ~ }~
+- Inside source: true
+*** True Line Result
+ }
** Processing line: ~ flush_trace~
- Inside source: true
*** True Line Result
@@ -109635,14 +117795,26 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
parameters = "#{args}"[1..-2]
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ $trace_puts << "\n #{tab_width}#{m}(#{parameters})"~
- Inside source: true
*** True Line Result
$trace_puts << "\n #{tab_width}#{m}(#{parameters})"
-** Processing line: ~ execution_time = Time.new.to_i~
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ execution_time = Time.new~
- Inside source: true
*** True Line Result
- execution_time = Time.new.to_i
+ execution_time = Time.new
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ $last_method_traced = trace_method_name~
- Inside source: true
*** True Line Result
@@ -109651,14 +117823,50 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
$trace_history << [m, parameters]
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ result = send(trace_method_name, *args)~
- Inside source: true
*** True Line Result
result = send(trace_method_name, *args)
-** Processing line: ~ completion_time = Time.new.to_i~
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ class_m = "#{instance.class}##{m}"~
- Inside source: true
*** True Line Result
- completion_time = Time.new.to_i
+ class_m = "#{instance.class}##{m}"
+** Processing line: ~ completion_time = ((Time.new - execution_time).to_f * 1000).round(2)~
+- Inside source: true
+*** True Line Result
+ completion_time = ((Time.new - execution_time).to_f * 1000).round(2)
+** Processing line: ~ $trace_performance[class_m][:min] = [$trace_performance[class_m][:min], completion_time].min~
+- Inside source: true
+*** True Line Result
+ $trace_performance[class_m][:min] = [$trace_performance[class_m][:min], completion_time].min
+** Processing line: ~ $trace_performance[class_m][:max] = [$trace_performance[class_m][:max], completion_time].max~
+- Inside source: true
+*** True Line Result
+ $trace_performance[class_m][:max] = [$trace_performance[class_m][:max], completion_time].max
+** Processing line: ~ $trace_performance[class_m][:count] += 1~
+- Inside source: true
+*** True Line Result
+ $trace_performance[class_m][:count] += 1
+** Processing line: ~ $trace_performance[class_m][:sum] += completion_time~
+- Inside source: true
+*** True Line Result
+ $trace_performance[class_m][:sum] += completion_time
+** Processing line: ~ $trace_performance[class_m][:avg] = $trace_performance[class_m][:sum].fdiv($trace_performance[class_m][:count])~
+- Inside source: true
+*** True Line Result
+ $trace_performance[class_m][:avg] = $trace_performance[class_m][:sum].fdiv($trace_performance[class_m][:count])
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
** Processing line: ~ instance.__trace_call_depth__ -= 1~
- Inside source: true
*** True Line Result
@@ -109667,10 +117875,10 @@ Follows is a source code listing for all files that have been open sourced. This
- Inside source: true
*** True Line Result
instance.__trace_call_depth__ = instance.__trace_call_depth__.greater 0
-** Processing line: ~ $trace_puts << "\n #{tab_width} success: #{m}"~
+** Processing line: ~ $trace_puts << "\n #{tab_width} #{completion_time > 10 ? '!!! ' : ''}#{completion_time}ms success: #{m}"~
- Inside source: true
*** True Line Result
- $trace_puts << "\n #{tab_width} success: #{m}"
+ $trace_puts << "\n #{tab_width} #{completion_time > 10 ? '!!! ' : ''}#{completion_time}ms success: #{m}"
** Processing line: ~ if instance.__trace_call_depth__ == 0~
- Inside source: true
*** True Line Result
@@ -109771,6 +117979,90 @@ Follows is a source code listing for all files that have been open sourced. This
- Line was identified as the end of a code block.
*** True Line Result
#+end_src
+** Processing line: ~~
+- End of paragraph detected.
+*** True Line Result
+
+** Processing line: ~* wizards.rb~
+- Header detected.
+*** True Line Result
+
+*** True Line Result
+* wizards.rb
+** Processing line: ~#+begin_src ruby~
+- Line was identified as the beginning of a code block.
+*** True Line Result
+
+*** True Line Result
+#+begin_src ruby
+** Processing line: ~ # ./dragon/wizards.rb~
+- Inside source: true
+*** True Line Result
+ # ./dragon/wizards.rb
+** Processing line: ~ # Copyright 2019 DragonRuby LLC~
+- Inside source: true
+*** True Line Result
+ # Copyright 2019 DragonRuby LLC
+** Processing line: ~ # MIT License~
+- Inside source: true
+*** True Line Result
+ # MIT License
+** Processing line: ~ # wizards.rb has been released under MIT (*only this file*).~
+- Inside source: true
+*** True Line Result
+ # wizards.rb has been released under MIT (*only this file*).
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ module GTK~
+- Inside source: true
+*** True Line Result
+ module GTK
+** Processing line: ~ class Wizards~
+- Inside source: true
+*** True Line Result
+ class Wizards
+** Processing line: ~ attr_accessor :ios, :itch~
+- Inside source: true
+*** True Line Result
+ attr_accessor :ios, :itch
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~ def initialize~
+- Inside source: true
+*** True Line Result
+ def initialize
+** Processing line: ~ @ios = IOSWizard.new~
+- Inside source: true
+*** True Line Result
+ @ios = IOSWizard.new
+** Processing line: ~ @itch = ItchWizard.new~
+- Inside source: true
+*** True Line Result
+ @itch = ItchWizard.new
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~ end~
+- Inside source: true
+*** True Line Result
+ end
+** Processing line: ~~
+- Inside source: true
+*** True Line Result
+
+** Processing line: ~#+end_src~
+- Line was identified as the end of a code block.
+*** True Line Result
+#+end_src
* Processing Html Given True Lines
** Processing line: ~* DragonRuby Game Toolkit Live Docs~
- H1 detected.
@@ -112790,6 +121082,22 @@ Follows is a source code listing for all files that have been open sourced. This
- PRE end detected.
** Processing line: ~~
** Processing line: ~~
+** Processing line: ~* DOCS: ~GTK::Runtime#reset~~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~DOCS: ~GTK::Runtime#reset~~
+- Line's tilde count is: 2
+- Line contains link marker: false
+- CODE detected.
+** Processing line: ~This function will reset Kernel.tick_count to 0 and will remove all data from args.state.~
+- P detected.
+- Determining if line is a header.
+- Line does not appear to be a header.
+- Formatting line: ~This function will reset Kernel.tick_count to 0 and will remove all data from args.state.~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
** Processing line: ~* DOCS: ~GTK::Runtime#calcstringbox~~
- H1 detected.
- Determining if line is a header.
@@ -112816,22 +121124,6 @@ Follows is a source code listing for all files that have been open sourced. This
- PRE end detected.
** Processing line: ~~
** Processing line: ~~
-** Processing line: ~* DOCS: ~GTK::Runtime#reset~~
-- H1 detected.
-- Determining if line is a header.
-- Line contains ~* ~... gsub-ing empty string
-- Formatting line: ~DOCS: ~GTK::Runtime#reset~~
-- Line's tilde count is: 2
-- Line contains link marker: false
-- CODE detected.
-** Processing line: ~This function will reset Kernel.tick_count to 0 and will remove all data from args.state.~
-- P detected.
-- Determining if line is a header.
-- Line does not appear to be a header.
-- Formatting line: ~This function will reset Kernel.tick_count to 0 and will remove all data from args.state.~
-- Line's tilde count is: 0
-- Line contains link marker: false
-** Processing line: ~~
** Processing line: ~* DOCS: ~Array~~
- H1 detected.
- Determining if line is a header.
@@ -113511,6 +121803,65 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~~
** Processing line: ~~
** Processing line: ~~
+** Processing line: ~* DOCS: ~GTK::Outputs#screenshots~~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~DOCS: ~GTK::Outputs#screenshots~~
+- Line's tilde count is: 2
+- Line contains link marker: false
+- CODE detected.
+** Processing line: ~~
+** Processing line: ~Add a hash to this collection to take a screenshot and save as png file. The keys of the hash can be provided in any order.~
+- P detected.
+- Determining if line is a header.
+- Line does not appear to be a header.
+- Formatting line: ~Add a hash to this collection to take a screenshot and save as png file. The keys of the hash can be provided in any order.~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~#+begin_src~
+- PRE start detected.
+** Processing line: ~ def tick args~
+** Processing line: ~ args.outputs.screenshots << {~
+** Processing line: ~ x: 0, y: 0, w: 100, h: 100, # Which portion of the screen should be captured~
+** Processing line: ~ path: 'screenshot.png', # Output path of PNG file (inside game directory)~
+** Processing line: ~ r: 255, g: 255, b: 255, a: 0 # Optional chroma key~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~#+end_src~
+- PRE end detected.
+** Processing line: ~~
+** Processing line: ~~
+** Processing line: ~** Chroma key (Making a color transparent)~
+- H2 detected.
+- Determining if line is a header.
+- Line contains ~** ~... gsub-ing empty string
+- Formatting line: ~Chroma key (Making a color transparent)~
+- Line's tilde count is: 0
+- Line contains link marker: false
+- Determining if line is a header.
+- Line contains ~** ~... gsub-ing empty string
+- Formatting line: ~Chroma key (Making a color transparent)~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~By specifying the r, g, b and a keys of the hash you change the transparency of a color in the resulting PNG file. This can be useful if you want to create files with transparent background like spritesheets. The transparency of the color specified by ~r~, ~g~, ~b~ will be set to the transparency specified by ~a~.~
+- P detected.
+- Determining if line is a header.
+- Line does not appear to be a header.
+- Formatting line: ~By specifying the r, g, b and a keys of the hash you change the transparency of a color in the resulting PNG file. This can be useful if you want to create files with transparent background like spritesheets. The transparency of the color specified by ~r~, ~g~, ~b~ will be set to the transparency specified by ~a~.~
+- Line's tilde count is: 8
+- Line contains link marker: false
+- CODE detected.
+** Processing line: ~The example above sets the color white (255, 255, 255) as transparent.~
+- P detected.
+- Determining if line is a header.
+- Line does not appear to be a header.
+- Formatting line: ~The example above sets the color white (255, 255, 255) as transparent.~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
** Processing line: ~* DOCS: ~GTK::Mouse~~
- H1 detected.
- Determining if line is a header.
@@ -115461,22 +123812,6 @@ Follows is a source code listing for all files that have been open sourced. This
- PRE end detected.
** Processing line: ~~
** Processing line: ~~
-** Processing line: ~* Learn Ruby Optional - Intermediate Ruby Primer - repl.rb~
-- H1 detected.
-- Determining if line is a header.
-- Line contains ~* ~... gsub-ing empty string
-- Formatting line: ~Learn Ruby Optional - Intermediate Ruby Primer - repl.rb~
-- Line's tilde count is: 0
-- Line contains link marker: false
-** Processing line: ~~
-** Processing line: ~#+begin_src ruby~
-- PRE start detected.
-** Processing line: ~ # ./samples/00_learn_ruby_optional/00_intermediate_ruby_primer/app/repl.rb~
-** Processing line: ~~
-** Processing line: ~#+end_src~
-- PRE end detected.
-** Processing line: ~~
-** Processing line: ~~
** Processing line: ~* Rendering Basics - Labels - main.rb~
- H1 detected.
- Determining if line is a header.
@@ -116114,6 +124449,9 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ end~
** Processing line: ~~
** Processing line: ~ def spawn_new_sound args, num~
+** Processing line: ~ input = nil~
+** Processing line: ~ input = "sounds/#{num}.#{(num == 6) ? 'ogg' : 'wav'}"~
+** Processing line: ~~
** Processing line: ~ # Spawn randomly in an area that won't be covered by UI.~
** Processing line: ~ screenx = (rand * 600.0) + 200.0~
** Processing line: ~ screeny = (rand * 400.0) + 100.0~
@@ -116123,7 +124461,7 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ # you can hang anything on the audio hashes you want, so we store the~
** Processing line: ~ # actual screen position in here for convenience.~
** Processing line: ~ args.audio[args.state.next_sound_index] = {~
-** Processing line: ~ filename: "sounds/#{num}.#{(num == 6) ? 'ogg' : 'wav'}",~
+** Processing line: ~ input: input,~
** Processing line: ~ screenx: screenx,~
** Processing line: ~ screeny: screeny,~
** Processing line: ~ x: ((screenx / 1279.0) * 2.0) - 1.0, # scale to -1.0 - 1.0 range~
@@ -116177,6 +124515,377 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ render_ui args~
** Processing line: ~ end~
** Processing line: ~~
+** Processing line: ~#+end_src~
+- PRE end detected.
+** Processing line: ~~
+** Processing line: ~~
+** Processing line: ~* Rendering Basics - Sound Synthesis - main.rb~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~Rendering Basics - Sound Synthesis - main.rb~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~#+begin_src ruby~
+- PRE start detected.
+** Processing line: ~ # ./samples/01_rendering_basics/07_sound_synthesis/app/main.rb~
+** Processing line: ~ def tick args~
+** Processing line: ~ defaults args~
+** Processing line: ~ render args~
+** Processing line: ~ input args~
+** Processing line: ~ process_audio_queue args~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def defaults args~
+** Processing line: ~ args.state.sine_waves ||= {}~
+** Processing line: ~ args.state.audio_queue ||= []~
+** Processing line: ~ args.state.buttons ||= [~
+** Processing line: ~ (frequency_buttons args),~
+** Processing line: ~ (note_buttons args),~
+** Processing line: ~ (bell_buttons args)~
+** Processing line: ~ ].flatten~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def frequency_buttons args~
+** Processing line: ~ [~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 4.0, col: 0, text: "300hz",~
+** Processing line: ~ frequency: 300,~
+** Processing line: ~ method_to_call: :play_sine_wave),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 5.0, col: 0, text: "400hz",~
+** Processing line: ~ frequency: 400,~
+** Processing line: ~ method_to_call: :play_sine_wave),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 6.0, col: 0, text: "500hz",~
+** Processing line: ~ frequency: 500,~
+** Processing line: ~ method_to_call: :play_sine_wave),~
+** Processing line: ~ ]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def play_sine_wave args, sender~
+** Processing line: ~ queue_sine_wave args,~
+** Processing line: ~ frequency: sender[:frequency],~
+** Processing line: ~ duration: 1.seconds,~
+** Processing line: ~ fade_out: true~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~~
+** Processing line: ~ def note_buttons args~
+** Processing line: ~ [~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 1.5, col: 3, text: "C4",~
+** Processing line: ~ note: :c, octave: 4, method_to_call: :play_note),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 2.5, col: 3, text: "D4",~
+** Processing line: ~ note: :d, octave: 4, method_to_call: :play_note),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 3.5, col: 3, text: "E4",~
+** Processing line: ~ note: :e, octave: 4, method_to_call: :play_note),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 4.5, col: 3, text: "F4",~
+** Processing line: ~ note: :f, octave: 4, method_to_call: :play_note),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 5.5, col: 3, text: "G4",~
+** Processing line: ~ note: :g, octave: 4, method_to_call: :play_note),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 6.5, col: 3, text: "A5",~
+** Processing line: ~ note: :a, octave: 5, method_to_call: :play_note),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 7.5, col: 3, text: "B5",~
+** Processing line: ~ note: :b, octave: 5, method_to_call: :play_note),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 8.5, col: 3, text: "C5",~
+** Processing line: ~ note: :c, octave: 5, method_to_call: :play_note),~
+** Processing line: ~ ]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def play_note args, sender~
+** Processing line: ~ queue_sine_wave args,~
+** Processing line: ~ frequency: (frequency_for note: sender[:note],~
+** Processing line: ~ octave: sender[:octave]),~
+** Processing line: ~ duration: 1.seconds,~
+** Processing line: ~ fade_out: true~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def bell_buttons args~
+** Processing line: ~ [~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 1.5, col: 6, text: "Bell C4",~
+** Processing line: ~ note: :c, octave: 4, method_to_call: :play_bell),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 2.5, col: 6, text: "Bell D4",~
+** Processing line: ~ note: :d, octave: 4, method_to_call: :play_bell),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 3.5, col: 6, text: "Bell E4",~
+** Processing line: ~ note: :e, octave: 4, method_to_call: :play_bell),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 4.5, col: 6, text: "Bell F4",~
+** Processing line: ~ note: :f, octave: 4, method_to_call: :play_bell),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 5.5, col: 6, text: "Bell G4",~
+** Processing line: ~ note: :g, octave: 4, method_to_call: :play_bell),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 6.5, col: 6, text: "Bell A5",~
+** Processing line: ~ note: :a, octave: 5, method_to_call: :play_bell),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 7.5, col: 6, text: "Bell B5",~
+** Processing line: ~ note: :b, octave: 5, method_to_call: :play_bell),~
+** Processing line: ~ (button args,~
+** Processing line: ~ row: 8.5, col: 6, text: "Bell C5",~
+** Processing line: ~ note: :c, octave: 5, method_to_call: :play_bell),~
+** Processing line: ~ ]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def play_bell args, sender~
+** Processing line: ~ queue_bell args,~
+** Processing line: ~ frequency: (frequency_for note: sender[:note],~
+** Processing line: ~ octave: sender[:octave]),~
+** Processing line: ~ duration: 2.seconds,~
+** Processing line: ~ fade_out: true~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def render args~
+** Processing line: ~ args.outputs.borders << args.state.buttons.map { |b| b[:border] }~
+** Processing line: ~ args.outputs.labels << args.state.buttons.map { |b| b[:label] }~
+** Processing line: ~ args.outputs.labels << args.layout~
+** Processing line: ~ .rect(row: 0,~
+** Processing line: ~ col: 11.5)~
+** Processing line: ~ .yield_self { |r| r.merge y: r.y + r.h }~
+** Processing line: ~ .merge(text: "This is a Pro only feature. Click here to watch the YouTube video if you are on the Standard License.",~
+** Processing line: ~ alignment_enum: 1)~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def input args~
+** Processing line: ~ args.state.buttons.each do |b|~
+** Processing line: ~ if args.inputs.mouse.click.inside_rect? b[:rect]~
+** Processing line: ~ parameter_string = (b.slice :frequency, :note, :octave).map { |k, v| "#{k}: #{v}" }.join ", "~
+** Processing line: ~ args.gtk.notify! "#{b[:method_to_call]} #{parameter_string}"~
+** Processing line: ~ send b[:method_to_call], args, b~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if args.inputs.mouse.click.inside_rect? (args.layout.rect(row: 0).yield_self { |r| r.merge y: r.y + r.h.half, h: r.h.half })~
+** Processing line: ~ args.gtk.openurl 'https://www.youtube.com/watch?v=zEzovM5jT-k&ab_channel=AmirRajan'~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def process_audio_queue args~
+** Processing line: ~ to_queue = args.state.audio_queue.find_all { |v| v[:queue_at] <= args.tick_count }~
+** Processing line: ~ args.state.audio_queue -= to_queue~
+** Processing line: ~~
+** Processing line: ~ to_queue.each do |a|~
+** Processing line: ~ args.audio[a[:id]] = a~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ args.audio.each do |k, v|~
+** Processing line: ~ if v[:decay_rate]~
+** Processing line: ~ v[:gain] -= v[:decay_rate]~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ sounds_to_stop = args.audio.find_all do |k, v|~
+** Processing line: ~ v[:stop_at] && args.state.tick_count >= v[:stop_at]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ sounds_to_stop.each do |(k, v)|~
+** Processing line: ~ args.audio.delete k~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def graph_sine_wave args, sine_wave, frequency~
+** Processing line: ~ if args.state.tick_count != args.state.graphed_at~
+** Processing line: ~ args.outputs.static_lines.clear~
+** Processing line: ~ args.outputs.static_sprites.clear~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ r, g, b = frequency.to_i % 80, frequency.to_i % 128, frequency.to_i % 255~
+** Processing line: ~ center_row = args.layout.rect(row: 5, col: 9)~
+** Processing line: ~ x_scale = 20~
+** Processing line: ~ y_scale = 100~
+** Processing line: ~ max_points = 20~
+** Processing line: ~~
+** Processing line: ~ points = sine_wave~
+** Processing line: ~ if sine_wave.length > max_points~
+** Processing line: ~ resolution = sine_wave.length.idiv max_points~
+** Processing line: ~ points = sine_wave.find_all~
+** Processing line: ~ .with_index { |y, i| i % resolution == 0 }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ args.outputs.static_lines << points.map_with_index do |y, x|~
+** Processing line: ~ next_y = points[x + 1]~
+** Processing line: ~~
+** Processing line: ~ if next_y~
+** Processing line: ~ {~
+** Processing line: ~ x: center_row.x + (x * x_scale),~
+** Processing line: ~ y: center_row.y + center_row.h.half + y_scale * y,~
+** Processing line: ~ x2: center_row.x + ((x + 1) * x_scale),~
+** Processing line: ~ y2: center_row.y + center_row.h.half + y_scale * next_y,~
+** Processing line: ~ r: r,~
+** Processing line: ~ g: g,~
+** Processing line: ~ b: b~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ args.outputs.static_sprites << points.map_with_index do |y, x|~
+** Processing line: ~ {~
+** Processing line: ~ x: (center_row.x + (x * x_scale)) - 1,~
+** Processing line: ~ y: (center_row.y + center_row.h.half + y_scale * y) - 1,~
+** Processing line: ~ w: 2,~
+** Processing line: ~ h: 2,~
+** Processing line: ~ path: 'sprites/square-black.png'~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ args.state.graphed_at = args.state.tick_count~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def defaults_period_sine_wave_for~
+** Processing line: ~ { frequency: 440, sample_rate: 48000 }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def sine_wave_for opts = { }~
+** Processing line: ~ opts = defaults_period_sine_wave_for.merge opts~
+** Processing line: ~ frequency = opts[:frequency]~
+** Processing line: ~ sample_rate = opts[:sample_rate]~
+** Processing line: ~ period_size = (sample_rate.fdiv frequency).ceil~
+** Processing line: ~ period_size.map_with_index do |i|~
+** Processing line: ~ Math::sin((2.0 * Math::PI) / (sample_rate.to_f / frequency.to_f) * i)~
+** Processing line: ~ end.to_a~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def generate_audio_data sine_wave, sample_rate~
+** Processing line: ~ sample_size = (sample_rate.fdiv (1000.fdiv 60)).ceil~
+** Processing line: ~ copy_count = (sample_size.fdiv sine_wave.length).ceil~
+** Processing line: ~ sine_wave * copy_count~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def defaults_queue_sine_wave~
+** Processing line: ~ { frequency: 440, duration: 60, gain: 1.0, fade_out: false, queue_in: 0 }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def queue_sine_wave args, opts = { }~
+** Processing line: ~ opts = defaults_queue_sine_wave.merge opts~
+** Processing line: ~ decay_rate = 0~
+** Processing line: ~ decay_rate = 1.fdiv(opts[:duration]) * opts[:gain] if opts[:fade_out]~
+** Processing line: ~ frequency = opts[:frequency]~
+** Processing line: ~ sample_rate = 48000~
+** Processing line: ~~
+** Processing line: ~ audio_state = {~
+** Processing line: ~ id: (new_id! args),~
+** Processing line: ~ frequency: frequency,~
+** Processing line: ~ sample_rate: 48000,~
+** Processing line: ~ stop_at: args.tick_count + opts[:queue_in] + opts[:duration],~
+** Processing line: ~ gain: opts[:gain].to_f,~
+** Processing line: ~ queue_at: args.state.tick_count + opts[:queue_in],~
+** Processing line: ~ decay_rate: decay_rate,~
+** Processing line: ~ pitch: 1.0,~
+** Processing line: ~ looping: true,~
+** Processing line: ~ paused: false~
+** Processing line: ~ }~
+** Processing line: ~~
+** Processing line: ~ sine_wave = sine_wave_for frequency: frequency, sample_rate: sample_rate~
+** Processing line: ~ args.state.sine_waves[frequency] ||= sine_wave_for frequency: frequency, sample_rate: sample_rate~
+** Processing line: ~~
+** Processing line: ~ proc = lambda do~
+** Processing line: ~ generate_audio_data args.state.sine_waves[frequency], sample_rate~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ audio_state[:input] = [1, sample_rate, proc]~
+** Processing line: ~ graph_sine_wave args, sine_wave, frequency~
+** Processing line: ~ args.state.audio_queue << audio_state~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def defaults_queue_bell~
+** Processing line: ~ { frequency: 440, duration: 1.seconds, queue_in: 0 }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def queue_bell args, opts = {}~
+** Processing line: ~ (bell_to_sine_waves (defaults_queue_bell.merge opts)).each { |b| queue_sine_wave args, b }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def bell_harmonics~
+** Processing line: ~ [~
+** Processing line: ~ { frequency_ratio: 0.5, duration_ratio: 1.00 },~
+** Processing line: ~ { frequency_ratio: 1.0, duration_ratio: 0.80 },~
+** Processing line: ~ { frequency_ratio: 2.0, duration_ratio: 0.60 },~
+** Processing line: ~ { frequency_ratio: 3.0, duration_ratio: 0.40 },~
+** Processing line: ~ { frequency_ratio: 4.2, duration_ratio: 0.25 },~
+** Processing line: ~ { frequency_ratio: 5.4, duration_ratio: 0.20 },~
+** Processing line: ~ { frequency_ratio: 6.8, duration_ratio: 0.15 }~
+** Processing line: ~ ]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def bell_to_sine_waves opts~
+** Processing line: ~ bell_harmonics.map do |b|~
+** Processing line: ~ {~
+** Processing line: ~ frequency: opts[:frequency] * b[:frequency_ratio],~
+** Processing line: ~ duration: opts[:duration] * b[:duration_ratio],~
+** Processing line: ~ queue_in: opts[:queue_in],~
+** Processing line: ~ gain: (1.fdiv bell_harmonics.length),~
+** Processing line: ~ fade_out: true~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def defaults_frequency_for~
+** Processing line: ~ { note: :a, octave: 5, sharp: false, flat: false }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def frequency_for opts = {}~
+** Processing line: ~ opts = defaults_frequency_for.merge opts~
+** Processing line: ~ octave_offset_multiplier = opts[:octave] - 5~
+** Processing line: ~ note = note_frequencies_octave_5[opts[:note]]~
+** Processing line: ~ if octave_offset_multiplier < 0~
+** Processing line: ~ note = note * 1 / (octave_offset_multiplier.abs + 1)~
+** Processing line: ~ elsif octave_offset_multiplier > 0~
+** Processing line: ~ note = note * (octave_offset_multiplier.abs + 1) / 1~
+** Processing line: ~ end~
+** Processing line: ~ note~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def note_frequencies_octave_5~
+** Processing line: ~ {~
+** Processing line: ~ a: 440.0,~
+** Processing line: ~ a_sharp: 466.16, b_flat: 466.16,~
+** Processing line: ~ b: 493.88,~
+** Processing line: ~ c: 523.25,~
+** Processing line: ~ c_sharp: 554.37, d_flat: 587.33,~
+** Processing line: ~ d: 587.33,~
+** Processing line: ~ d_sharp: 622.25, e_flat: 659.25,~
+** Processing line: ~ e: 659.25,~
+** Processing line: ~ f: 698.25,~
+** Processing line: ~ f_sharp: 739.99, g_flat: 739.99,~
+** Processing line: ~ g: 783.99,~
+** Processing line: ~ g_sharp: 830.61, a_flat: 830.61~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def new_id! args~
+** Processing line: ~ args.state.audio_id ||= 0~
+** Processing line: ~ args.state.audio_id += 1~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def button args, opts~
+** Processing line: ~ button_def = opts.merge rect: (args.layout.rect (opts.merge w: 2, h: 1))~
+** Processing line: ~~
+** Processing line: ~ button_def[:border] = button_def[:rect].merge r: 0, g: 0, b: 0~
+** Processing line: ~~
+** Processing line: ~ font_size_enum = args.layout.font_relative_size_enum 0~
+** Processing line: ~ label_offset_x = 4~
+** Processing line: ~ label_offset_y = button_def[:rect].h.half + button_def[:rect].h.idiv(4)~
+** Processing line: ~~
+** Processing line: ~ button_def[:label] = button_def[:rect].merge text: opts[:text],~
+** Processing line: ~ size_enum: font_size_enum,~
+** Processing line: ~ x: button_def[:rect].x + label_offset_x,~
+** Processing line: ~ y: button_def[:rect].y + label_offset_y~
+** Processing line: ~~
+** Processing line: ~ button_def~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ $gtk.reset~
** Processing line: ~~
** Processing line: ~#+end_src~
- PRE end detected.
@@ -116832,6 +125541,64 @@ Follows is a source code listing for all files that have been open sourced. This
- PRE end detected.
** Processing line: ~~
** Processing line: ~~
+** Processing line: ~* Input Basics - Touch - main.rb~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~Input Basics - Touch - main.rb~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~#+begin_src ruby~
+- PRE start detected.
+** Processing line: ~ # ./samples/02_input_basics/06_touch/app/main.rb~
+** Processing line: ~ def tick args~
+** Processing line: ~ args.outputs.background_color = [ 0, 0, 0 ]~
+** Processing line: ~ args.outputs.primitives << [640, 700, "Touch your screen.", 5, 1, 255, 255, 255].label~
+** Processing line: ~~
+** Processing line: ~ # If you don't want to get fancy, you can just look for finger_one~
+** Processing line: ~ # (and _two, if you like), which are assigned in the order new touches hit~
+** Processing line: ~ # the screen. If not nil, they are touching right now, and are just~
+** Processing line: ~ # references to specific items in the args.input.touch hash.~
+** Processing line: ~ # If finger_one lifts off, it will become nil, but finger_two, if it was~
+** Processing line: ~ # touching, remains until it also lifts off. When all fingers lift off, the~
+** Processing line: ~ # the next new touch will be finger_one again, but until then, new touches~
+** Processing line: ~ # don't fill in earlier slots.~
+** Processing line: ~ if !args.inputs.finger_one.nil?~
+** Processing line: ~ args.outputs.primitives << [640, 650, "Finger #1 is touching at (#{args.inputs.finger_one.x}, #{args.inputs.finger_one.y}).", 5, 1, 255, 255, 255].label~
+** Processing line: ~ end~
+** Processing line: ~ if !args.inputs.finger_two.nil?~
+** Processing line: ~ args.outputs.primitives << [640, 600, "Finger #2 is touching at (#{args.inputs.finger_two.x}, #{args.inputs.finger_two.y}).", 5, 1, 255, 255, 255].label~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ # Here's the more flexible interface: this will report as many simultaneous~
+** Processing line: ~ # touches as the system can handle, but it's a little more effort to track~
+** Processing line: ~ # them. Each item in the args.input.touch hash has a unique key (an~
+** Processing line: ~ # incrementing integer) that exists until the finger lifts off. You can~
+** Processing line: ~ # tell which order the touches happened globally by the key value, or~
+** Processing line: ~ # by the touch[id].touch_order field, which resets to zero each time all~
+** Processing line: ~ # touches have lifted.~
+** Processing line: ~~
+** Processing line: ~ args.state.colors ||= [~
+** Processing line: ~ 0xFF0000, 0x00FF00, 0x1010FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF~
+** Processing line: ~ ]~
+** Processing line: ~~
+** Processing line: ~ size = 100~
+** Processing line: ~ args.inputs.touch.each { |k,v|~
+** Processing line: ~ color = args.state.colors[v.touch_order % 7]~
+** Processing line: ~ r = (color & 0xFF0000) >> 16~
+** Processing line: ~ g = (color & 0x00FF00) >> 8~
+** Processing line: ~ b = (color & 0x0000FF)~
+** Processing line: ~ args.outputs.primitives << [v.x - (size / 2), v.y + (size / 2), size, size, r, g, b, 255].solid~
+** Processing line: ~ args.outputs.primitives << [v.x, v.y + size, k.to_s, 0, 1, 0, 0, 0].label~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~~
+** Processing line: ~#+end_src~
+- PRE end detected.
+** Processing line: ~~
+** Processing line: ~~
** Processing line: ~* Rendering Sprites - Animation Using Separate Pngs - main.rb~
- H1 detected.
- Determining if line is a header.
@@ -121579,6 +130346,63 @@ Follows is a source code listing for all files that have been open sourced. This
- PRE end detected.
** Processing line: ~~
** Processing line: ~~
+** Processing line: ~* Advanced Rendering - Pixel Arrays - main.rb~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~Advanced Rendering - Pixel Arrays - main.rb~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~#+begin_src ruby~
+- PRE start detected.
+** Processing line: ~ # ./samples/07_advanced_rendering/06_pixel_arrays/app/main.rb~
+** Processing line: ~ $gtk.reset~
+** Processing line: ~~
+** Processing line: ~ def tick args~
+** Processing line: ~ args.state.posinc ||= 1~
+** Processing line: ~ args.state.pos ||= 0~
+** Processing line: ~ args.state.rotation ||= 0~
+** Processing line: ~~
+** Processing line: ~ dimension = 10 # keep it small and let the GPU scale it when rendering the sprite.~
+** Processing line: ~~
+** Processing line: ~ # Set up our "scanner" pixel array and fill it with black pixels.~
+** Processing line: ~ args.pixel_array(:scanner).width = dimension~
+** Processing line: ~ args.pixel_array(:scanner).height = dimension~
+** Processing line: ~ args.pixel_array(:scanner).pixels.fill(0xFF000000, 0, dimension * dimension) # black, full alpha~
+** Processing line: ~~
+** Processing line: ~ # Draw a green line that bounces up and down the sprite.~
+** Processing line: ~ args.pixel_array(:scanner).pixels.fill(0xFF00FF00, dimension * args.state.pos, dimension) # green, full alpha~
+** Processing line: ~~
+** Processing line: ~ # Adjust position for next frame.~
+** Processing line: ~ args.state.pos += args.state.posinc~
+** Processing line: ~ if args.state.posinc > 0 && args.state.pos >= dimension~
+** Processing line: ~ args.state.posinc = -1~
+** Processing line: ~ args.state.pos = dimension - 1~
+** Processing line: ~ elsif args.state.posinc < 0 && args.state.pos < 0~
+** Processing line: ~ args.state.posinc = 1~
+** Processing line: ~ args.state.pos = 1~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ # New/changed pixel arrays get uploaded to the GPU before we render~
+** Processing line: ~ # anything. At that point, they can be scaled, rotated, and otherwise~
+** Processing line: ~ # used like any other sprite.~
+** Processing line: ~ w = 100~
+** Processing line: ~ h = 100~
+** Processing line: ~ x = (1280 - w) / 2~
+** Processing line: ~ y = (720 - h) / 2~
+** Processing line: ~ args.outputs.background_color = [64, 0, 128]~
+** Processing line: ~ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite~
+** Processing line: ~ args.state.rotation += 1~
+** Processing line: ~~
+** Processing line: ~ args.outputs.primitives << args.gtk.current_framerate_primitives~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~~
+** Processing line: ~#+end_src~
+- PRE end detected.
+** Processing line: ~~
+** Processing line: ~~
** Processing line: ~* Tweening Lerping Easing Functions - Easing Functions - main.rb~
- H1 detected.
- Determining if line is a header.
@@ -123401,6 +132225,44 @@ Follows is a source code listing for all files that have been open sourced. This
- PRE end detected.
** Processing line: ~~
** Processing line: ~~
+** Processing line: ~* 12 C Extensions - Native Pixel Arrays - main.rb~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~12 C Extensions - Native Pixel Arrays - main.rb~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~#+begin_src ruby~
+- PRE start detected.
+** Processing line: ~ # ./samples/12_c_extensions/03_native_pixel_arrays/app/main.rb~
+** Processing line: ~ $gtk.ffi_misc.gtk_dlopen("ext")~
+** Processing line: ~ include FFI::CExt~
+** Processing line: ~~
+** Processing line: ~ def tick args~
+** Processing line: ~ args.state.rotation ||= 0~
+** Processing line: ~~
+** Processing line: ~ update_scanner_texture # this calls into a C extension!~
+** Processing line: ~~
+** Processing line: ~ # New/changed pixel arrays get uploaded to the GPU before we render~
+** Processing line: ~ # anything. At that point, they can be scaled, rotated, and otherwise~
+** Processing line: ~ # used like any other sprite.~
+** Processing line: ~ w = 100~
+** Processing line: ~ h = 100~
+** Processing line: ~ x = (1280 - w) / 2~
+** Processing line: ~ y = (720 - h) / 2~
+** Processing line: ~ args.outputs.background_color = [64, 0, 128]~
+** Processing line: ~ args.outputs.primitives << [x, y, w, h, :scanner, args.state.rotation].sprite~
+** Processing line: ~ args.state.rotation += 1~
+** Processing line: ~~
+** Processing line: ~ args.outputs.primitives << args.gtk.current_framerate_primitives~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~~
+** Processing line: ~#+end_src~
+- PRE end detected.
+** Processing line: ~~
+** Processing line: ~~
** Processing line: ~* 3d - 3d Cube - main.rb~
- H1 detected.
- Determining if line is a header.
@@ -129250,39 +138112,6 @@ Follows is a source code listing for all files that have been open sourced. This
- PRE end detected.
** Processing line: ~~
** Processing line: ~~
-** Processing line: ~* Platformer - Gorillas Basic - repl.rb~
-- H1 detected.
-- Determining if line is a header.
-- Line contains ~* ~... gsub-ing empty string
-- Formatting line: ~Platformer - Gorillas Basic - repl.rb~
-- Line's tilde count is: 0
-- Line contains link marker: false
-** Processing line: ~~
-** Processing line: ~#+begin_src ruby~
-- PRE start detected.
-** Processing line: ~ # ./samples/99_genre_platformer/gorillas_basic/app/repl.rb~
-** Processing line: ~ begin~
-** Processing line: ~ if $gtk.args.state.current_turn == :player_1_angle~
-** Processing line: ~ $gtk.args.state.player_1_angle = "#{60 + 10.randomize(:ratio).to_i}"~
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-** Processing line: ~ $gtk.args.state.player_1_velocity = "#{30 + 20.randomize(:ratio).to_i}"~
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-** Processing line: ~ elsif $gtk.args.state.current_turn == :player_2_angle~
-** Processing line: ~ $gtk.args.state.player_2_angle = "#{60 + 10.randomize(:ratio).to_i}"~
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-** Processing line: ~ $gtk.args.state.player_2_velocity = "#{30 + 20.randomize(:ratio).to_i}"~
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-** Processing line: ~ else~
-** Processing line: ~ $you_so_basic_gorillas.input_execute_turn~
-** Processing line: ~ end~
-** Processing line: ~ rescue Exception => e~
-** Processing line: ~ puts e~
-** Processing line: ~ end~
-** Processing line: ~~
-** Processing line: ~#+end_src~
-- PRE end detected.
-** Processing line: ~~
-** Processing line: ~~
** Processing line: ~* Platformer - Gorillas Basic - tests.rb~
- H1 detected.
- Determining if line is a header.
@@ -132780,23 +141609,6 @@ Follows is a source code listing for all files that have been open sourced. This
- PRE end detected.
** Processing line: ~~
** Processing line: ~~
-** Processing line: ~* Rpg Narrative - Return Of Serenity - repl.rb~
-- H1 detected.
-- Determining if line is a header.
-- Line contains ~* ~... gsub-ing empty string
-- Formatting line: ~Rpg Narrative - Return Of Serenity - repl.rb~
-- Line's tilde count is: 0
-- Line contains link marker: false
-** Processing line: ~~
-** Processing line: ~#+begin_src ruby~
-- PRE start detected.
-** Processing line: ~ # ./samples/99_genre_rpg_narrative/return_of_serenity/app/repl.rb~
-** Processing line: ~ puts $gtk.args.state.current_scene~
-** Processing line: ~~
-** Processing line: ~#+end_src~
-- PRE end detected.
-** Processing line: ~~
-** Processing line: ~~
** Processing line: ~* Rpg Narrative - Return Of Serenity - require.rb~
- H1 detected.
- Determining if line is a header.
@@ -135827,6 +144639,8 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~~
** Processing line: ~ attr_accessor :wizards~
** Processing line: ~~
+** Processing line: ~ attr_accessor :layout~
+** Processing line: ~~
** Processing line: ~ def initialize runtime, recording~
** Processing line: ~ @inputs = Inputs.new~
** Processing line: ~ @outputs = Outputs.new args: self~
@@ -135838,9 +144652,11 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ @recording = recording~
** Processing line: ~ @grid = Grid.new runtime~
** Processing line: ~ @render_targets = {}~
+** Processing line: ~ @pixel_arrays = {}~
** Processing line: ~ @all_tests = []~
** Processing line: ~ @geometry = GTK::Geometry~
** Processing line: ~ @wizards = Wizards.new~
+** Processing line: ~ @layout = GTK::Layout.new @grid.w, @grid.h~
** Processing line: ~ end~
** Processing line: ~~
** Processing line: ~~
@@ -135869,6 +144685,26 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ [grid, inputs, state, outputs, runtime, passes]~
** Processing line: ~ end~
** Processing line: ~~
+** Processing line: ~ def clear_pixel_arrays~
+** Processing line: ~ pixel_arrays_clear~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def pixel_arrays_clear~
+** Processing line: ~ @pixel_arrays = {}~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def pixel_arrays~
+** Processing line: ~ @pixel_arrays~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def pixel_array name~
+** Processing line: ~ name = name.to_s~
+** Processing line: ~ if !@pixel_arrays[name]~
+** Processing line: ~ @pixel_arrays[name] = PixelArray.new~
+** Processing line: ~ end~
+** Processing line: ~ @pixel_arrays[name]~
+** Processing line: ~ end~
+** Processing line: ~~
** Processing line: ~ def clear_render_targets~
** Processing line: ~ render_targets_clear~
** Processing line: ~ end~
@@ -136168,6 +145004,10 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ args.passes~
** Processing line: ~ end~
** Processing line: ~~
+** Processing line: ~ def pixel_arrays~
+** Processing line: ~ args.pixel_arrays~
+** Processing line: ~ end~
+** Processing line: ~~
** Processing line: ~ def geometry~
** Processing line: ~ args.geometry~
** Processing line: ~ end~
@@ -136269,6 +145109,8 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~~
** Processing line: ~ module GTK~
** Processing line: ~ class Console~
+** Processing line: ~ include ConsoleDeprecated~
+** Processing line: ~~
** Processing line: ~ attr_accessor :show_reason, :log, :logo, :background_color,~
** Processing line: ~ :text_color, :animation_duration,~
** Processing line: ~ :max_log_lines, :max_history, :log,~
@@ -136339,7 +145181,7 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ @disabled = false~
** Processing line: ~ end~
** Processing line: ~~
-** Processing line: ~ def addsprite obj~
+** Processing line: ~ def add_sprite obj~
** Processing line: ~ @log_invocation_count += 1~
** Processing line: ~ obj[:id] ||= "id_#{obj[:path]}_#{Time.now.to_i}".to_sym~
** Processing line: ~~
@@ -136359,14 +145201,14 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~~
** Processing line: ~ def add_primitive obj~
** Processing line: ~ if obj.is_a? Hash~
-** Processing line: ~ addsprite obj~
+** Processing line: ~ add_sprite obj~
** Processing line: ~ else~
-** Processing line: ~ addtext obj~
+** Processing line: ~ add_text obj~
** Processing line: ~ end~
** Processing line: ~ nil~
** Processing line: ~ end~
** Processing line: ~~
-** Processing line: ~ def addtext obj~
+** Processing line: ~ def add_text obj~
** Processing line: ~ @last_log_lines_count ||= 1~
** Processing line: ~ @log_invocation_count += 1~
** Processing line: ~~
@@ -136490,12 +145332,12 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ @toasted_at = Kernel.global_tick_count~
** Processing line: ~ log_once_info :perma_toast_tip, "Use console.perma_toast to show the toast for longer."~
** Processing line: ~ dwim_duration = 5.seconds~
-** Processing line: ~ addtext "* toast :#{id}"~
+** Processing line: ~ add_text "* toast :#{id}"~
** Processing line: ~ puts "* TOAST: :#{id}"~
** Processing line: ~ messages.each do |message|~
** Processing line: ~ lines = message.to_s.wrapped_lines(self.console_text_width)~
** Processing line: ~ dwim_duration += lines.length.seconds~
-** Processing line: ~ addtext "** #{message}"~
+** Processing line: ~ add_text "** #{message}"~
** Processing line: ~ puts "** #{message}"~
** Processing line: ~ end~
** Processing line: ~ show :toast~
@@ -136713,6 +145555,10 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ @command_history_index -= 1~
** Processing line: ~ self.current_input_str = @command_history[@command_history_index].dup~
** Processing line: ~ end~
+** Processing line: ~ elsif args.inputs.keyboard.key_down.left~
+** Processing line: ~ prompt.move_cursor_left~
+** Processing line: ~ elsif args.inputs.keyboard.key_down.right~
+** Processing line: ~ prompt.move_cursor_right~
** Processing line: ~ elsif inputs_scroll_up_full? args~
** Processing line: ~ scroll_up_full~
** Processing line: ~ elsif inputs_scroll_down_full? args~
@@ -137320,23 +146166,53 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ @cursor_color = Color.new [187, 21, 6]~
** Processing line: ~ @console_text_width = console_text_width~
** Processing line: ~~
+** Processing line: ~ @cursor_position = 0~
+** Processing line: ~ update_cursor_position_px~
+** Processing line: ~~
** Processing line: ~ @last_autocomplete_prefix = nil~
** Processing line: ~ @next_candidate_index = 0~
** Processing line: ~ end~
** Processing line: ~~
+** Processing line: ~ def update_cursor_position_px~
+** Processing line: ~ @cursor_position_px = ($gtk.calcstringbox (@prompt + @current_input_str[0...@cursor_position]), @font_style.size_enum, @font_style.font).x~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def current_input_str=(str)~
+** Processing line: ~ @current_input_str = str~
+** Processing line: ~ @cursor_position = str.length~
+** Processing line: ~ end~
+** Processing line: ~~
** Processing line: ~ def <<(str)~
-** Processing line: ~ @current_input_str << str~
+** Processing line: ~ @current_input_str = @current_input_str[0...@cursor_position] + str + @current_input_str[@cursor_position..-1]~
+** Processing line: ~ @cursor_position += str.length~
+** Processing line: ~ update_cursor_position_px~
** Processing line: ~ @current_input_changed_at = Kernel.global_tick_count~
** Processing line: ~ reset_autocomplete~
** Processing line: ~ end~
** Processing line: ~~
** Processing line: ~ def backspace~
-** Processing line: ~ @current_input_str.chop!~
+** Processing line: ~ return if current_input_str.length.zero? || @cursor_position.zero?~
+** Processing line: ~~
+** Processing line: ~ @current_input_str = @current_input_str[0...(@cursor_position - 1)] + @current_input_str[@cursor_position..-1]~
+** Processing line: ~ @cursor_position -= 1~
+** Processing line: ~ update_cursor_position_px~
** Processing line: ~ reset_autocomplete~
** Processing line: ~ end~
** Processing line: ~~
+** Processing line: ~ def move_cursor_left~
+** Processing line: ~ @cursor_position -= 1 if @cursor_position > 0~
+** Processing line: ~ update_cursor_position_px~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def move_cursor_right~
+** Processing line: ~ @cursor_position += 1 if @cursor_position < current_input_str.length~
+** Processing line: ~ update_cursor_position_px~
+** Processing line: ~ end~
+** Processing line: ~~
** Processing line: ~ def clear~
** Processing line: ~ @current_input_str = ''~
+** Processing line: ~ @cursor_position = 0~
+** Processing line: ~ update_cursor_position_px~
** Processing line: ~ reset_autocomplete~
** Processing line: ~ end~
** Processing line: ~~
@@ -137355,7 +146231,10 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ @next_candidate_index += 1~
** Processing line: ~ @next_candidate_index = 0 if @next_candidate_index >= candidates.length~
** Processing line: ~ self.current_input_str = display_autocomplete_candidate(candidate)~
+** Processing line: ~ update_cursor_position_px~
** Processing line: ~ end~
+** Processing line: ~ rescue Exception => e~
+** Processing line: ~ puts "* BUG: Tab autocompletion failed. Let us know about this.\n#{e}"~
** Processing line: ~ end~
** Processing line: ~~
** Processing line: ~ def pretty_print_strings_as_table items~
@@ -137414,7 +146293,21 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~~
** Processing line: ~ def render(args, x:, y:)~
** Processing line: ~ args.outputs.reserved << font_style.label(x: x, y: y, text: "#{@prompt}#{current_input_str}", color: @text_color)~
-** Processing line: ~ args.outputs.reserved << font_style.label(x: x - 2, y: y + 3, text: (" " * (@prompt.length + current_input_str.length)) + "|", color: @cursor_color)~
+** Processing line: ~ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 0.5,~
+** Processing line: ~ y: y + 5,~
+** Processing line: ~ x2: x + @cursor_position_px + 0.5,~
+** Processing line: ~ y2: y + @font_style.letter_size.y + 5)~
+** Processing line: ~~
+** Processing line: ~ args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 1,~
+** Processing line: ~ y: y + 5,~
+** Processing line: ~ x2: x + @cursor_position_px + 1,~
+** Processing line: ~ y2: y + @font_style.letter_size.y + 5)~
+** Processing line: ~~
+** Processing line: ~ # debugging rectangle for string~
+** Processing line: ~ # args.outputs.reserved << (@cursor_color.to_h.merge x: x,~
+** Processing line: ~ # y: y + 5,~
+** Processing line: ~ # w: @cursor_position_px,~
+** Processing line: ~ # h: @font_style.letter_size.y).border~
** Processing line: ~ end~
** Processing line: ~~
** Processing line: ~ def tick~
@@ -139457,6 +148350,59 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~~
** Processing line: ~ alias_method :inspect, :to_s~
** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ # Provides access to multitouch input~
+** Processing line: ~ #~
+** Processing line: ~ # @gtk~
+** Processing line: ~ class FingerTouch~
+** Processing line: ~~
+** Processing line: ~ # @gtk~
+** Processing line: ~ attr_accessor :moved,~
+** Processing line: ~ :moved_at,~
+** Processing line: ~ :global_moved_at,~
+** Processing line: ~ :touch_order,~
+** Processing line: ~ :x, :y~
+** Processing line: ~~
+** Processing line: ~ def initialize~
+** Processing line: ~ @moved = false~
+** Processing line: ~ @moved_at = 0~
+** Processing line: ~ @global_moved_at = 0~
+** Processing line: ~ @touch_order = 0~
+** Processing line: ~ @x = 0~
+** Processing line: ~ @y = 0~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def point~
+** Processing line: ~ [@x, @y].point~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def inside_rect? rect~
+** Processing line: ~ point.inside_rect? rect~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def inside_circle? center, radius~
+** Processing line: ~ point.point_inside_circle? center, radius~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ alias_method :position, :point~
+** Processing line: ~~
+** Processing line: ~ def serialize~
+** Processing line: ~ result = {}~
+** Processing line: ~ result[:x] = @x~
+** Processing line: ~ result[:y] = @y~
+** Processing line: ~ result[:touch_order] = @touch_order~
+** Processing line: ~ result[:moved] = @moved~
+** Processing line: ~ result[:moved_at] = @moved_at~
+** Processing line: ~~
+** Processing line: ~ result~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def to_s~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ alias_method :inspect, :to_s~
+** Processing line: ~ end~
** Processing line: ~ end~
** Processing line: ~~
** Processing line: ~ module GTK~
@@ -139477,6 +148423,11 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ # @gtk~
** Processing line: ~ attr_reader :mouse~
** Processing line: ~~
+** Processing line: ~ # @return {FingerTouch}~
+** Processing line: ~ # @gtk~
+** Processing line: ~ attr_reader :touch~
+** Processing line: ~ attr_accessor :finger_one, :finger_two~
+** Processing line: ~~
** Processing line: ~ # @gtk~
** Processing line: ~ attr_accessor :text, :history~
** Processing line: ~~
@@ -139484,6 +148435,9 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ @controllers = [Controller.new, Controller.new]~
** Processing line: ~ @keyboard = Keyboard.new~
** Processing line: ~ @mouse = Mouse.new~
+** Processing line: ~ @touch = {}~
+** Processing line: ~ @finger_one = nil~
+** Processing line: ~ @finger_two = nil~
** Processing line: ~ @text = []~
** Processing line: ~ end~
** Processing line: ~~
@@ -139559,6 +148513,9 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ @mouse.clear~
** Processing line: ~ @keyboard.clear~
** Processing line: ~ @controllers.each(&:clear)~
+** Processing line: ~ @touch.clear~
+** Processing line: ~ @finger_one = nil~
+** Processing line: ~ @finger_two = nil~
** Processing line: ~ end~
** Processing line: ~~
** Processing line: ~ # @return [Hash]~
@@ -139578,6 +148535,1418 @@ Follows is a source code listing for all files that have been open sourced. This
- PRE end detected.
** Processing line: ~~
** Processing line: ~~
+** Processing line: ~* ios_wizard.rb~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~ios_wizard.rb~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~#+begin_src ruby~
+- PRE start detected.
+** Processing line: ~ # ./dragon/ios_wizard.rb~
+** Processing line: ~ # Copyright 2019 DragonRuby LLC~
+** Processing line: ~ # MIT License~
+** Processing line: ~ # ios_wizard.rb has been released under MIT (*only this file*).~
+** Processing line: ~~
+** Processing line: ~ class WizardException < Exception~
+** Processing line: ~ attr_accessor :console_primitives~
+** Processing line: ~~
+** Processing line: ~ def initialize *console_primitives~
+** Processing line: ~ @console_primitives = console_primitives~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ class IOSWizard~
+** Processing line: ~ def initialize~
+** Processing line: ~ @doctor_executed_at = 0~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def relative_path~
+** Processing line: ~ (File.dirname $gtk.binary_path)~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def steps~
+** Processing line: ~ [~
+** Processing line: ~ :check_for_xcode,~
+** Processing line: ~ :check_for_brew,~
+** Processing line: ~ :check_for_certs,~
+** Processing line: ~ :check_for_device,~
+** Processing line: ~ :check_for_dev_profile,~
+** Processing line: ~ :determine_app_name,~
+** Processing line: ~ :determine_app_id,~
+** Processing line: ~ :blow_away_temp,~
+** Processing line: ~ :stage_app,~
+** Processing line: ~ :write_info_plist,~
+** Processing line: ~ :write_entitlements_plist,~
+** Processing line: ~ :code_sign,~
+** Processing line: ~ :create_ipa,~
+** Processing line: ~ :deploy,~
+** Processing line: ~ ]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def get_reserved_sprite png~
+** Processing line: ~ sprite_path = ".dragonruby/sprites/wizards/ios/#{png}"~
+** Processing line: ~~
+** Processing line: ~ if !$gtk.ivar :rcb_release_mode~
+** Processing line: ~ sprite_path = "deploy_template/#{sprite_path}"~
+** Processing line: ~ $gtk.reset_sprite sprite_path~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if !$gtk.read_file sprite_path~
+** Processing line: ~ log_error "png #{png} not found."~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ sprite_path~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def start~
+** Processing line: ~ @certificate_name = nil~
+** Processing line: ~ init_wizard_status~
+** Processing line: ~ log_info "Starting iOS Wizard so we can deploy to your device."~
+** Processing line: ~ @start_at = Kernel.global_tick_count~
+** Processing line: ~ steps.each do |m|~
+** Processing line: ~ begin~
+** Processing line: ~ result = (send m) || :success if @wizard_status[m][:result] != :success~
+** Processing line: ~ @wizard_status[m][:result] = result~
+** Processing line: ~ rescue Exception => e~
+** Processing line: ~ if e.is_a? WizardException~
+** Processing line: ~ $console.log.clear~
+** Processing line: ~ $console.archived_log.clear~
+** Processing line: ~ log "=" * $console.console_text_width~
+** Processing line: ~ e.console_primitives.each do |p|~
+** Processing line: ~ $console.add_primitive p~
+** Processing line: ~ end~
+** Processing line: ~ log "=" * $console.console_text_width~
+** Processing line: ~ else~
+** Processing line: ~ log_error "Step #{m} failed."~
+** Processing line: ~ log_error e.to_s~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ $console.set_command "$wizards.ios.start"~
+** Processing line: ~~
+** Processing line: ~ break~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ return nil~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def always_fail~
+** Processing line: ~ return false if $gtk.ivar :rcb_release_mode~
+** Processing line: ~ return true~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def check_for_xcode~
+** Processing line: ~ if !cli_app_exist?(xcodebuild_cli_app)~
+** Processing line: ~ raise WizardException.new(~
+** Processing line: ~ "* You need Xcode to use $wizards.ios.start.",~
+** Processing line: ~ { w: 75, h: 75, path: get_reserved_sprite("xcode.png") },~
+** Processing line: ~ "** 1. Go to http://developer.apple.com and register.",~
+** Processing line: ~ "** 2. Download Xcode 11.3+ from http://developer.apple.com/downloads.",~
+** Processing line: ~ " NOTE: DO NOT install Xcode from the App Store. Use the link above.",~
+** Processing line: ~ { w: 700, h: 359, path: get_reserved_sprite("xcode-downloads.png") },~
+** Processing line: ~ "** 3. After installing. Open up Xcode to accept the EULA."~
+** Processing line: ~ )~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def check_for_brew~
+** Processing line: ~ if !cli_app_exist?('brew')~
+** Processing line: ~ raise WizardException.new(~
+** Processing line: ~ "* You need to install Brew.",~
+** Processing line: ~ { w: 700, h: 388, path: get_reserved_sprite("brew.png") },~
+** Processing line: ~ "** 1. Go to http://brew.sh.",~
+** Processing line: ~ "** 2. Copy the command that starts with `/bin/bash -c` on the site.",~
+** Processing line: ~ "** 3. Open Terminal and run the command you copied from the website.",~
+** Processing line: ~ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },~
+** Processing line: ~ )~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def init_wizard_status~
+** Processing line: ~ @wizard_status = {}~
+** Processing line: ~ steps.each do |m|~
+** Processing line: ~ @wizard_status[m] = { result: :not_started }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ previous_step = nil~
+** Processing line: ~ next_step = nil~
+** Processing line: ~ steps.each_cons(2) do |current_step, next_step|~
+** Processing line: ~ @wizard_status[current_step][:next_step] = next_step~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ steps.reverse.each_cons(2) do |current_step, previous_step|~
+** Processing line: ~ @wizard_status[current_step][:previous_step] = previous_step~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def restart~
+** Processing line: ~ init_wizard_status~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def check_for_dev_profile~
+** Processing line: ~ if !($gtk.read_file 'profiles/development.mobileprovision')~
+** Processing line: ~ $gtk.system "mkdir -p #{relative_path}/profiles"~
+** Processing line: ~ $gtk.system "open #{relative_path}/profiles"~
+** Processing line: ~ $gtk.system "echo Download the mobile provisioning profile and place it here with the name development.mobileprovision > #{relative_path}/profiles/README.txt"~
+** Processing line: ~ raise WizardException.new(~
+** Processing line: ~ "* I didn't find a mobile provision.",~
+** Processing line: ~ "** 1. Go to http://developer.apple.com and click \"Certificates, IDs & Profiles\".",~
+** Processing line: ~ "** 2. Add an App Identifier.",~
+** Processing line: ~ "** 3. Select the App IDs option from the list.",~
+** Processing line: ~ { w: 700, h: 75, path: get_reserved_sprite("identifiers.png") },~
+** Processing line: ~ "** 4. Add your Device next. You can use idevice_id -l to get the UUID of your device.",~
+** Processing line: ~ { w: 365, h: 69, path: get_reserved_sprite("device-link.png") },~
+** Processing line: ~ "** 5. Create a Profile. Associate your certs, id, and device.",~
+** Processing line: ~ { w: 300, h: 122, path: get_reserved_sprite("profiles.png") },~
+** Processing line: ~ "** 6. Download the mobile provision and save it to 'profiles/development.mobileprovision'.",~
+** Processing line: ~ { w: 200, h: 124, path: get_reserved_sprite("profiles-folder.png") },~
+** Processing line: ~ )~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def determine_app_name~
+** Processing line: ~ @app_name = dev_profile_xml[:children].first[:children].first[:children][1][:children].first[:data]~
+** Processing line: ~ log_info "App name is: #{@app_name}."~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def dev_profile_xml~
+** Processing line: ~ xml = $gtk.read_file 'profiles/development.mobileprovision'~
+** Processing line: ~ scrubbed = xml.each_line.map do |l|~
+** Processing line: ~ if l.strip.start_with? "<"~
+** Processing line: ~ if l.start_with? '</plist>'~
+** Processing line: ~ '</plist>'~
+** Processing line: ~ elsif l.include? "Apple Inc."~
+** Processing line: ~ nil~
+** Processing line: ~ elsif l.include? '<data>'~
+** Processing line: ~ nil~
+** Processing line: ~ else~
+** Processing line: ~ l~
+** Processing line: ~ end~
+** Processing line: ~ else~
+** Processing line: ~ nil~
+** Processing line: ~ end~
+** Processing line: ~ end.reject { |l| !l }.join~
+** Processing line: ~ $gtk.parse_xml scrubbed~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def determine_app_id~
+** Processing line: ~ # lol~
+** Processing line: ~ @app_id = dev_profile_xml[:children].first[:children].first[:children][13][:children][1][:children].first[:data]~
+** Processing line: ~ log_info "App Identifier is set to : #{@app_id}"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def set_app_name name~
+** Processing line: ~ @app_name = name~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def set_dev_profile path~
+** Processing line: ~ if !$gtk.read_file path~
+** Processing line: ~ log_error "I couldn't find a development profile at #{path}."~
+** Processing line: ~ ask_for_dev_profile~
+** Processing line: ~ else~
+** Processing line: ~ @dev_profile_path = path~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def blow_away_temp~
+** Processing line: ~ sh "rm -rf #{tmp_directory}"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def stage_app~
+** Processing line: ~ log_info "Staging."~
+** Processing line: ~ sh "mkdir -p #{tmp_directory}"~
+** Processing line: ~ sh "cp -R #{relative_path}/dragonruby-ios.app \"#{tmp_directory}/#{@app_name}.app\""~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def set_app_id id~
+** Processing line: ~ log_info = "App Id set to: #{id}"~
+** Processing line: ~ @app_id = id~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def check_for_device~
+** Processing line: ~ log_info "Looking for device."~
+** Processing line: ~~
+** Processing line: ~ if !cli_app_exist?(idevice_id_cli_app)~
+** Processing line: ~ raise WizardException.new(~
+** Processing line: ~ "* It doesn't look like you have the libimobiledevice iOS protocol library installed.",~
+** Processing line: ~ "** 1. Open Terminal.",~
+** Processing line: ~ { w: 700, h: 99, path: get_reserved_sprite("terminal.png") },~
+** Processing line: ~ "** 2. Run: `brew install libimobiledevice`.",~
+** Processing line: ~ { w: 500, h: 93, path: get_reserved_sprite("brew-install-libimobiledevice.png") },~
+** Processing line: ~ )~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if connected_devices.length == 0~
+** Processing line: ~ raise WizardException.new("* I couldn't find any connected devices. Connect your iOS device to your Mac and try again.")~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ @device_id = connected_devices.first~
+** Processing line: ~ log_info "I will be using device with UUID #{@device_id}"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def check_for_certs~
+** Processing line: ~ log_info "Attempting to find certificates on your computer."~
+** Processing line: ~~
+** Processing line: ~ if !cli_app_exist?(security_cli_app)~
+** Processing line: ~ raise WizardException.new(~
+** Processing line: ~ "* It doesn't look like you have #{security_cli_app}.",~
+** Processing line: ~ "** 1. Open Disk Utility and run First Aid.",~
+** Processing line: ~ { w: 700, h: 148, path: get_reserved_sprite("disk-utility.png") },~
+** Processing line: ~ )~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if valid_certs.length == 0~
+** Processing line: ~ raise WizardException.new(~
+** Processing line: ~ "* It doesn't look like you have any valid certs installed.",~
+** Processing line: ~ "** 1. Open Xcode.",~
+** Processing line: ~ "** 2. Log into your developer account. Xcode -> Preferences -> Accounts.",~
+** Processing line: ~ { w: 700, h: 98, path: get_reserved_sprite("login-xcode.png") },~
+** Processing line: ~ "** 3. After loggin in, select Manage Certificates...",~
+** Processing line: ~ { w: 700, h: 115, path: get_reserved_sprite("manage-certificates.png") },~
+** Processing line: ~ "** 4. Add a certificate for Apple Development.",~
+** Processing line: ~ { w: 700, h: 217, path: get_reserved_sprite("add-cert.png") },~
+** Processing line: ~ )~
+** Processing line: ~ raise "You do not have any Apple development certs on this computer."~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ @certificate_name = valid_certs.first[:name]~
+** Processing line: ~ log_info "I will be using '#{@certificate_name}' to deploy to your device."~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def idevice_id_cli_app~
+** Processing line: ~ "idevice_id"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def security_cli_app~
+** Processing line: ~ "/usr/bin/security"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def xcodebuild_cli_app~
+** Processing line: ~ "xcodebuild"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def valid_certs~
+** Processing line: ~ certs = sh("#{security_cli_app} -q find-identity -p codesigning -v").each_line.map do |l|~
+** Processing line: ~ if l.include?(")") && !l.include?("Developer ID") && l.include?("Development")~
+** Processing line: ~ l.strip~
+** Processing line: ~ else~
+** Processing line: ~ nil~
+** Processing line: ~ end~
+** Processing line: ~ end.reject_nil.map do |l|~
+** Processing line: ~ number, id, name = l.split(' ', 3)~
+** Processing line: ~ name = name.gsub("\"", "") if name~
+** Processing line: ~ {~
+** Processing line: ~ number: 1,~
+** Processing line: ~ id: id,~
+** Processing line: ~ name: name~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def connected_devices~
+** Processing line: ~ sh("idevice_id -l").strip.each_line.map do |l|~
+** Processing line: ~ l.strip~
+** Processing line: ~ end.reject { |l| l.length == 0 }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def cli_app_exist? app~
+** Processing line: ~ `which #{app}`.strip.length != 0~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def write_entitlements_plist~
+** Processing line: ~ entitlement_plist_string = <<-XML~
+** Processing line: ~ <?xml version="1.0" encoding="UTF-8"?>~
+** Processing line: ~ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">~
+** Processing line: ~ <plist version="1.0">~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>application-identifier</key>~
+** Processing line: ~ <string>:app_id</string>~
+** Processing line: ~ <key>get-task-allow</key>~
+** Processing line: ~ <true/>~
+** Processing line: ~ </dict>~
+** Processing line: ~ </plist>~
+** Processing line: ~ XML~
+** Processing line: ~~
+** Processing line: ~ log_info "Creating Entitlements.plist"~
+** Processing line: ~~
+** Processing line: ~ $gtk.write_file_root "tmp/ios/Entitlements.plist", entitlement_plist_string.gsub(":app_id", @app_id).strip~
+** Processing line: ~~
+** Processing line: ~ sh "/usr/bin/plutil -convert binary1 \"#{tmp_directory}/Entitlements.plist\""~
+** Processing line: ~ sh "/usr/bin/plutil -convert xml1 \"#{tmp_directory}/Entitlements.plist\""~
+** Processing line: ~~
+** Processing line: ~ @entitlement_plist_written = true~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def code_sign~
+** Processing line: ~ sh "cp #{@dev_profile_path} \"#{app_path}/embedded.mobileprovision\""~
+** Processing line: ~~
+** Processing line: ~ log_info "Signing app with #{@certificate_name}."~
+** Processing line: ~~
+** Processing line: ~ sh "/usr/bin/plutil -convert binary1 \"#{app_path}/Info.plist\""~
+** Processing line: ~~
+** Processing line: ~ sh "CODESIGN_ALLOCATE=\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate\" /usr/bin/codesign -f -s \"#{@certificate_name}\" --entitlements #{tmp_directory}/Entitlements.plist \"#{tmp_directory}/#{@app_name}.app\""~
+** Processing line: ~~
+** Processing line: ~ @code_sign_completed = true~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def write_info_plist~
+** Processing line: ~ log_info "Adding Info.plist."~
+** Processing line: ~~
+** Processing line: ~ info_plist_string = <<-XML~
+** Processing line: ~ <?xml version="1.0" encoding="UTF-8"?>~
+** Processing line: ~ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">~
+** Processing line: ~ <plist version="1.0">~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>NSAppTransportSecurity</key>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>NSAllowsArbitraryLoads</key>~
+** Processing line: ~ <true/>~
+** Processing line: ~ <key>NSExceptionDomains</key>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>google.com</key>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>NSExceptionAllowsInsecureHTTPLoads</key>~
+** Processing line: ~ <true/>~
+** Processing line: ~ <key>NSIncludesSubdomains</key>~
+** Processing line: ~ <true/>~
+** Processing line: ~ </dict>~
+** Processing line: ~ </dict>~
+** Processing line: ~ </dict>~
+** Processing line: ~ <key>BuildMachineOSBuild</key>~
+** Processing line: ~ <string>19C57</string>~
+** Processing line: ~ <key>CFBundleDevelopmentRegion</key>~
+** Processing line: ~ <string>en</string>~
+** Processing line: ~ <key>CFBundleDisplayName</key>~
+** Processing line: ~ <string>:app_name</string>~
+** Processing line: ~ <key>CFBundleExecutable</key>~
+** Processing line: ~ <string>Runtime</string>~
+** Processing line: ~ <key>CFBundleIconFiles</key>~
+** Processing line: ~ <array>~
+** Processing line: ~ <string>AppIcon60x60</string>~
+** Processing line: ~ </array>~
+** Processing line: ~ <key>CFBundleIcons</key>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>CFBundlePrimaryIcon</key>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>CFBundleIconFiles</key>~
+** Processing line: ~ <array>~
+** Processing line: ~ <string>AppIcon60x60</string>~
+** Processing line: ~ </array>~
+** Processing line: ~ <key>CFBundleIconName</key>~
+** Processing line: ~ <string>AppIcon</string>~
+** Processing line: ~ </dict>~
+** Processing line: ~ </dict>~
+** Processing line: ~ <key>CFBundleIcons~ipad</key>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>CFBundlePrimaryIcon</key>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>CFBundleIconFiles</key>~
+** Processing line: ~ <array>~
+** Processing line: ~ <string>AppIcon60x60</string>~
+** Processing line: ~ <string>AppIcon76x76</string>~
+** Processing line: ~ </array>~
+** Processing line: ~ <key>CFBundleIconName</key>~
+** Processing line: ~ <string>AppIcon</string>~
+** Processing line: ~ </dict>~
+** Processing line: ~ </dict>~
+** Processing line: ~ <key>CFBundleIdentifier</key>~
+** Processing line: ~ <string>com.carlile.swisscheese</string>~
+** Processing line: ~ <key>CFBundleInfoDictionaryVersion</key>~
+** Processing line: ~ <string>6.0</string>~
+** Processing line: ~ <key>CFBundleName</key>~
+** Processing line: ~ <string>:app_name</string>~
+** Processing line: ~ <key>CFBundlePackageType</key>~
+** Processing line: ~ <string>APPL</string>~
+** Processing line: ~ <key>CFBundleShortVersionString</key>~
+** Processing line: ~ <string>1.0</string>~
+** Processing line: ~ <key>CFBundleSignature</key>~
+** Processing line: ~ <string>????</string>~
+** Processing line: ~ <key>CFBundleSupportedPlatforms</key>~
+** Processing line: ~ <array>~
+** Processing line: ~ <string>iPhoneOS</string>~
+** Processing line: ~ </array>~
+** Processing line: ~ <key>CFBundleVersion</key>~
+** Processing line: ~ <string>1.0</string>~
+** Processing line: ~ <key>DTCompiler</key>~
+** Processing line: ~ <string>com.apple.compilers.llvm.clang.1_0</string>~
+** Processing line: ~ <key>DTPlatformBuild</key>~
+** Processing line: ~ <string>17B102</string>~
+** Processing line: ~ <key>DTPlatformName</key>~
+** Processing line: ~ <string>iphoneos</string>~
+** Processing line: ~ <key>DTPlatformVersion</key>~
+** Processing line: ~ <string>13.2</string>~
+** Processing line: ~ <key>DTSDKBuild</key>~
+** Processing line: ~ <string>17B102</string>~
+** Processing line: ~ <key>DTSDKName</key>~
+** Processing line: ~ <string>iphoneos13.2</string>~
+** Processing line: ~ <key>DTXcode</key>~
+** Processing line: ~ <string>01131</string>~
+** Processing line: ~ <key>DTXcodeBuild</key>~
+** Processing line: ~ <string>11C505</string>~
+** Processing line: ~ <key>ITSAppUsesNonExemptEncryption</key>~
+** Processing line: ~ <false/>~
+** Processing line: ~ <key>MinimumOSVersion</key>~
+** Processing line: ~ <string>11.0</string>~
+** Processing line: ~ <key>UIAppFonts</key>~
+** Processing line: ~ <array/>~
+** Processing line: ~ <key>UIBackgroundModes</key>~
+** Processing line: ~ <array/>~
+** Processing line: ~ <key>UIDeviceFamily</key>~
+** Processing line: ~ <array>~
+** Processing line: ~ <integer>1</integer>~
+** Processing line: ~ <integer>2</integer>~
+** Processing line: ~ </array>~
+** Processing line: ~ <key>UILaunchImages</key>~
+** Processing line: ~ <array>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+** Processing line: ~ <string>11.0</string>~
+** Processing line: ~ <key>UILaunchImageName</key>~
+** Processing line: ~ <string>LaunchImage-1100-Portrait-2436h</string>~
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+** Processing line: ~ <string>Portrait</string>~
+** Processing line: ~ <key>UILaunchImageSize</key>~
+** Processing line: ~ <string>{375, 812}</string>~
+** Processing line: ~ </dict>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+** Processing line: ~ <string>8.0</string>~
+** Processing line: ~ <key>UILaunchImageName</key>~
+** Processing line: ~ <string>LaunchImage-800-Portrait-736h</string>~
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+** Processing line: ~ <string>Portrait</string>~
+** Processing line: ~ <key>UILaunchImageSize</key>~
+** Processing line: ~ <string>{414, 736}</string>~
+** Processing line: ~ </dict>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+** Processing line: ~ <string>8.0</string>~
+** Processing line: ~ <key>UILaunchImageName</key>~
+** Processing line: ~ <string>LaunchImage-800-667h</string>~
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+** Processing line: ~ <string>Portrait</string>~
+** Processing line: ~ <key>UILaunchImageSize</key>~
+** Processing line: ~ <string>{375, 667}</string>~
+** Processing line: ~ </dict>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+** Processing line: ~ <string>7.0</string>~
+** Processing line: ~ <key>UILaunchImageName</key>~
+** Processing line: ~ <string>LaunchImage-700</string>~
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+** Processing line: ~ <string>Portrait</string>~
+** Processing line: ~ <key>UILaunchImageSize</key>~
+** Processing line: ~ <string>{320, 480}</string>~
+** Processing line: ~ </dict>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+** Processing line: ~ <string>7.0</string>~
+** Processing line: ~ <key>UILaunchImageName</key>~
+** Processing line: ~ <string>LaunchImage-700-568h</string>~
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+** Processing line: ~ <string>Portrait</string>~
+** Processing line: ~ <key>UILaunchImageSize</key>~
+** Processing line: ~ <string>{320, 568}</string>~
+** Processing line: ~ </dict>~
+** Processing line: ~ <dict>~
+** Processing line: ~ <key>UILaunchImageMinimumOSVersion</key>~
+** Processing line: ~ <string>7.0</string>~
+** Processing line: ~ <key>UILaunchImageName</key>~
+** Processing line: ~ <string>LaunchImage-700-Portrait</string>~
+** Processing line: ~ <key>UILaunchImageOrientation</key>~
+** Processing line: ~ <string>Portrait</string>~
+** Processing line: ~ <key>UILaunchImageSize</key>~
+** Processing line: ~ <string>{768, 1024}</string>~
+** Processing line: ~ </dict>~
+** Processing line: ~ </array>~
+** Processing line: ~ <key>UIRequiredDeviceCapabilities</key>~
+** Processing line: ~ <array>~
+** Processing line: ~ <string>arm64</string>~
+** Processing line: ~ </array>~
+** Processing line: ~ <key>UIRequiresFullScreen</key>~
+** Processing line: ~ <true/>~
+** Processing line: ~ <key>UIStatusBarStyle</key>~
+** Processing line: ~ <string>UIStatusBarStyleDefault</string>~
+** Processing line: ~ <key>UISupportedInterfaceOrientations</key>~
+** Processing line: ~ <array>~
+** Processing line: ~ <string>#{device_orientation_xml}</string>~
+** Processing line: ~ </array>~
+** Processing line: ~ </dict>~
+** Processing line: ~ </plist>~
+** Processing line: ~ XML~
+** Processing line: ~~
+** Processing line: ~ # <string>UIInterfaceOrientationPortrait</string>~
+** Processing line: ~ # <string>UIInterfaceOrientationLandscapeRight</string>~
+** Processing line: ~~
+** Processing line: ~ $gtk.write_file_root "tmp/ios/#{@app_name}.app/Info.plist", info_plist_string.gsub(":app_name", @app_name).strip~
+** Processing line: ~~
+** Processing line: ~ @info_plist_written = true~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def device_orientation_xml~
+** Processing line: ~ return "UIInterfaceOrientationLandscapeRight" if $gtk.logical_width > $gtk.logical_height~
+** Processing line: ~ return "UIInterfaceOrientationPortrait"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def tmp_directory~
+** Processing line: ~ "#{relative_path}/tmp/ios"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def app_path~
+** Processing line: ~ "#{tmp_directory}/#{@app_name}.app"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def root_folder~
+** Processing line: ~ "#{relative_path}/#{$gtk.cli_arguments[:dragonruby]}"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def write_ip_address~
+** Processing line: ~ $gtk.write_file "app/server_ip_address.txt", $gtk.ffi_misc.get_local_ip_address.strip~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def create_ipa~
+** Processing line: ~ write_ip_address~
+** Processing line: ~ sh "rm \"#{@app_name}\".ipa"~
+** Processing line: ~ sh "rm -rf \"#{app_path}/app\""~
+** Processing line: ~ sh "rm -rf \"#{app_path}/sounds\""~
+** Processing line: ~ sh "rm -rf \"#{app_path}/sprites\""~
+** Processing line: ~ sh "rm -rf \"#{app_path}/data\""~
+** Processing line: ~ sh "rm -rf \"#{app_path}/fonts\""~
+** Processing line: ~ sh "cp -r \"#{root_folder}/app/\" \"#{app_path}/app/\""~
+** Processing line: ~ sh "cp -r \"#{root_folder}/sounds/\" \"#{app_path}/sounds/\""~
+** Processing line: ~ sh "cp -r \"#{root_folder}/sprites/\" \"#{app_path}/sprites/\""~
+** Processing line: ~ sh "cp -r \"#{root_folder}/data/\" \"#{app_path}/data/\""~
+** Processing line: ~ sh "cp -r \"#{root_folder}/fonts/\" \"#{app_path}/fonts/\""~
+** Processing line: ~ sh "mkdir -p #{tmp_directory}/ipa_root/Payload"~
+** Processing line: ~ sh "cp -r \"#{app_path}\" \"#{tmp_directory}/ipa_root/Payload\""~
+** Processing line: ~ sh "chmod -R 755 \"#{tmp_directory}/ipa_root/Payload\""~
+** Processing line: ~ do_zip~
+** Processing line: ~ sh "cp \"#{tmp_directory}/ipa_root/archive.zip\" \"#{tmp_directory}/#{@app_name}.ipa\""~
+** Processing line: ~ sh "XCODE_DIR=\"/Applications/Xcode.app/Contents/Developer\" \"#{relative_path}/dragonruby-deploy-ios\" -d \"#{@device_id}\" \"#{tmp_directory}/#{@app_name}.ipa\""~
+** Processing line: ~ cmd_result = `ps -e | grep civetweb`~
+** Processing line: ~ is_civet_running = (`ps -e | grep civetweb`).strip.each_line.to_a.length > 2~
+** Processing line: ~ if !is_civet_running~
+** Processing line: ~ $gtk.system "cp \"#{relative_path}/civetweb\" \"#{tmp_directory}/../src_backup/civetweb\""~
+** Processing line: ~ $gtk.system "open \"#{tmp_directory}/../src_backup/civetweb\" -g"~
+** Processing line: ~ else~
+** Processing line: ~ log "* INFO: civetweb is running already running. No need to start another instance."~
+** Processing line: ~ end~
+** Processing line: ~ log_info "Check your device!!"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def do_zip~
+** Processing line: ~ $gtk.write_file_root "tmp/ios/do_zip.sh", <<-SCRIPT~
+** Processing line: ~ pushd #{tmp_directory}/ipa_root/~
+** Processing line: ~ zip -q -r archive.zip Payload~
+** Processing line: ~ popd~
+** Processing line: ~ SCRIPT~
+** Processing line: ~~
+** Processing line: ~ sh "sh #{tmp_directory}/do_zip.sh"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def sh cmd~
+** Processing line: ~ log_info cmd.strip~
+** Processing line: ~ result = `#{cmd}`~
+** Processing line: ~ if result.strip.length > 0~
+** Processing line: ~ log_info result.strip.each_line.map(&:strip).join("\n")~
+** Processing line: ~ end~
+** Processing line: ~ result~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def deploy~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~#+end_src~
+- PRE end detected.
+** Processing line: ~~
+** Processing line: ~~
+** Processing line: ~* itch_wizard.rb~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~itch_wizard.rb~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~#+begin_src ruby~
+- PRE start detected.
+** Processing line: ~ # ./dragon/itch_wizard.rb~
+** Processing line: ~ # Copyright 2019 DragonRuby LLC~
+** Processing line: ~ # MIT License~
+** Processing line: ~ # itch_wizard.rb has been released under MIT (*only this file*).~
+** Processing line: ~~
+** Processing line: ~ class ItchWizard~
+** Processing line: ~ def steps~
+** Processing line: ~ [~
+** Processing line: ~ :check_metadata,~
+** Processing line: ~ :deploy~
+** Processing line: ~ ]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def metadata_file_path~
+** Processing line: ~ "metadata/game_metadata.txt"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def get_metadata~
+** Processing line: ~ metadata = $gtk.read_file metadata_file_path~
+** Processing line: ~~
+** Processing line: ~ if !metadata~
+** Processing line: ~ write_blank_metadata~
+** Processing line: ~ metadata = $gtk.read_file metadata_file_path~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ dev_id, dev_title, game_id, game_title, version, icon = *metadata.each_line.to_a~
+** Processing line: ~~
+** Processing line: ~ {~
+** Processing line: ~ dev_id: dev_id.strip,~
+** Processing line: ~ dev_title: dev_title.strip,~
+** Processing line: ~ game_id: game_id.strip,~
+** Processing line: ~ game_title: game_title.strip,~
+** Processing line: ~ version: version.strip,~
+** Processing line: ~ icon: icon.strip~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def write_blank_metadata~
+** Processing line: ~ $gtk.write_file metadata_file_path, <<-S.strip~
+** Processing line: ~ #devid=myname~
+** Processing line: ~ #devtitle=My Name~
+** Processing line: ~ #gameid=mygame~
+** Processing line: ~ #gametitle=My Game~
+** Processing line: ~ #version=0.1~
+** Processing line: ~ #icon=metadata/icon.png~
+** Processing line: ~ S~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def check_metadata~
+** Processing line: ~ metadata_text = $gtk.read_file metadata_file_path~
+** Processing line: ~ if !metadata_text~
+** Processing line: ~ write_blank_metadata~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if metadata_text.each_line.to_a.length != 6~
+** Processing line: ~ write_blank_metadata~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ log "* INFO: Contents of #{metadata_file_path}:"~
+** Processing line: ~ log "#+begin_src txt"~
+** Processing line: ~ metadata_text.each_line { |l| log " #{l}" }~
+** Processing line: ~ log "#+end_src"~
+** Processing line: ~ metadata = get_metadata~
+** Processing line: ~~
+** Processing line: ~ if metadata[:dev_id].start_with?("#") || !@dev_id~
+** Processing line: ~ log "* PROMPT: Please provide your username for Itch."~
+** Processing line: ~ $console.set_command "$wizards.itch.set_dev_id \"your-itch-username\""~
+** Processing line: ~ return :need_dev_id~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if metadata[:dev_title].start_with?("#") || !@dev_title~
+** Processing line: ~ log "* PROMPT: Please provide developer's/company's name that you want displayed."~
+** Processing line: ~ $console.set_command "$wizards.itch.set_dev_title \"Your Name\""~
+** Processing line: ~ return :need_dev_title~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if metadata[:game_id].start_with?("#") || !@game_id~
+** Processing line: ~ log "* PROMPT: Please provide the id for you game. This is the id you specified when you set up a new game page on Itch."~
+** Processing line: ~ $console.set_command "$wizards.itch.set_game_id \"your-game-id\""~
+** Processing line: ~ return :need_game_id~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if metadata[:game_title].start_with?("#") || !@game_title~
+** Processing line: ~ log "* PROMPT: Please provide the display name for your game. (This can include spaces)"~
+** Processing line: ~ $console.set_command "$wizards.itch.set_game_title \"Your Game\""~
+** Processing line: ~ return :need_game_title~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if metadata[:version].start_with?("#") || !@version~
+** Processing line: ~ log "* PROMPT: Please provide the version for your game."~
+** Processing line: ~ $console.set_command "$wizards.itch.set_version \"1.0\""~
+** Processing line: ~ return :need_version~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if metadata[:icon].start_with?("#") || !@icon~
+** Processing line: ~ log "* PROPT: Please provide icon path for your game."~
+** Processing line: ~ $console.set_command "$wizards.itch.set_icon \"icon.png\""~
+** Processing line: ~ return :need_icon~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ return :success~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def set_dev_id value~
+** Processing line: ~ @dev_id = value~
+** Processing line: ~ write_metadata~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def set_dev_title value~
+** Processing line: ~ @dev_title = value~
+** Processing line: ~ write_metadata~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def set_game_id value~
+** Processing line: ~ @game_id = value~
+** Processing line: ~ write_metadata~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def set_game_title value~
+** Processing line: ~ @game_title = value~
+** Processing line: ~ write_metadata~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def set_version value~
+** Processing line: ~ @version = value~
+** Processing line: ~ write_metadata~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def set_icon value~
+** Processing line: ~ @icon = value~
+** Processing line: ~ write_metadata~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def write_metadata~
+** Processing line: ~ text = ""~
+** Processing line: ~ if @dev_id~
+** Processing line: ~ text += "devid=#{@dev_id}\n"~
+** Processing line: ~ else~
+** Processing line: ~ text += "#devid=myname\n"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if @dev_title~
+** Processing line: ~ text += "devtitle=#{@dev_title}\n"~
+** Processing line: ~ else~
+** Processing line: ~ text += "#devtitle=My Name\n"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if @game_id~
+** Processing line: ~ text += "gameid=#{@game_id}\n"~
+** Processing line: ~ else~
+** Processing line: ~ text += "#gameid=gameid\n"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if @game_title~
+** Processing line: ~ text += "gametitle=#{@game_title}\n"~
+** Processing line: ~ else~
+** Processing line: ~ text += "#gametitle=Game Name\n"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if @version~
+** Processing line: ~ text += "version=#{@version}\n"~
+** Processing line: ~ else~
+** Processing line: ~ text += "#version=0.1\n"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if @icon~
+** Processing line: ~ text += "icon=metadata/#{@icon}\n"~
+** Processing line: ~ else~
+** Processing line: ~ text += "#icon=metadata/icon.png\n"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ $gtk.write_file metadata_file_path, text~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def relative_path~
+** Processing line: ~ (File.dirname $gtk.binary_path)~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def package_command~
+** Processing line: ~ "#{File.join $gtk.get_base_dir, 'dragonruby-publish'}"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def deploy~
+** Processing line: ~ log_info "* Running dragonruby-publish: #{package_command}"~
+** Processing line: ~ results = $gtk.exec package_command~
+** Processing line: ~ log "#+begin_src"~
+** Processing line: ~ log results~
+** Processing line: ~ log "#+end_src"~
+** Processing line: ~ :success~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def start~
+** Processing line: ~ log "================"~
+** Processing line: ~ log "* INFO: Starting Itch Wizard."~
+** Processing line: ~ @start_at = Kernel.global_tick_count~
+** Processing line: ~ steps.each do |m|~
+** Processing line: ~ begin~
+** Processing line: ~ log_info "Running Itch Wizard Step: ~$wizards.itch.#{m}~"~
+** Processing line: ~ result = (send m) || :success if @wizard_status[m][:result] != :success~
+** Processing line: ~ @wizard_status[m][:result] = result~
+** Processing line: ~ if result != :success~
+** Processing line: ~ log_info "Exiting wizard. :#{result}"~
+** Processing line: ~ break~
+** Processing line: ~ end~
+** Processing line: ~ rescue Exception => e~
+** Processing line: ~ if e.is_a? WizardException~
+** Processing line: ~ $console.log.clear~
+** Processing line: ~ $console.archived_log.clear~
+** Processing line: ~ log "=" * $console.console_text_width~
+** Processing line: ~ e.console_primitives.each do |p|~
+** Processing line: ~ $console.add_primitive p~
+** Processing line: ~ end~
+** Processing line: ~ log "=" * $console.console_text_width~
+** Processing line: ~ $console.set_command (e.console_command || "$wizards.itch.start")~
+** Processing line: ~ else~
+** Processing line: ~ log_error "Step #{m} failed."~
+** Processing line: ~ log_error e.to_s~
+** Processing line: ~ $console.set_command "$wizards.itch.start"~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ break~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def reset~
+** Processing line: ~ @dev_id = nil~
+** Processing line: ~ @dev_title = nil~
+** Processing line: ~ @game_id = nil~
+** Processing line: ~ @game_title = nil~
+** Processing line: ~ @version = nil~
+** Processing line: ~ @icon = nil~
+** Processing line: ~ init_wizard_status~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def restart~
+** Processing line: ~ reset~
+** Processing line: ~ start~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def initialize~
+** Processing line: ~ reset~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def init_wizard_status~
+** Processing line: ~ @wizard_status = {}~
+** Processing line: ~~
+** Processing line: ~ steps.each do |m|~
+** Processing line: ~ @wizard_status[m] = { result: :not_started }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ previous_step = nil~
+** Processing line: ~ next_step = nil~
+** Processing line: ~~
+** Processing line: ~ steps.each_cons(2) do |current_step, next_step|~
+** Processing line: ~ @wizard_status[current_step][:next_step] = next_step~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ steps.reverse.each_cons(2) do |current_step, previous_step|~
+** Processing line: ~ @wizard_status[current_step][:previous_step] = previous_step~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~#+end_src~
+- PRE end detected.
+** Processing line: ~~
+** Processing line: ~~
+** Processing line: ~* layout.rb~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~layout.rb~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~#+begin_src ruby~
+- PRE start detected.
+** Processing line: ~ # ./dragon/layout.rb~
+** Processing line: ~ # Copyright 2019 DragonRuby LLC~
+** Processing line: ~ # MIT License~
+** Processing line: ~ # layout.rb has been released under MIT (*only this file*).~
+** Processing line: ~~
+** Processing line: ~ module GTK~
+** Processing line: ~ class Margin~
+** Processing line: ~ attr :left, :right, :top, :bottom~
+** Processing line: ~~
+** Processing line: ~ def initialize~
+** Processing line: ~ @left = 0~
+** Processing line: ~ @right = 0~
+** Processing line: ~ @top = 0~
+** Processing line: ~ @bottom = 0~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def serialize~
+** Processing line: ~ {~
+** Processing line: ~ left: @left,~
+** Processing line: ~ right: @right,~
+** Processing line: ~ top: @top,~
+** Processing line: ~ bottom: @bottom,~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def inspect~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def to_s~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ class SafeArea~
+** Processing line: ~ attr :w, :h, :margin~
+** Processing line: ~~
+** Processing line: ~ def initialize~
+** Processing line: ~ @w = 0~
+** Processing line: ~ @h = 0~
+** Processing line: ~ @margin = Margin.new~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def serialize~
+** Processing line: ~ {~
+** Processing line: ~ w: @w,~
+** Processing line: ~ h: @h,~
+** Processing line: ~ margin: @margin.serialize~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def inspect~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def to_s~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ class GridArea~
+** Processing line: ~ attr :w, :h, :margin, :gutter, :col_count, :row_count, :cell_w, :cell_h, :outer_gutter~
+** Processing line: ~~
+** Processing line: ~ def initialize~
+** Processing line: ~ @w = 0~
+** Processing line: ~ @h = 0~
+** Processing line: ~ @gutter = 0~
+** Processing line: ~ @outer_gutter = 0~
+** Processing line: ~ @col_count = 0~
+** Processing line: ~ @row_count = 0~
+** Processing line: ~ @margin = Margin.new~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def serialize~
+** Processing line: ~ {~
+** Processing line: ~ w: @w,~
+** Processing line: ~ h: @h,~
+** Processing line: ~ gutter: @gutter,~
+** Processing line: ~ outer_gutter: @outer_gutter,~
+** Processing line: ~ col_count: @col_count,~
+** Processing line: ~ row_count: @row_count,~
+** Processing line: ~ margin: @margin.serialize~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def inspect~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def to_s~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ class ControlArea~
+** Processing line: ~ attr :cell_size, :w, :h, :margin~
+** Processing line: ~~
+** Processing line: ~ def initialize~
+** Processing line: ~ @margin = Margin.new~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def serialize~
+** Processing line: ~ {~
+** Processing line: ~ cell_size: @cell_size,~
+** Processing line: ~ w: @w,~
+** Processing line: ~ h: @h,~
+** Processing line: ~ margin: @margin.serialize,~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def inspect~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def to_s~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ class Device~
+** Processing line: ~ attr :w, :h, :safe_area, :grid_area, :control_area, :name, :aspect~
+** Processing line: ~~
+** Processing line: ~ def initialize~
+** Processing line: ~ @name = ""~
+** Processing line: ~ @w = 0~
+** Processing line: ~ @h = 0~
+** Processing line: ~ @safe_area = SafeArea.new~
+** Processing line: ~ @grid_area = GridArea.new~
+** Processing line: ~ @control_area = ControlArea.new~
+** Processing line: ~ @aspect = AspectRatio.new~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def assert! result, message~
+** Processing line: ~ return if result~
+** Processing line: ~ raise message~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def check_math!~
+** Processing line: ~ assert! (@control_area.w + @control_area.margin.left + @control_area.margin.right) == @w, "Math for Width didn't pan out."~
+** Processing line: ~ assert! (@control_area.h + @control_area.margin.top + @control_area.margin.bottom) == @h, "Math for Height didn't pan out."~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def serialize~
+** Processing line: ~ {~
+** Processing line: ~ name: @name,~
+** Processing line: ~ w: @w,~
+** Processing line: ~ h: @h,~
+** Processing line: ~ aspect: @aspect.serialize,~
+** Processing line: ~ safe_area: @safe_area.serialize,~
+** Processing line: ~ grid_area: @grid_area.serialize,~
+** Processing line: ~ control_area: @control_area.serialize~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def inspect~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def to_s~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ class AspectRatio~
+** Processing line: ~ attr :w, :h, :u~
+** Processing line: ~~
+** Processing line: ~ def initialize~
+** Processing line: ~ @w = 0~
+** Processing line: ~ @h = 0~
+** Processing line: ~ @u = 0~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def serialize~
+** Processing line: ~ {~
+** Processing line: ~ w: @w,~
+** Processing line: ~ h: @h,~
+** Processing line: ~ u: @u~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def inspect~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def to_s~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ class Layout~
+** Processing line: ~ attr :w, :h, :rect_cache~
+** Processing line: ~~
+** Processing line: ~ def initialize w, h~
+** Processing line: ~ @w = w~
+** Processing line: ~ @h = h~
+** Processing line: ~ @rect_cache = {}~
+** Processing line: ~ init_device @w, @h~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def u_for_16x9 w, h~
+** Processing line: ~ u = (w.fdiv 16).floor~
+** Processing line: ~ u = (h.fdiv 9).floor if (u * 9) > h~
+** Processing line: ~~
+** Processing line: ~ {~
+** Processing line: ~ u: u,~
+** Processing line: ~ w: u * 16,~
+** Processing line: ~ h: u * 9~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_relative_size_enum size_enum~
+** Processing line: ~ base_line_logical = 22~
+** Processing line: ~ base_line_actual = font_size_med~
+** Processing line: ~ target_logical = size_enum~
+** Processing line: ~ target_logical = 1 if target_logical <= 0~
+** Processing line: ~ (base_line_actual / base_line_logical) * target_logical~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_px_to_pt px~
+** Processing line: ~ (px / 1.33333).floor~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_pt_to_px pt~
+** Processing line: ~ pt * 1.333333~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_size_cell~
+** Processing line: ~ (cell_height / 1.33333)~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_size_xl~
+** Processing line: ~ font_size_cell~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_size_lg~
+** Processing line: ~ font_size_cell * 0.8~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_size_med~
+** Processing line: ~ font_size_cell * 0.7~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_size_sm~
+** Processing line: ~ font_size_cell * 0.6~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_size_xs~
+** Processing line: ~ font_size_cell * 0.5~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def font_size~
+** Processing line: ~ font_size_cell * 0.7~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def logical_rect~
+** Processing line: ~ @logical_rect ||= { x: 0,~
+** Processing line: ~ y: 0,~
+** Processing line: ~ w: @w,~
+** Processing line: ~ h: @h }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def safe_rect~
+** Processing line: ~ @safe_rect ||= { x: 0,~
+** Processing line: ~ y: 0,~
+** Processing line: ~ w: @w,~
+** Processing line: ~ h: @h }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def control_rect~
+** Processing line: ~ @control_rect ||= { x: device.control_area.margin.left,~
+** Processing line: ~ y: device.control_area.margin.top,~
+** Processing line: ~ w: device.control_area.w,~
+** Processing line: ~ h: device.control_area.h }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def row_count~
+** Processing line: ~ device.grid_area.row_count~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def col_count~
+** Processing line: ~ device.grid_area.col_count~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def gutter_height~
+** Processing line: ~ device.grid_area.gutter~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def gutter_width~
+** Processing line: ~ device.grid_area.gutter~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def outer_gutter~
+** Processing line: ~ device.grid_area.outer_gutter~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def cell_height~
+** Processing line: ~ device.control_area.cell_size~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def cell_width~
+** Processing line: ~ device.control_area.cell_size~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def rect_defaults~
+** Processing line: ~ {~
+** Processing line: ~ row: nil,~
+** Processing line: ~ col: nil,~
+** Processing line: ~ h: 1,~
+** Processing line: ~ w: 1,~
+** Processing line: ~ dx: 0,~
+** Processing line: ~ dy: 0,~
+** Processing line: ~ rect: :control_rect~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def rect opts~
+** Processing line: ~ opts = rect_defaults.merge opts~
+** Processing line: ~ result = send opts[:rect]~
+** Processing line: ~ if opts[:row] && opts[:col] && opts[:w] && opts[:h]~
+** Processing line: ~ col = rect_col opts[:col], opts[:w]~
+** Processing line: ~ row = rect_row opts[:row], opts[:h]~
+** Processing line: ~ result = control_rect.merge x: col.x,~
+** Processing line: ~ y: row.y,~
+** Processing line: ~ w: col.w,~
+** Processing line: ~ h: row.h~
+** Processing line: ~ elsif opts[:row] && !opts[:col]~
+** Processing line: ~ result = rect_row opts[:row], opts[:h]~
+** Processing line: ~ elsif !opts[:row] && opts[:col]~
+** Processing line: ~ result = rect_col opts[:col], opts[:w]~
+** Processing line: ~ else~
+** Processing line: ~ raise "LayoutTheory::rect unable to process opts #{opts}."~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if opts[:max_height] && opts[:max_height] >= 0~
+** Processing line: ~ if result[:h] > opts[:max_height]~
+** Processing line: ~ delta = (result[:h] - opts[:max_height]) * 2~
+** Processing line: ~ result[:y] += delta~
+** Processing line: ~ result[:h] = opts[:max_height]~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if opts[:max_width] && opts[:max_width] >= 0~
+** Processing line: ~ if result[:w] > opts[:max_width]~
+** Processing line: ~ delta = (result[:w] - opts[:max_width]) * 2~
+** Processing line: ~ result[:x] += delta~
+** Processing line: ~ result[:w] = opts[:max_width]~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ result[:x] += opts[:dx]~
+** Processing line: ~ result[:y] += opts[:dy]~
+** Processing line: ~~
+** Processing line: ~ if opts[:include_row_gutter]~
+** Processing line: ~ result[:x] -= device.grid_area.gutter~
+** Processing line: ~ result[:w] += device.grid_area.gutter * 2~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ if opts[:include_col_gutter]~
+** Processing line: ~ result[:y] -= device.grid_area.gutter~
+** Processing line: ~ result[:h] += device.grid_area.gutter * 2~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ result~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def rect_center reference, target~
+** Processing line: ~ delta_x = (reference.w - target.w).fdiv 2~
+** Processing line: ~ delta_y = (reference.h - target.h).fdiv 2~
+** Processing line: ~ [target.x - delta_x, target.y - delta_y, target.w, target.h]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def rect_row index, h~
+** Processing line: ~ @rect_cache[:row] ||= {}~
+** Processing line: ~ @rect_cache[:row][index] ||= {}~
+** Processing line: ~ return @rect_cache[:row][index][h] if @rect_cache[:row][index][h]~
+** Processing line: ~ row_h = (device.grid_area.gutter * (h - 1)) +~
+** Processing line: ~ (device.control_area.cell_size * h)~
+** Processing line: ~~
+** Processing line: ~ row_h = row_h.to_i~
+** Processing line: ~ row_h -= 1 if row_h.odd?~
+** Processing line: ~~
+** Processing line: ~ row_y = (control_rect.y) +~
+** Processing line: ~ (device.grid_area.gutter * index) +~
+** Processing line: ~ (device.control_area.cell_size * index)~
+** Processing line: ~~
+** Processing line: ~ row_y = row_y.to_i~
+** Processing line: ~ row_y += 1 if row_y.odd? && (index + 1) > @device.grid_area.row_count.half~
+** Processing line: ~ row_y += 1 if row_y.odd? && (index + 1) <= @device.grid_area.row_count.half~
+** Processing line: ~~
+** Processing line: ~ row_y = device.h - row_y - row_h~
+** Processing line: ~~
+** Processing line: ~ result = control_rect.merge y: row_y, h: row_h~
+** Processing line: ~ @rect_cache[:row][index][h] = result~
+** Processing line: ~ @rect_cache[:row][index][h]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def rect_col index, w~
+** Processing line: ~ @rect_cache[:col] ||= {}~
+** Processing line: ~ @rect_cache[:col][index] ||= {}~
+** Processing line: ~ return @rect_cache[:col][index][w] if @rect_cache[:col][index][w]~
+** Processing line: ~ col_x = (control_rect.x) +~
+** Processing line: ~ (device.grid_area.gutter * index) +~
+** Processing line: ~ (device.control_area.cell_size * index)~
+** Processing line: ~~
+** Processing line: ~ col_x = col_x.to_i~
+** Processing line: ~ col_x -= 1 if col_x.odd? && (index + 1) < @device.grid_area.col_count.half~
+** Processing line: ~ col_x += 1 if col_x.odd? && (index + 1) >= @device.grid_area.col_count.half~
+** Processing line: ~~
+** Processing line: ~ col_w = (device.grid_area.gutter * (w - 1)) +~
+** Processing line: ~ (device.control_area.cell_size * w)~
+** Processing line: ~~
+** Processing line: ~ col_w = col_w.to_i~
+** Processing line: ~ col_w -= 1 if col_w.odd?~
+** Processing line: ~~
+** Processing line: ~ result = control_rect.merge x: col_x, w: col_w~
+** Processing line: ~ @rect_cache[:col][index][w] = result~
+** Processing line: ~ @rect_cache[:col][index][w]~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def device~
+** Processing line: ~ @device~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def init_device w, h~
+** Processing line: ~ @device = Device.new~
+** Processing line: ~ @device.w = w~
+** Processing line: ~ @device.h = h~
+** Processing line: ~ @device.name = "Device"~
+** Processing line: ~ @device.aspect.w = (u_for_16x9 w, h)[:w]~
+** Processing line: ~ @device.aspect.h = (u_for_16x9 w, h)[:h]~
+** Processing line: ~ @device.aspect.u = (u_for_16x9 w, h)[:u]~
+** Processing line: ~ @device.safe_area.w = @device.aspect.u * 16~
+** Processing line: ~ @device.safe_area.h = @device.aspect.u * 9~
+** Processing line: ~ @device.safe_area.margin.left = ((@device.w - @device.safe_area.w).fdiv 2).floor~
+** Processing line: ~ @device.safe_area.margin.right = ((@device.w - @device.safe_area.w).fdiv 2).floor~
+** Processing line: ~ @device.safe_area.margin.top = ((@device.h - @device.safe_area.h).fdiv 2).floor~
+** Processing line: ~ @device.safe_area.margin.bottom = ((@device.h - @device.safe_area.h).fdiv 2).floor~
+** Processing line: ~ @device.grid_area.outer_gutter = @device.w / 80~
+** Processing line: ~ @device.grid_area.gutter = @device.w / 160~
+** Processing line: ~~
+** Processing line: ~ @device.grid_area.w = @device.safe_area.w - (@device.grid_area.outer_gutter * 2)~
+** Processing line: ~ @device.grid_area.h = @device.safe_area.h - (@device.grid_area.outer_gutter * 2)~
+** Processing line: ~~
+** Processing line: ~ @device.grid_area.margin.left = ((@device.w - @device.grid_area.w).fdiv 2).floor~
+** Processing line: ~ @device.grid_area.margin.right = ((@device.w - @device.grid_area.w).fdiv 2).floor~
+** Processing line: ~ @device.grid_area.margin.top = ((@device.h - @device.grid_area.h).fdiv 2).floor~
+** Processing line: ~ @device.grid_area.margin.bottom = ((@device.h - @device.grid_area.h).fdiv 2).floor~
+** Processing line: ~~
+** Processing line: ~ @device.grid_area.col_count = 24~
+** Processing line: ~ @device.grid_area.row_count = 12~
+** Processing line: ~ @device.grid_area.cell_w = ((@device.aspect.w - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.col_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.col_count~
+** Processing line: ~ @device.grid_area.cell_h = ((@device.aspect.h - (@device.grid_area.outer_gutter * 2)) - ((@device.grid_area.row_count - 1) * @device.grid_area.gutter)).fdiv @device.grid_area.row_count~
+** Processing line: ~~
+** Processing line: ~ @device.control_area.cell_size = @device.grid_area.cell_w~
+** Processing line: ~ @device.control_area.cell_size = @device.grid_area.cell_h if @device.grid_area.cell_h < @device.grid_area.cell_w && @device.grid_area.cell_h > 0~
+** Processing line: ~ @device.control_area.cell_size = @device.control_area.cell_size.floor~
+** Processing line: ~ @device.control_area.w = (@device.control_area.cell_size * @device.grid_area.col_count) + (@device.grid_area.gutter * (@device.grid_area.col_count - 1))~
+** Processing line: ~ @device.control_area.h = (@device.control_area.cell_size * @device.grid_area.row_count) + (@device.grid_area.gutter * (@device.grid_area.row_count - 1))~
+** Processing line: ~ @device.control_area.margin.left = (@device.w - @device.control_area.w).fdiv 2~
+** Processing line: ~ @device.control_area.margin.right = (@device.w - @device.control_area.w).fdiv 2~
+** Processing line: ~ @device.control_area.margin.top = (@device.h - @device.control_area.h).fdiv 2~
+** Processing line: ~ @device.control_area.margin.bottom = (@device.h - @device.control_area.h).fdiv 2~
+** Processing line: ~ @device~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def serialize~
+** Processing line: ~ {~
+** Processing line: ~ device: @device.serialize,~
+** Processing line: ~ }~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def inspect~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def to_s~
+** Processing line: ~ serialize.to_s~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~#+end_src~
+- PRE end detected.
+** Processing line: ~~
+** Processing line: ~~
** Processing line: ~* log.rb~
- H1 detected.
- Determining if line is a header.
@@ -140368,6 +150737,11 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ return 720 - self unless $gtk~
** Processing line: ~ $gtk.args.grid.h - self~
** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def from_right~
+** Processing line: ~ return 1280 - self unless $gtk~
+** Processing line: ~ $gtk.args.grid.w - self~
+** Processing line: ~ end~
** Processing line: ~ end~
** Processing line: ~~
** Processing line: ~ class Fixnum~
@@ -140749,6 +151123,18 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ def draw_screenshots~
** Processing line: ~ @args.outputs.screenshots.each { |s| draw_screenshot s }~
** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~ def pixel_arrays~
+** Processing line: ~ @args.pixel_arrays.each { |k,v|~
+** Processing line: ~ if v.pixels.length == (v.width * v.height) # !!! FIXME: warning? exception? Different API?~
+** Processing line: ~ @ffi_draw.upload_pixel_array k.to_s, v.width.to_i, v.height.to_i, v.pixels~
+** Processing line: ~ end~
+** Processing line: ~ }~
+** Processing line: ~ rescue Exception => e~
+** Processing line: ~ pause!~
+** Processing line: ~ pretty_print_exception_and_export! e~
+** Processing line: ~ end~
+** Processing line: ~~
** Processing line: ~ end~
** Processing line: ~ end~
** Processing line: ~ end~
@@ -141235,6 +151621,9 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ # MIT License~
** Processing line: ~ # trace.rb has been released under MIT (*only this file*).~
** Processing line: ~~
+** Processing line: ~ # Contributors outside of DragonRuby who also hold Copyright:~
+** Processing line: ~ # - Dan Healy: https://github.com/danhealy~
+** Processing line: ~~
** Processing line: ~ module GTK~
** Processing line: ~ module Trace~
** Processing line: ~ IGNORED_METHODS = [~
@@ -141314,10 +151703,19 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ methods.reject { |m| m.start_with? "__trace_" }.reject { |m| IGNORED_METHODS.include? m }~
** Processing line: ~ end~
** Processing line: ~~
+** Processing line: ~ def self.trace_times_string~
+** Processing line: ~ str = []~
+** Processing line: ~ $trace_performance.sort_by {|method_name, times| -times[:avg] }.each do |method_name, times|~
+** Processing line: ~ str << "#{method_name}: #{times[:sum].round(2)}/#{times[:count]} #{times[:min]}ms min, #{times[:avg].round(2)}ms avg, #{times[:max]}ms max"~
+** Processing line: ~ end~
+** Processing line: ~ str.join("\n")~
+** Processing line: ~ end~
+** Processing line: ~~
** Processing line: ~ def self.flush_trace pad_with_newline = false~
** Processing line: ~ $trace_puts ||= []~
+** Processing line: ~ puts "(Trace info flushed!)"~
** Processing line: ~ if $trace_puts.length > 0~
-** Processing line: ~ text = $trace_puts.join("")~
+** Processing line: ~ text = $trace_puts.join("").strip + "\n" + self.trace_times_string + "\n"~
** Processing line: ~ if pad_with_newline~
** Processing line: ~ $gtk.append_file_root 'logs/trace.txt', "\n" + text.strip~
** Processing line: ~ else~
@@ -141332,6 +151730,15 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ $trace_history ||= []~
** Processing line: ~ $trace_enabled = true~
** Processing line: ~ $trace_call_depth ||=0~
+** Processing line: ~ $trace_performance = Hash.new {|h,k|~
+** Processing line: ~ h[k] = {~
+** Processing line: ~ min: 100000,~
+** Processing line: ~ max: 0,~
+** Processing line: ~ avg: 0,~
+** Processing line: ~ sum: 0,~
+** Processing line: ~ count: 0~
+** Processing line: ~ }~
+** Processing line: ~ }~
** Processing line: ~ flush_trace~
** Processing line: ~ instance = $top_level unless instance~
** Processing line: ~ return if Trace.traced_classes.include? instance.class~
@@ -141349,15 +151756,27 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ instance.__trace_call_depth__ += 1~
** Processing line: ~ $trace_call_depth = instance.__trace_call_depth__~
** Processing line: ~ parameters = "#{args}"[1..-2]~
+** Processing line: ~~
** Processing line: ~ $trace_puts << "\n #{tab_width}#{m}(#{parameters})"~
-** Processing line: ~ execution_time = Time.new.to_i~
+** Processing line: ~~
+** Processing line: ~ execution_time = Time.new~
+** Processing line: ~~
** Processing line: ~ $last_method_traced = trace_method_name~
** Processing line: ~ $trace_history << [m, parameters]~
+** Processing line: ~~
** Processing line: ~ result = send(trace_method_name, *args)~
-** Processing line: ~ completion_time = Time.new.to_i~
+** Processing line: ~~
+** Processing line: ~ class_m = "#{instance.class}##{m}"~
+** Processing line: ~ completion_time = ((Time.new - execution_time).to_f * 1000).round(2)~
+** Processing line: ~ $trace_performance[class_m][:min] = [$trace_performance[class_m][:min], completion_time].min~
+** Processing line: ~ $trace_performance[class_m][:max] = [$trace_performance[class_m][:max], completion_time].max~
+** Processing line: ~ $trace_performance[class_m][:count] += 1~
+** Processing line: ~ $trace_performance[class_m][:sum] += completion_time~
+** Processing line: ~ $trace_performance[class_m][:avg] = $trace_performance[class_m][:sum].fdiv($trace_performance[class_m][:count])~
+** Processing line: ~~
** Processing line: ~ instance.__trace_call_depth__ -= 1~
** Processing line: ~ instance.__trace_call_depth__ = instance.__trace_call_depth__.greater 0~
-** Processing line: ~ $trace_puts << "\n #{tab_width} success: #{m}"~
+** Processing line: ~ $trace_puts << "\n #{tab_width} #{completion_time > 10 ? '!!! ' : ''}#{completion_time}ms success: #{m}"~
** Processing line: ~ if instance.__trace_call_depth__ == 0~
** Processing line: ~ $trace_puts << "\n"~
** Processing line: ~ $trace_history.clear~
@@ -141383,4 +151802,34 @@ Follows is a source code listing for all files that have been open sourced. This
** Processing line: ~ end~
** Processing line: ~~
** Processing line: ~#+end_src~
+- PRE end detected.
+** Processing line: ~~
+** Processing line: ~~
+** Processing line: ~* wizards.rb~
+- H1 detected.
+- Determining if line is a header.
+- Line contains ~* ~... gsub-ing empty string
+- Formatting line: ~wizards.rb~
+- Line's tilde count is: 0
+- Line contains link marker: false
+** Processing line: ~~
+** Processing line: ~#+begin_src ruby~
+- PRE start detected.
+** Processing line: ~ # ./dragon/wizards.rb~
+** Processing line: ~ # Copyright 2019 DragonRuby LLC~
+** Processing line: ~ # MIT License~
+** Processing line: ~ # wizards.rb has been released under MIT (*only this file*).~
+** Processing line: ~~
+** Processing line: ~ module GTK~
+** Processing line: ~ class Wizards~
+** Processing line: ~ attr_accessor :ios, :itch~
+** Processing line: ~~
+** Processing line: ~ def initialize~
+** Processing line: ~ @ios = IOSWizard.new~
+** Processing line: ~ @itch = ItchWizard.new~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~ end~
+** Processing line: ~~
+** Processing line: ~#+end_src~
- PRE end detected. \ No newline at end of file