BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

make_screenshots.rb (7634B)


      1 #!/usr/bin/env ruby
      2 
      3 # To reggenerate screenshots:
      4 #  1. Extract module screenshots from Rack: ./scripts/make_module_screenshots.rb
      5 #  2. Make composite screenshots for README: ./scripts/make_screenshots.rb
      6 
      7 screens = [
      8   {
      9     file: 'modules1.png',
     10     crop: false,
     11     rows: [
     12       ['VCO', 'LVCO', 'Sine', 'Pulse', 'XCO', 'Additator', 'FMOp', 'Chirp'],
     13       ['LFO', 'LLFO', 'FourFO', 'EightFO']
     14     ]
     15   },
     16   {
     17     file: 'modules2.png',
     18     crop: false,
     19     rows: [
     20       ['VCF', 'LVCF', 'FFB', 'EQ', 'EQS', '-', 'LPG', 'LLPG', 'MegaGate'],
     21       ['PEQ', 'PEQ6', 'PEQ6XF', 'PEQ14', 'PEQ14XF'],
     22       ['DADSRH', 'DADSRHPlus', 'Shaper', 'ShaperPlus', 'AD', 'ASR', 'ADSR', 'Vish', 'DGate', 'RGate', 'Edge', 'Follow']
     23     ]
     24   },
     25   {
     26     file: 'modules3.png',
     27     crop: false,
     28     rows: [
     29       ['Mix8', 'Mix8x', 'Mute8'],
     30       ['Mix4', 'Mix4x', 'Mix1', 'Mix2', 'UMix', 'Mumix', 'VCM', 'Pan', 'XFade'],
     31       ['Matrix81', 'Matrix18', 'Matrix44', 'Matrix44Cvm'],
     32       ['Matrix88', 'Matrix88Cv', 'Matrix88M'],
     33       ['Switch81', 'Switch18', 'Switch44', 'Switch88', 'Switch1616']
     34     ]
     35   },
     36   {
     37     file: 'modules4.png',
     38     crop: false,
     39     rows: [
     40       ['VCA', 'VCAmp', 'Velo', '-', 'AMRM', 'Pressor', 'Clpr', 'Lmtr', 'Nsgt', 'CmpDist'],
     41       ['Noise', 'SampleHold', 'Walk2', 'Walk', '-', 'EightOne', 'OneEight', 'AddrSeq', 'AddrSeqX', 'PGMR', 'PGMRX'],
     42       ['VU', 'Analyzer', 'AnalyzerXL'],
     43       ['Ranalyzer']
     44     ]
     45   },
     46   {
     47     file: 'modules5.png',
     48     crop: false,
     49     rows: [
     50       ['Mono', 'Arp', 'Assign', 'Unison', 'PolyCon', 'PolyCon8', 'PolyOff16', 'PolyOff8', 'PolyMult', '-', 'Detune', 'Stack', 'Reftone'],
     51       ['Bool', 'Cmp', 'CVD', 'FlipFlop', 'Inv', 'Manual', 'FourMan', 'Mult', 'Offset', 'Slew', 'Sums', 'Switch', 'Lgsw', '-', 'Blank3', 'Blank6']
     52     ]
     53   },
     54 
     55   {
     56     file: 'skin-dark.png',
     57     crop: false,
     58     rows: [
     59       ['VCO', 'XCO', 'FMOp', 'Walk2', 'VCF', 'DADSRH', 'FFB', 'SampleHold', 'Pan'],
     60       ['Mix4', 'AddrSeq', 'Pgmr', 'Switch44', 'Analyzer', 'Pressor', 'Offset', 'Blank6']
     61     ],
     62     skin: 'dark',
     63     nopad: true
     64   },
     65   {
     66     file: 'skin-lowcontrast.png',
     67     crop: false,
     68     rows: [
     69       ['VCO', 'XCO', 'FMOp', 'Walk2', 'VCF', 'DADSRH', 'FFB', 'SampleHold', 'Pan'],
     70       ['Mix4', 'AddrSeq', 'Pgmr', 'Switch44', 'Analyzer', 'Pressor', 'Offset', 'Blank6']
     71     ],
     72     skin: 'lowcontrast',
     73     nopad: true
     74   },
     75 
     76   {
     77     file: 'oscillators1.png',
     78     crop: true,
     79     rows: [
     80       ['VCO', 'LVCO', 'Sine', 'Pulse', 'XCO']
     81     ]
     82   },
     83   {
     84     file: 'oscillators2.png',
     85     crop: true,
     86     rows: [
     87       ['Additator', 'FMOp', 'Chirp']
     88     ]
     89   },
     90   {
     91     file: 'lfos.png',
     92     crop: true,
     93     rows: [
     94       ['LFO', 'LLFO', 'FourFO', 'EightFO']
     95     ]
     96   },
     97   {
     98     file: 'filters.png',
     99     crop: true,
    100     rows: [
    101       ['VCF', 'LVCF', 'FFB', 'EQ', 'EQS']
    102     ]
    103   },
    104   {
    105     file: 'lpgs.png',
    106     crop: true,
    107     rows: [
    108       ['LPG', 'LLPG', 'MegaGAte']
    109     ]
    110   },
    111   {
    112     file: 'parametric_eqs1.png',
    113     crop: true,
    114     rows: [
    115       ['PEQ', 'PEQ6', 'PEQ6XF']
    116     ]
    117   },
    118   {
    119     file: 'parametric_eqs2.png',
    120     crop: true,
    121     rows: [
    122       ['PEQ14', 'PEQ14XF']
    123     ]
    124   },
    125   {
    126     file: 'envelopes1.png',
    127     crop: true,
    128     rows: [
    129       ['DADSRH', 'DADSRHPlus']
    130     ]
    131   },
    132   {
    133     file: 'envelopes2.png',
    134     crop: true,
    135     rows: [
    136       ['Shaper', 'ShaperPlus', 'AD', 'ASR', 'ADSR', 'Vish']
    137     ]
    138   },
    139   {
    140     file: 'envelopes3.png',
    141     crop: true,
    142     rows: [
    143       ['DGate', 'RGate', 'Edge', 'Follow']
    144     ]
    145   },
    146   {
    147     file: 'noise.png',
    148     crop: true,
    149     rows: [
    150       ['Noise', 'SampleHold', 'Walk2', 'Walk']
    151     ]
    152   },
    153   {
    154     file: 'mixers1.png',
    155     crop: true,
    156     rows: [
    157       ['Mix8', 'Mix8x']
    158     ]
    159   },
    160   {
    161     file: 'mixers2.png',
    162     crop: true,
    163     rows: [
    164       ['Mix4', 'Mix4x']
    165     ]
    166   },
    167   {
    168     file: 'mixers3.png',
    169     crop: true,
    170     rows: [
    171       ['Mix1', 'Mix2', 'UMix', 'Mumix', 'Mute8', 'VCM', 'Pan', 'XFade']
    172     ]
    173   },
    174   {
    175     file: 'mixers4.png',
    176     crop: true,
    177     rows: [
    178       ['Matrix81', 'Matrix18', 'Matrix44', 'Matrix44Cvm']
    179     ]
    180   },
    181   {
    182     file: 'mixers5.png',
    183     crop: true,
    184     rows: [
    185       ['Matrix88', 'Matrix88Cv', 'Matrix88M']
    186     ]
    187   },
    188   {
    189     file: 'mixers6.png',
    190     crop: true,
    191     rows: [
    192       ['Switch81', 'Switch18', 'Switch44', 'Switch88', 'Switch1616']
    193     ]
    194   },
    195   {
    196     file: 'vcas.png',
    197     crop: true,
    198     rows: [
    199       ['VCA', 'VCAmp', 'Velo']
    200     ]
    201   },
    202   {
    203     file: 'dynamics.png',
    204     crop: true,
    205     rows: [
    206       ['AMRM', 'Pressor', 'Clpr', 'Lmtr', 'Nsgt', 'CmpDist']
    207     ]
    208   },
    209   {
    210     file: 'sequencers1.png',
    211     crop: true,
    212     rows: [
    213       ['EightOne', 'OneEight', 'AddrSeq', 'AddrSeqX']
    214     ]
    215   },
    216   {
    217     file: 'sequencers2.png',
    218     crop: true,
    219     rows: [
    220       ['PGMR', 'PGMRX']
    221     ]
    222   },
    223   {
    224     file: 'visualizers.png',
    225     crop: true,
    226     rows: [
    227       ['VU', 'Analyzer']
    228     ]
    229   },
    230   {
    231     file: 'visualizers2.png',
    232     crop: true,
    233     rows: [
    234       ['AnalyzerXL']
    235     ]
    236   },
    237   {
    238     file: 'visualizers3.png',
    239     crop: true,
    240     rows: [
    241       ['Ranalyzer']
    242     ]
    243   },
    244   {
    245     file: 'poly1.png',
    246     crop: true,
    247     rows: [
    248       ['Mono', 'Arp', 'Assign', 'Unison']
    249     ]
    250   },
    251   {
    252     file: 'poly2.png',
    253     crop: true,
    254     rows: [
    255       ['PolyCon', 'Polycon8', 'PolyOff16', 'PolyOff8', 'PolyMult']
    256     ]
    257   },
    258   {
    259     file: 'pitch.png',
    260     crop: true,
    261     rows: [
    262       ['Detune', 'Stack', 'Reftone']
    263     ]
    264   },
    265   {
    266     file: 'utilities.png',
    267     crop: true,
    268     rows: [
    269       ['Bool', 'Cmp', 'CVD', 'FlipFlop', 'Inv', 'Manual', 'FourMan', 'Mult', 'Offset', 'Slew', 'Sums', 'Switch', 'Lgsw']
    270     ]
    271   },
    272   {
    273     file: 'misc.png',
    274     crop: true,
    275     rows: [
    276       ['Blank3', 'Blank6']
    277     ]
    278   }
    279 ]
    280 
    281 HP = 15
    282 PAD_EDGE = 1 * HP
    283 PAD_MODULE = 1 * HP
    284 PAD_GROUP = 3 * HP
    285 BACKGROUND_FILE = './doc/rack_background.png'
    286 
    287 # require 'chunky_png'
    288 require 'oily_png'
    289 require 'pp'
    290 
    291 base_dir = File.absolute_path(File.join(File.dirname($0), '..'))
    292 screens_dir = File.join(base_dir, 'doc', 'module_screenshots')
    293 unless Dir.exist?(screens_dir)
    294   STDERR.puts "No screenshots directory: #{screens_dir}\nMake it with ./scripts/make_module_screenshots.rb"
    295   exit 1
    296 end
    297 
    298 out_dir = File.join(base_dir, 'doc', 'www')
    299 unless Dir.exist?(screens_dir)
    300   STDERR.puts "No output directory: #{out_dir}"
    301   exit 1
    302 end
    303 
    304 $row_background = nil
    305 def background_for_rows(n)
    306   unless $row_background
    307     background = ChunkyPNG::Image.from_file(BACKGROUND_FILE)
    308     $row_background = background.crop(0, 31, 15 * ((background.dimension.width - 10) / 15), 380)
    309   end
    310 
    311   out = ChunkyPNG::Image.new($row_background.dimension.width, n * $row_background.dimension.height, ChunkyPNG::Color::TRANSPARENT)
    312   (0...n).each do |i|
    313     out.compose!($row_background, 0, i * $row_background.dimension.height)
    314   end
    315   out
    316 end
    317 
    318 screens.each do |screen|
    319   next unless screen
    320 
    321   unless screen.key?(:skin)
    322     screen[:skin] = 'default'
    323   end
    324 
    325   rows = screen[:rows]
    326   out = background_for_rows(rows.size)
    327   x = 0
    328   rows.each_with_index do |row, i|
    329     x = PAD_EDGE
    330     row.each_with_index do |item, j|
    331       if item == '-'
    332         unless screen[:nopad]
    333           x += PAD_GROUP
    334           x -= PAD_MODULE if j > 0
    335         end
    336       else
    337         image = ChunkyPNG::Image.from_file(File.join(screens_dir, screen[:skin], "#{item}.png"))
    338         out.compose!(image, x, i * $row_background.dimension.height)
    339         x += image.dimension.width
    340         x += PAD_MODULE unless screen[:nopad]
    341       end
    342     end
    343     x -= PAD_MODULE if rows.last.size > 0 && !screen[:nopad]
    344     x += PAD_EDGE
    345   end
    346 
    347   out.crop!(0, 0, x, out.dimension.height) if screen[:crop]
    348 
    349   file = File.join(out_dir, screen[:file])
    350   out.save(file)
    351   puts "wrote #{file}"
    352   # system("open #{file}")
    353 end