adventure_rl 0.0.1.pre.ld42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +5 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +47 -0
- data/LICENSE.txt +21 -0
- data/README.md +31 -0
- data/Rakefile +11 -0
- data/adventure_rl.gemspec +48 -0
- data/bin/console +7 -0
- data/bin/mkaudio +196 -0
- data/bin/mkclip +223 -0
- data/bin/rdoc +9 -0
- data/bin/setup +8 -0
- data/bin/vimall +5 -0
- data/doc/Mask.md +183 -0
- data/doc/Point.md +95 -0
- data/doc/Window.md +139 -0
- data/lib/AdventureRL/Animation.rb +63 -0
- data/lib/AdventureRL/Audio.rb +75 -0
- data/lib/AdventureRL/AudioPlayer.rb +65 -0
- data/lib/AdventureRL/Button.rb +51 -0
- data/lib/AdventureRL/Clip.rb +91 -0
- data/lib/AdventureRL/ClipPlayer.rb +187 -0
- data/lib/AdventureRL/Deltatime.rb +51 -0
- data/lib/AdventureRL/EventHandlers/Buttons.rb +225 -0
- data/lib/AdventureRL/EventHandlers/EventHandler.rb +62 -0
- data/lib/AdventureRL/EventHandlers/MouseButtons.rb +142 -0
- data/lib/AdventureRL/Events/Event.rb +69 -0
- data/lib/AdventureRL/Events/Mouse.rb +60 -0
- data/lib/AdventureRL/FileGroup.rb +100 -0
- data/lib/AdventureRL/FileGroupPlayer.rb +226 -0
- data/lib/AdventureRL/Helpers/Error.rb +68 -0
- data/lib/AdventureRL/Helpers/MethodHelper.rb +20 -0
- data/lib/AdventureRL/Helpers/PipeMethods.rb +26 -0
- data/lib/AdventureRL/Image.rb +77 -0
- data/lib/AdventureRL/Layer.rb +273 -0
- data/lib/AdventureRL/Mask.rb +462 -0
- data/lib/AdventureRL/Menu.rb +92 -0
- data/lib/AdventureRL/Modifiers/Gravity.rb +60 -0
- data/lib/AdventureRL/Modifiers/Inventory.rb +104 -0
- data/lib/AdventureRL/Modifiers/Pusher.rb +61 -0
- data/lib/AdventureRL/Modifiers/Solid.rb +302 -0
- data/lib/AdventureRL/Modifiers/Velocity.rb +163 -0
- data/lib/AdventureRL/Point.rb +188 -0
- data/lib/AdventureRL/Quadtree.rb +237 -0
- data/lib/AdventureRL/Rectangle.rb +62 -0
- data/lib/AdventureRL/Settings.rb +80 -0
- data/lib/AdventureRL/SolidsManager.rb +170 -0
- data/lib/AdventureRL/Textbox.rb +195 -0
- data/lib/AdventureRL/TimingHandler.rb +225 -0
- data/lib/AdventureRL/Window.rb +152 -0
- data/lib/AdventureRL/misc/extensions.rb +80 -0
- data/lib/AdventureRL/misc/require_files.rb +45 -0
- data/lib/AdventureRL/version.rb +3 -0
- data/lib/adventure_rl.rb +22 -0
- data/lib/default_settings.yml +20 -0
- data/vimrc +4 -0
- metadata +237 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 419aead10a1f774fe22958d32dc028016f1176fd9aaa7ed5774c2cfec570f6c6
|
4
|
+
data.tar.gz: b360c7689d0e920376812f90f1e600b8402d5a02e2271e22389ac7ef61778926
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3370836de93da89533476f2f828d086e630d9d143fb5ba03a9cfa30d536f28455a5f6343c7def30fcc4bb77e10d9dc9e77e5e9c051537022efa8100d6ab2e003
|
7
|
+
data.tar.gz: 1507a166dae00060b1d2d0d1fb467d671b7663eca6fbdc2bb0387216b52f2e8db69b9b3e8fe459724f5a87190ddbd1544e23a8e1af16e13bf38cac426cd2958a
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
git_source(:github) do |repo_name|
|
4
|
+
"https://github.com/#{repo_name}"
|
5
|
+
end
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem 'argument_parser', git: 'https://github.com/Noah2610/ArgumentParser'
|
9
|
+
end
|
10
|
+
|
11
|
+
# Specify your gem's dependencies in AdventureRL.gemspec
|
12
|
+
gemspec
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/Noah2610/ArgumentParser
|
3
|
+
revision: 3ac5b0083fd42ae8740d1d22d988f56c74a29470
|
4
|
+
specs:
|
5
|
+
argument_parser (1.0.0)
|
6
|
+
|
7
|
+
PATH
|
8
|
+
remote: .
|
9
|
+
specs:
|
10
|
+
adventure_rl (0.0.1.pre.ld42)
|
11
|
+
gosu (~> 0.13.3)
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
awesome_print (1.8.0)
|
17
|
+
byebug (10.0.2)
|
18
|
+
docile (1.3.1)
|
19
|
+
gosu (0.13.3)
|
20
|
+
json (2.1.0)
|
21
|
+
minitest (5.11.3)
|
22
|
+
rake (10.5.0)
|
23
|
+
rdoc (6.0.4)
|
24
|
+
simplecov (0.16.1)
|
25
|
+
docile (~> 1.1)
|
26
|
+
json (>= 1.8, < 3)
|
27
|
+
simplecov-html (~> 0.10.0)
|
28
|
+
simplecov-html (0.10.2)
|
29
|
+
virb (0.1.1)
|
30
|
+
|
31
|
+
PLATFORMS
|
32
|
+
ruby
|
33
|
+
|
34
|
+
DEPENDENCIES
|
35
|
+
adventure_rl!
|
36
|
+
argument_parser!
|
37
|
+
awesome_print
|
38
|
+
bundler (~> 1.16)
|
39
|
+
byebug
|
40
|
+
minitest (~> 5.0)
|
41
|
+
rake (~> 10.0)
|
42
|
+
rdoc (~> 6.0)
|
43
|
+
simplecov
|
44
|
+
virb
|
45
|
+
|
46
|
+
BUNDLED WITH
|
47
|
+
1.16.3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Noah Rosenzweig
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# AdventureRL
|
2
|
+
Point-N-Click adventure game framework, using real video recordings as animations.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
Add this line to your application's Gemfile:
|
6
|
+
```ruby
|
7
|
+
gem 'adventure_rl'
|
8
|
+
```
|
9
|
+
And then execute:
|
10
|
+
```
|
11
|
+
$ bundle
|
12
|
+
```
|
13
|
+
Or install it yourself as:
|
14
|
+
```
|
15
|
+
$ gem install adventure_rl
|
16
|
+
```
|
17
|
+
|
18
|
+
## Documentation
|
19
|
+
Documentation is being written and is available under the `doc/` directory
|
20
|
+
in the project's root directory.
|
21
|
+
|
22
|
+
## Development
|
23
|
+
We have just started this project, so this gem is highly __Work In Progress__.
|
24
|
+
|
25
|
+
While developing this framework, we are creating a [demo game][demo-url] with it.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License][MIT-url].
|
29
|
+
|
30
|
+
[demo-url]: https://github.com/Noah2610/AdventureRL-Demo
|
31
|
+
[MIT-url]: https://opensource.org/licenses/MIT
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift lib unless ($LOAD_PATH.include? lib)
|
3
|
+
require 'AdventureRL/version'
|
4
|
+
github_url = 'https://github.com/Noah2610/AdventureRL'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'adventure_rl'
|
8
|
+
spec.version = AdventureRL::VERSION
|
9
|
+
spec.authors = ['Noah Rosenzweig']
|
10
|
+
spec.email = ['rosenzweig.noah@gmail.com']
|
11
|
+
spec.summary = <<-SUMMARY_END
|
12
|
+
Game framework built on top of Gosu.
|
13
|
+
SUMMARY_END
|
14
|
+
spec.description = <<-DESCRIPTION_END
|
15
|
+
This video game framework is written using the Gosu game development library.
|
16
|
+
It was originally intended to be used for writing Point-N-Click adventure games,
|
17
|
+
but has become a more general 2D video game framework.
|
18
|
+
It's interesting features include video and audio playback capabilities.
|
19
|
+
The project is definitely lacking some documentation.
|
20
|
+
Although I have been trying to write documentation using rdoc and write tests
|
21
|
+
with Minitest, I do not think that I have been doing either of those very successfully.
|
22
|
+
I don't think many people aside from myself will be able to use it properly,
|
23
|
+
as I have built it specifically for my needs.
|
24
|
+
Thank you for reading, have a nice day :)
|
25
|
+
DESCRIPTION_END
|
26
|
+
spec.homepage = github_url
|
27
|
+
spec.license = 'MIT'
|
28
|
+
|
29
|
+
# Specify which files should be added to the gem when it is released.
|
30
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
31
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
32
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
33
|
+
end
|
34
|
+
spec.bindir = 'exe'
|
35
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
36
|
+
spec.require_paths = ['lib']
|
37
|
+
|
38
|
+
spec.add_development_dependency 'awesome_print'
|
39
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
40
|
+
spec.add_development_dependency 'byebug'
|
41
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
42
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
43
|
+
spec.add_development_dependency 'rdoc', '~> 6.0'
|
44
|
+
spec.add_development_dependency 'simplecov'
|
45
|
+
spec.add_development_dependency 'virb'
|
46
|
+
|
47
|
+
spec.add_dependency 'gosu', '~> 0.13.3'
|
48
|
+
end
|
data/bin/console
ADDED
data/bin/mkaudio
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'argument_parser'
|
5
|
+
|
6
|
+
class AudioGenerator
|
7
|
+
DEFAULTS = {
|
8
|
+
fps: 10,
|
9
|
+
extension: 'flac'
|
10
|
+
}
|
11
|
+
HELP_TEXT = <<-EOT
|
12
|
+
USAGE
|
13
|
+
#{$0} [options...] AUDIO_FILEPATH
|
14
|
+
|
15
|
+
AUDIO_FILEPATH
|
16
|
+
The path to a audio or video file,
|
17
|
+
from which to extract the audio into multiple
|
18
|
+
smaller audio files..
|
19
|
+
This argument is mandatory.
|
20
|
+
|
21
|
+
OPTIONS
|
22
|
+
--help, -h
|
23
|
+
Print this text and exit.
|
24
|
+
|
25
|
+
--base-directory, --directory, --dir, -d BASE_DIRECTORY
|
26
|
+
The path and base name of the directory
|
27
|
+
where the files will be put. The full directory
|
28
|
+
name will be created with the following format:
|
29
|
+
{BASE_DIRECTORY}.{FPS}F.{EXTENSION}
|
30
|
+
This option is mandatory.
|
31
|
+
|
32
|
+
--fps, -f FPS
|
33
|
+
The frames per second to use, as an integer.
|
34
|
+
Default: '#{DEFAULTS[:fps]}'
|
35
|
+
|
36
|
+
--extension, --ext, -e EXTENSION
|
37
|
+
The extension and audio format to use for the audio files.
|
38
|
+
Default: '#{DEFAULTS[:extension]}'
|
39
|
+
EOT
|
40
|
+
VALID_ARGUMENTS = {
|
41
|
+
single: {
|
42
|
+
help: [
|
43
|
+
[?h],
|
44
|
+
false
|
45
|
+
],
|
46
|
+
directory: [
|
47
|
+
[?d],
|
48
|
+
true
|
49
|
+
],
|
50
|
+
fps: [
|
51
|
+
[?f],
|
52
|
+
true
|
53
|
+
],
|
54
|
+
extension: [
|
55
|
+
[?e],
|
56
|
+
true
|
57
|
+
]
|
58
|
+
},
|
59
|
+
double: {
|
60
|
+
help: [
|
61
|
+
['help'],
|
62
|
+
false
|
63
|
+
],
|
64
|
+
directory: [
|
65
|
+
['base-directory', 'directory', 'dir'],
|
66
|
+
true
|
67
|
+
],
|
68
|
+
fps: [
|
69
|
+
['fps'],
|
70
|
+
true
|
71
|
+
],
|
72
|
+
extension: [
|
73
|
+
['extension', 'ext'],
|
74
|
+
true
|
75
|
+
]
|
76
|
+
},
|
77
|
+
keywords: {
|
78
|
+
input: [:INPUT]
|
79
|
+
}
|
80
|
+
}
|
81
|
+
MESSAGE_PADDING = ' '
|
82
|
+
AUDIO_FILE_REGEX = /\A[\/\w\-]+?\.(flac|mp3|wav|ogg|mp4|mkv|webm)\z/i
|
83
|
+
BASE_DIRECTORY_REGEX = /\A[\/\w\-]+\z/
|
84
|
+
PERCENT_DECIMAL_POINTS = 2
|
85
|
+
|
86
|
+
def initialize
|
87
|
+
validate_dependencies
|
88
|
+
@arguments = ArgumentParser.get_arguments VALID_ARGUMENTS
|
89
|
+
@input_file = nil
|
90
|
+
@base_directory = nil
|
91
|
+
@fps = DEFAULTS[:fps]
|
92
|
+
@extension = DEFAULTS[:extension]
|
93
|
+
handle_arguments
|
94
|
+
validate_arguments
|
95
|
+
@directory = get_directory
|
96
|
+
end
|
97
|
+
|
98
|
+
def run
|
99
|
+
input_file_duration = `ffprobe -show_entries format=duration -v error -of default=noprint_wrappers=1:nokey=1 -i #{@input_file}`.strip.to_f
|
100
|
+
segment_duration = 1.0 / @fps.to_f
|
101
|
+
segments_amount = (input_file_duration / segment_duration).ceil
|
102
|
+
segments_amount.times do |n|
|
103
|
+
filename = "#{n.to_s.rjust 4, ?0}.#{@extension}"
|
104
|
+
seek_time = segment_duration * n
|
105
|
+
cmd = "ffmpeg -y -ss #{seek_time} -i #{@input_file} -t #{segment_duration} -vn #{@directory}/#{filename} &> /dev/null"
|
106
|
+
n_human = n + 1
|
107
|
+
percent = ((n_human.to_f / segments_amount.to_f) * 100.0).round(PERCENT_DECIMAL_POINTS)
|
108
|
+
msg(
|
109
|
+
"Executing:",
|
110
|
+
"`#{cmd}'",
|
111
|
+
"#{n_human}/#{segments_amount} -- #{percent.to_s}% done."
|
112
|
+
)
|
113
|
+
error(
|
114
|
+
"ffmpeg exited with an error code!"
|
115
|
+
) unless (system cmd)
|
116
|
+
end
|
117
|
+
msg "Done!", "Generated files in #{@directory}."
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def error *messages
|
123
|
+
message = messages.flatten.join(?\n).gsub(/^/,"#{MESSAGE_PADDING}")
|
124
|
+
abort([
|
125
|
+
"#{$0} ERROR",
|
126
|
+
message,
|
127
|
+
"#{MESSAGE_PADDING}Exiting."
|
128
|
+
].flatten.join(?\n))
|
129
|
+
end
|
130
|
+
|
131
|
+
def msg *messages
|
132
|
+
message = messages.flatten.join(?\n).gsub(/^/,"#{MESSAGE_PADDING}")
|
133
|
+
puts([
|
134
|
+
"#{$0}",
|
135
|
+
message
|
136
|
+
].flatten.join(?\n))
|
137
|
+
end
|
138
|
+
|
139
|
+
def validate_dependencies
|
140
|
+
error(
|
141
|
+
"`ffmpeg' is not available."
|
142
|
+
) unless (system('which ffmpeg &> /dev/null'))
|
143
|
+
end
|
144
|
+
|
145
|
+
def handle_arguments
|
146
|
+
if (@arguments[:options][:help])
|
147
|
+
puts HELP_TEXT
|
148
|
+
exit
|
149
|
+
end
|
150
|
+
@input_file = (@arguments[:keywords][:input] || []).first
|
151
|
+
@base_directory = @arguments[:options][:directory] if (@arguments[:options][:directory])
|
152
|
+
@fps = @arguments[:options][:fps] if (@arguments[:options][:fps])
|
153
|
+
@extension = @arguments[:options][:extension] if (@arguments[:options][:extension])
|
154
|
+
end
|
155
|
+
|
156
|
+
def validate_arguments
|
157
|
+
error(
|
158
|
+
"AUDIO_FILEPATH must be a valid audio or video file.",
|
159
|
+
"It must match `#{AUDIO_FILE_REGEX.inspect}'",
|
160
|
+
"Got `#{@input_file}'."
|
161
|
+
) unless (valid_audio_file? @input_file)
|
162
|
+
error(
|
163
|
+
"BASE_DIRECTORY must be in a valid parent directory.",
|
164
|
+
"It must match `#{BASE_DIRECTORY_REGEX.inspect}`",
|
165
|
+
"Got `#{@base_directory}'."
|
166
|
+
) unless (valid_base_directory? @base_directory)
|
167
|
+
# TODO: Validate other options.
|
168
|
+
end
|
169
|
+
|
170
|
+
def valid_audio_file? audio_file
|
171
|
+
return (
|
172
|
+
audio_file &&
|
173
|
+
File.file?(audio_file) &&
|
174
|
+
audio_file.match?(AUDIO_FILE_REGEX)
|
175
|
+
)
|
176
|
+
end
|
177
|
+
|
178
|
+
def valid_base_directory? base_directory
|
179
|
+
return (
|
180
|
+
base_directory &&
|
181
|
+
File.directory?(File.dirname(base_directory)) &&
|
182
|
+
base_directory.match?(BASE_DIRECTORY_REGEX)
|
183
|
+
)
|
184
|
+
end
|
185
|
+
|
186
|
+
def get_directory
|
187
|
+
directory = "#{@base_directory}.#{@fps.to_s}F.#{@extension}"
|
188
|
+
Dir.mkdir directory unless (File.directory? directory)
|
189
|
+
return directory
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
if ($0 == __FILE__)
|
194
|
+
generator = AudioGenerator.new
|
195
|
+
generator.run
|
196
|
+
end
|
data/bin/mkclip
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'argument_parser'
|
5
|
+
|
6
|
+
class ImageGenerator
|
7
|
+
DEFAULTS = {
|
8
|
+
resolution: '960x540',
|
9
|
+
fps: 24,
|
10
|
+
extension: 'png',
|
11
|
+
quality: 5
|
12
|
+
}
|
13
|
+
HELP_TEXT = <<-EOT
|
14
|
+
USAGE
|
15
|
+
#{$0} [options...] VIDEO_FILEPATH
|
16
|
+
|
17
|
+
VIDEO_FILEPATH
|
18
|
+
The path to a video file.
|
19
|
+
This argument is mandatory.
|
20
|
+
|
21
|
+
OPTIONS
|
22
|
+
--help, -h
|
23
|
+
Print this text and exit.
|
24
|
+
|
25
|
+
--base-directory, --directory, --dir, -d BASE_DIRECTORY
|
26
|
+
The path and base name of the directory
|
27
|
+
where the files will be put. The full directory
|
28
|
+
name will be created with the following format:
|
29
|
+
{BASE_DIRECTORY}.{RESOLUTION}.{FPS}F.{EXTENSION}
|
30
|
+
If the EXTENSION is a JPEG format, then the QUALITY will be included:
|
31
|
+
{BASE_DIRECTORY}.{RESOLUTION}.{FPS}F.{QUALITY}Q.{EXTENSION}
|
32
|
+
This option is mandatory.
|
33
|
+
|
34
|
+
--resolution, --res, -r RESOLUTION
|
35
|
+
The resolution to use for the images.
|
36
|
+
The images will be scaled to fit the resolution.
|
37
|
+
See `$ man ffmpeg' for formatting options.
|
38
|
+
Default: '#{DEFAULTS[:resolution]}'
|
39
|
+
|
40
|
+
--fps, -f FPS
|
41
|
+
The frames per second to use, as an integer.
|
42
|
+
Default: '#{DEFAULTS[:fps]}'
|
43
|
+
|
44
|
+
--extension, --ext, -e EXTENSION
|
45
|
+
The extension and image format to use for the images.
|
46
|
+
Default: '#{DEFAULTS[:extension]}'
|
47
|
+
|
48
|
+
--quality, -q QUALITY
|
49
|
+
The quality to use for JPEG compression, as an integer.
|
50
|
+
The higher the value is, the better the quality is.
|
51
|
+
This will only have an effect on compression formats that take a quality option.
|
52
|
+
Default: '#{DEFAULTS[:quality]}'
|
53
|
+
EOT
|
54
|
+
VALID_ARGUMENTS = {
|
55
|
+
single: {
|
56
|
+
help: [
|
57
|
+
[?h],
|
58
|
+
false
|
59
|
+
],
|
60
|
+
directory: [
|
61
|
+
[?d],
|
62
|
+
true
|
63
|
+
],
|
64
|
+
resolution: [
|
65
|
+
[?r],
|
66
|
+
true
|
67
|
+
],
|
68
|
+
fps: [
|
69
|
+
[?f],
|
70
|
+
true
|
71
|
+
],
|
72
|
+
extension: [
|
73
|
+
[?e],
|
74
|
+
true
|
75
|
+
],
|
76
|
+
quality: [
|
77
|
+
[?q],
|
78
|
+
true
|
79
|
+
]
|
80
|
+
},
|
81
|
+
double: {
|
82
|
+
help: [
|
83
|
+
['help'],
|
84
|
+
false
|
85
|
+
],
|
86
|
+
directory: [
|
87
|
+
['base-directory', 'directory', 'dir'],
|
88
|
+
true
|
89
|
+
],
|
90
|
+
resolution: [
|
91
|
+
['resolution', 'res'],
|
92
|
+
true
|
93
|
+
],
|
94
|
+
fps: [
|
95
|
+
['fps'],
|
96
|
+
true
|
97
|
+
],
|
98
|
+
extension: [
|
99
|
+
['extension', 'ext'],
|
100
|
+
true
|
101
|
+
],
|
102
|
+
quality: [
|
103
|
+
['quality'],
|
104
|
+
true
|
105
|
+
]
|
106
|
+
},
|
107
|
+
keywords: {
|
108
|
+
input: [:INPUT]
|
109
|
+
}
|
110
|
+
}
|
111
|
+
MESSAGE_PADDING = ' '
|
112
|
+
VIDEO_FILE_REGEX = /\A[\/\w\-]+?\.(mp4|mkv|webm)\z/i
|
113
|
+
BASE_DIRECTORY_REGEX = /\A[\/\w\-]+\z/
|
114
|
+
|
115
|
+
def initialize
|
116
|
+
validate_dependencies
|
117
|
+
@arguments = ArgumentParser.get_arguments VALID_ARGUMENTS
|
118
|
+
@input_file = nil
|
119
|
+
@base_directory = nil
|
120
|
+
@resolution = DEFAULTS[:resolution]
|
121
|
+
@fps = DEFAULTS[:fps]
|
122
|
+
@extension = DEFAULTS[:extension]
|
123
|
+
@quality = DEFAULTS[:quality]
|
124
|
+
handle_arguments
|
125
|
+
validate_arguments
|
126
|
+
@directory = get_directory
|
127
|
+
end
|
128
|
+
|
129
|
+
def run
|
130
|
+
cmd = "ffmpeg -y -i #{@input_file} -filter:v scale=#{@resolution} -r #{@fps} -qscale:v #{@quality} -an #{@directory}/%4d.#{@extension}"
|
131
|
+
msg(
|
132
|
+
"Executing:",
|
133
|
+
"`#{cmd}'"
|
134
|
+
)
|
135
|
+
error(
|
136
|
+
"ffmpeg exited with an error code!"
|
137
|
+
) unless (system cmd)
|
138
|
+
msg "Done!", "Generated files in #{@directory}."
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def error *messages
|
144
|
+
message = messages.flatten.join(?\n).gsub(/^/,"#{MESSAGE_PADDING}")
|
145
|
+
abort([
|
146
|
+
"#{$0} ERROR",
|
147
|
+
message,
|
148
|
+
"#{MESSAGE_PADDING}Exiting."
|
149
|
+
].flatten.join(?\n))
|
150
|
+
end
|
151
|
+
|
152
|
+
def msg *messages
|
153
|
+
message = messages.flatten.join(?\n).gsub(/^/,"#{MESSAGE_PADDING}")
|
154
|
+
puts([
|
155
|
+
"#{$0}",
|
156
|
+
message
|
157
|
+
].flatten.join(?\n))
|
158
|
+
end
|
159
|
+
|
160
|
+
def validate_dependencies
|
161
|
+
error(
|
162
|
+
"`ffmpeg' is not available."
|
163
|
+
) unless (system('which ffmpeg &> /dev/null'))
|
164
|
+
end
|
165
|
+
|
166
|
+
def handle_arguments
|
167
|
+
if (@arguments[:options][:help])
|
168
|
+
puts HELP_TEXT
|
169
|
+
exit
|
170
|
+
end
|
171
|
+
@input_file = (@arguments[:keywords][:input] || []).first
|
172
|
+
@base_directory = @arguments[:options][:directory] if (@arguments[:options][:directory])
|
173
|
+
@resolution = @arguments[:options][:resolution] if (@arguments[:options][:resolution])
|
174
|
+
@fps = @arguments[:options][:fps] if (@arguments[:options][:fps])
|
175
|
+
@extension = @arguments[:options][:extension] if (@arguments[:options][:extension])
|
176
|
+
@quality = @arguments[:options][:quality] if (@arguments[:options][:quality])
|
177
|
+
end
|
178
|
+
|
179
|
+
def validate_arguments
|
180
|
+
error(
|
181
|
+
"VIDEO_FILEPATH must be a valid video file.",
|
182
|
+
"It must match `#{VIDEO_FILE_REGEX.inspect}'",
|
183
|
+
"Got `#{@input_file}'."
|
184
|
+
) unless (valid_video_file? @input_file)
|
185
|
+
error(
|
186
|
+
"BASE_DIRECTORY must be in a valid parent directory.",
|
187
|
+
"It must match `#{BASE_DIRECTORY_REGEX.inspect}`",
|
188
|
+
"Got `#{@base_directory}'."
|
189
|
+
) unless (valid_base_directory? @base_directory)
|
190
|
+
# TODO: Validate other options.
|
191
|
+
end
|
192
|
+
|
193
|
+
def valid_video_file? video_file
|
194
|
+
return (
|
195
|
+
video_file &&
|
196
|
+
File.file?(video_file) &&
|
197
|
+
video_file.match?(VIDEO_FILE_REGEX)
|
198
|
+
)
|
199
|
+
end
|
200
|
+
|
201
|
+
def valid_base_directory? base_directory
|
202
|
+
return (
|
203
|
+
base_directory &&
|
204
|
+
File.directory?(File.dirname(base_directory)) &&
|
205
|
+
base_directory.match?(BASE_DIRECTORY_REGEX)
|
206
|
+
)
|
207
|
+
end
|
208
|
+
|
209
|
+
def get_directory
|
210
|
+
directory = "#{@base_directory}.#{@resolution}.#{@fps.to_s}F#{is_jpeg? ? ".#{@quality}Q" : ""}.#{@extension}"
|
211
|
+
Dir.mkdir directory unless (File.directory? directory)
|
212
|
+
return directory
|
213
|
+
end
|
214
|
+
|
215
|
+
def is_jpeg?
|
216
|
+
return @extension.match?(/\Ajpe?g\z/i)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
if ($0 == __FILE__)
|
221
|
+
generator = ImageGenerator.new
|
222
|
+
generator.run
|
223
|
+
end
|
data/bin/rdoc
ADDED
data/bin/setup
ADDED
data/bin/vimall
ADDED