replace_forests (CWrp::File8WVR)

    # File ../lib/roller/CWRP.rb, line 688
      def replace_forests(replacements)
        objects_to_add = Array.new # All new objects, that aren't direct replacements.
        num_forests_replaced = 0 # Number of forest objects replaced

        # Add new objects after the last one we already have.
        last_object_id = if @objects.empty?
          0
        else
          @objects.last.id
        end

        reset_progress 'Replacing forests', @objects.size / OBJECTS_PER_PROGRESS

        @objects.each_with_index do |object, index|
          # If replacement has been defined, replace it.
          replacement = replacements[object.name]
          unless replacement.nil?
            forest_id = object.id # ID of the object we are replacing.

            block_dir = object.dir

            total_proportion = replacement[:models].values.inject(0) do |total, value|
              total + value
            end

            # Work out how many to place within the block.
            min = replacement[:min].to_f
            max = replacement[:max].to_f
            to_place = (rand(max - min + 1) + min).floor

            sectors = replacement[:sectors]

            # Place a number of replacement objects.
            to_place.times do

              # Pick a random replacement object from the options.
              pick_proportion = rand() * total_proportion

              replacement[:models].each_pair do |model, proportion|
                pick_proportion -= proportion

                if pick_proportion <= 0
                  # Use a copy of the original orientation, so you have the same
                  # scale, but then rotate it randomly.
                  orientation = object.orientation.deep_copy
                  orientation.dir = rand() * 360

                  # Work out an appropriate position within the available sectors.
                  h_offset, v_offset = random_sector_position(sectors)

                  # Rotate the position based on the orientation of the block.
                  h_offset, v_offset = rotate(h_offset, v_offset, block_dir)

                  # Rotate the position around the block position,
                  # based on the block dir.
                  # TODO: The height will ALWAYS be wrong, unless on a flat plane.
                  position = object.position.deep_copy
                  position.x += h_offset
                  position.y += v_offset
                  position.z = height_at(position.x, position.y)

                  # The height (position.z) will be wrong, since object is not in same place!
                  if forest_id.nil?
                    # Not the first replacement, add object as a new object (not replacing an old ID).
                    last_object_id += 1
                    objects_to_add.push WrpObject.new(model, last_object_id, position, orientation)
                  else
                    # The first replacement for this block, so replace the block ID.
                    num_forests_replaced += 1
                    @objects[index] = WrpObject.new(model, forest_id, position, orientation)
                    forest_id = nil
                  end

                  break
                end
              end
            end
          end

          increment_progress if index.modulo(OBJECTS_PER_PROGRESS) == 0
        end

        @objects += objects_to_add

        [num_forests_replaced, objects_to_add.size]
      end