process (CWrp::Cli)

    # File ../lib/roller.rb, line 124
        def self.process
          options = OpenStruct.new

          processing = false
          exporting = false

          option_parser = OptionParser.new do |opts|
            opts.banner = '-' * 80 +
              "\n#{APP_NAME} #{APP_VERSION}\n" +
              "by #{AUTHOR_NAME} (#{AUTHOR_CONTACT})\n" +
              '-' * 80 +
              "\n\nUsage:\n  #{File.basename(RUBYSCRIPT2EXE.executable)} WRPFILE [options]"

            opts.separator ''
            opts.separator 'Replacing objects and textures:'

            options.replace_forests = []
            desc = 'Replace OFP forest block objects with individual trees and bushes, according to comma-separated list of YAML files (occurs after object replacement)'
            opts.on('-F', '--replace-forests A,B,C', Array, *desc.wrap(DESC_WIDTH)) do |o|
              options.replace_forests = o
              processing = true
            end

            options.replace_objects = []
            desc = 'Replace objects according to comma-separated list of YAML files (occurs before forest replacement)'
            opts.on('-o', '--replace-objects A,B,C', Array, *desc.wrap(DESC_WIDTH)) do |o|
              options.replace_objects = o
              processing = true
            end

            options.replace_textures = []
            desc = 'Replace textures according to comma-separated list of YAML files'
            opts.on('-t', '--replace-textures A,B,C', Array, *desc.wrap(DESC_WIDTH)) do |o|
              options.replace_textures = o
              processing = true
            end

            opts.separator ''
            opts.separator 'Altering the terrain:'

            options.terrain_cell_size = nil
            desc = 'Set new size of terrain cells (metres). This must give a legal grid size of 16x16 to 4096x4096 cells (e.g. for an island imported from OFP, which has 50m cells, you could resize to 800, 400, 200, 100, 25, 12.5, 6.25 or 3.125).'
            opts.on('-c', '--terrain-cell-size N', Float, *desc.wrap(DESC_WIDTH)) do |o|
              options.terrain_cell_size = o
              processing = true
            end

            options.terrain_bumpiness = nil
            desc = 'Maximum amount of vertical distortion of new grid points added by terrain-cell-size (metres). Applied after terrain cell resizing, but before other changes.'
            opts.on('-b', '--terrain-bumpiness N', Float, *desc.wrap(DESC_WIDTH)) do |o|
              options.terrain_bumpiness = o
              processing = true
            end

            options.raise_sea_level = nil
            desc = 'Move sea level up by this distance (move sea level down if negative). Done before edge-height is set.'
            opts.on('-r', '--raise-sea-level N', Float, *desc.wrap(DESC_WIDTH)) do |o|
              options.raise_sea_level = o
              processing = true
            end

            options.edge_height = nil
            desc = 'Sets the height of all terrain points around the edge to a specific value. This is applied after cell, bumpiness and sea-level changes.'
            opts.on('-e', '--edge-height N', Float, *desc.wrap(DESC_WIDTH)) do |o|
              options.edge_height = o
              processing = true
            end

            opts.separator ''
            opts.separator 'Generating images:'

            options.satellite_mask = nil
            desc = "Export a satellite mask PNG image (FILE defaults to 'WRPFILE#{DEFAULT_EXPORT_MASK}')"
            opts.on('-m', '--satellite-mask [FILE]', *desc.wrap(DESC_WIDTH)) do |o|
              options.satellite_mask = if o.nil?
                DEFAULT_EXPORT_MASK
              else
                o
              end
              exporting = true
            end

            options.satellite_cell_size = DEFAULT_SATELLITE_CELL_SIZE
            desc = "Size of satellite cells, i.e. pixels, in metres (defaults to #{DEFAULT_SATELLITE_CELL_SIZE}m if this option is omitted')"
            opts.on('-C', '--satellite-cell-size N', Float, *desc.wrap(DESC_WIDTH)) do |o|
              options.satellite_cell_size = o
            end

            opts.separator ''
            opts.separator 'Exporting files:'

            options.export_objects = nil
            desc = "Export BIS objects file (FILE defaults to 'WRPFILE#{DEFAULT_EXPORT_OBJECTS}')"
            opts.on('-O' ,'--objects [FILE]', *desc.wrap(DESC_WIDTH)) do |o|
              options.export_objects = if o.nil?
                DEFAULT_EXPORT_OBJECTS
              else
                o
              end
              exporting = true
            end

            options.export_unique_objects = nil
            desc = "Export a list of objects used in the WRP (FILE defaults to 'WRPFILE#{DEFAULT_EXPORT_UNIQUE_OBJECTS}')"
            opts.on('-u' ,'--unique-objects [FILE]', *desc.wrap(DESC_WIDTH)) do |o|
              options.export_unique_objects = if o.nil?
                DEFAULT_EXPORT_UNIQUE_OBJECTS
              else
                o
              end
              exporting = true
            end

            options.export_wrp = nil
            desc = "Export WRP file in 8WVR format, regardless of which format it was imported as (FILE defaults to 'WRPFILE#{DEFAULT_EXPORT_WRP}')"
            opts.on('-w', '--wrp [FILE]', *desc.wrap(DESC_WIDTH)) do |o|
              options.export_wrp = if o.nil?
                DEFAULT_EXPORT_WRP
              else
                o
              end
              exporting = true
            end

            options.export_xyz = nil
            desc = "Export XYZ file (FILE defaults to 'WRPFILE#{DEFAULT_EXPORT_XYZ}')"
            opts.on('-x', '--xyz [FILE]', *desc.wrap(DESC_WIDTH)) do |o|
              options.export_xyz = if o.nil?
                DEFAULT_EXPORT_XYZ
              else
                o
              end
              exporting = true
            end

            opts.separator ''
            opts.separator 'Common options:'

            options.show_progress = false
            desc = 'Show the graphical progress bar (which will slow down all import, export and processing slightly).'
            opts.on('-p', '--show-progress', *desc.wrap(DESC_WIDTH)) do
              options.show_progress = true
            end

            options.force_overwrite = false
            desc = 'Forces overwriting of existing output files (defaults to requesting user confirmation of overwrites)'
            opts.on('-f', '--force-overwrite', *desc.wrap(DESC_WIDTH)) do |o|
              options.force_overwrite = o
            end

            opts.on_tail('-?', '--help', 'Display this message') do |o|
              puts opts.help
              return true
            end
          end

          begin
            option_parser.parse!
          rescue => error
            puts error.message
            option_parser.help
            return false
          end

          if ARGV.size == 0
            puts "Need to specify a WRP file to import"
            puts option_parser.help
            return false
          elsif ARGV.size > 1
            puts "Too many arguments"
            puts option_parser.help
            return false
          end

          filename_in = ARGV.first

          # Add WRP extension if missing.
          base_name = filename_in.gsub(/#{File.extname(filename_in)}$/,'')
          filename_in += EXT_WRP if File.extname(filename_in).empty?

          start = Time.now

          puts '--- Importing ---'

          # Load WRP
          file8wvr = File.timed_open(filename_in, "rb") do |file|
            File8WVR.new(file, options.show_progress)
          end

          puts
          puts file8wvr.info
          puts

          # Process WRP
          if exporting
            puts '--- Processing ---'
          end

          # Resize the terrain grid size.
          unless options.terrain_cell_size.nil?
            print "Resizing terrain cell size from #{file8wvr.terrain_cell_size}m to #{options.terrain_cell_size}m..."
            timed_block do
              file8wvr.resize_terrain_grid(options.terrain_cell_size)
            end
          end

          unless options.terrain_bumpiness.nil?
            print "Applying up to #{options.terrain_bumpiness}m bumps..."
            timed_block do
              file8wvr.apply_bumpiness(options.terrain_bumpiness)
            end
          end

          # Set height along all four edges.
          unless options.raise_sea_level.nil?
            print "Altering sea level by #{if options.raise_sea_level >= 0 then '+' end}#{options.raise_sea_level}m..."
            timed_block do
              file8wvr.raise_sea_level(options.raise_sea_level)
            end
          end

          # Set height along all four edges.
          unless options.edge_height.nil?
            print "Setting terrain height along all edges to #{options.edge_height}m..."
            timed_block do
              file8wvr.set_edge_height(options.edge_height)
            end
          end

          # Replace objects.
          options.replace_objects.each do |filename|
            filename = find_config_file(filename)
            return false if filename.nil?
            print 'Replacing objects: '
            File.timed_open(filename, "r") do |file|
              num_replacements = file8wvr.replace_objects(YAML::load(file))
              print "replaced #{num_replacements} objects..."
            end
          end

          # Replace textures.
          options.replace_textures.each do |filename|
            filename = find_config_file(filename)
            return false if filename.nil?
            print 'Replacing textures: '
            File.timed_open(filename, "r") do |file|
              num_replacements = file8wvr.replace_textures(YAML::load(file))
              print "replaced #{num_replacements} textures..."
            end
          end

          # Replace blocks of trees.
          options.replace_forests.each do |filename|
            filename = find_config_file(filename)
            return false if filename.nil?
            print 'Replacing forests: '
            File.timed_open(filename, "r") do |file|
              num_blocks, num_models = file8wvr.replace_forests(YAML::load(file))
              print "replaced #{num_blocks} forest blocks with #{num_models} trees and bushes..."
            end
          end

          # Output the updated island info.
          if processing
            puts
            puts file8wvr.info
            puts
          end

          # EXPORT

          if exporting
            puts '--- Exporting ---'
          end

          # Export WRP file.
          unless options.export_wrp.nil?
            file_name = export_file_name(options.export_wrp, base_name, DEFAULT_EXPORT_WRP)

            if options.force_overwrite or confirm_overwrite(file_name)

              print "WRP export: "
              if file_name == filename_in
                puts "Not overwriting #{filename_in} to export WRP!"
                return false
              end

              File.timed_open(file_name, "wb") do |file|
                file8wvr.write_wrp(file)
              end

              if FileUtils.compare_file(filename_in, file_name)
                puts "Input and output WRP files are identical"
              end
            end
          end

          # Export XYZ data.
          unless options.export_xyz.nil?
            file_name = export_file_name(options.export_xyz, base_name, DEFAULT_EXPORT_XYZ)

            if options.force_overwrite or confirm_overwrite(file_name)
              print "XYZ export: "
              File.timed_open(file_name, "w") do |file|
                num_points = file8wvr.write_xyz(file)
                print "#{num_points} positions..."
              end
            end
          end

          # Export object template.
          unless options.export_objects.nil?
            file_name = export_file_name(options.export_objects, base_name, DEFAULT_EXPORT_OBJECTS)

            if options.force_overwrite or confirm_overwrite(file_name)
              print "Object export: "
              File.timed_open(file_name, "w") do |file|
                num_objects = file8wvr.write_object_template(file)
                print "#{num_objects} objects..."
              end
            end
          end

          # Export list of unique objects.
          unless options.export_unique_objects.nil?
            file_name = export_file_name(options.export_unique_objects, base_name, DEFAULT_EXPORT_UNIQUE_OBJECTS)

            if options.force_overwrite or confirm_overwrite(file_name)
              print "Unique objects export: "
              File.timed_open(file_name, "w") do |file|
                object_names = file8wvr.object_names
                object_names.each do |object|
                  file.puts object.downcase
                end
                print "#{object_names.size} objects..."
              end
            end
          end

          # Export satellite mask.
          unless options.satellite_mask.nil?
            image_file_name = export_file_name(options.satellite_mask, base_name, DEFAULT_EXPORT_MASK)

            if options.force_overwrite or confirm_overwrite(image_file_name)
              print 'Satellite-mask export...'

              timed_block do
                # TODO: Specify this file, rather than always use same one..
                config_file_name = find_config_file('mask.yaml')
                return false if config_file_name.nil?
                config = File.open(config_file_name, 'r') do |file|
                  YAML::load(file)
                end

                file8wvr.export_satellite_mask(image_file_name, options.satellite_cell_size, config)
              end
            end
          end

          puts
          puts "#{APP_NAME} completed in #{format_time(Time.now - start)}"

          true
        end