##########################################################################
# This file is part of Vacuum Magic
# Copyright (C) 2008 by UPi <upi at sourceforge.net>
##########################################################################

=comment

== Creating a Video File with Vacuum Magic ==

These instructions will let you create a video file from your vacuum magic game.
The instructions are designed for linux, but they can work with windows just fine with minor adjustments.

You will need PerlMagick and mencoder.


=== # Creating a series of PNG files ===

# First, you play and save the game with the Flight Recorder.
# Quit Vacuum Magic.
# Set the <tt>MovieMode = 1</tt> in the vacuum magic config file (.vacuumrc on linux, vacuum.cfg on windows)
# Start Vacuum Magic, go to the Flight Recorder, and play back your saved flight.
# This will create a series of PNG files in a series of directories (1000 files / directory)

=== # Creating the sound file ===

# Quit Vacuum Magic.
# Set the MovieMode back to 0 in the config file.
# Set <tt>TimePrecisePlayback = 1</tt> in the config file.
# Start Vacuum Magic, play back the flight again, and record the sound with a sound recorder application of your choice.
# Save the sound file as a .wav file

=== # Converting the .PNG files to AVI ===

# find . -name "*.png" | sort > list.txt
# mencoder mf://@list.txt -mf fps=25 -oac copy -ovc xvid -xvidencopts bitrate=1500 -vf scale=640:480 -sws 2 -o movie.avi

There will be 25 PNG files per second, 1500 per minute. A 10-minute video (youtube limit) is 15000 PNGs

=cut

use strict;
use Image::Magick;


package Menu;
use vars qw($TotalSize);

sub GetPngFilename {
  my ($i) = @_;
  my ($filesPerDirectory, $directory);
  
  $filesPerDirectory = 1000;
  $directory = sprintf("%04d", int($i / $filesPerDirectory));
  if ($i % $filesPerDirectory == 0) {
    mkdir $directory;
  }
  return sprintf("$directory/movie%05d.png", $i);
}

sub SavePng {
  my ($filename) = @_;
  my ($data, $image, $result);
  
  $data = ::glReadPixels(0, 0, $::PhysicalScreenWidth, $::PhysicalScreenHeight, ::GL_RGB, ::GL_UNSIGNED_BYTE);
  $image = Image::Magick->new(magick=>'RGB', depth=>8, size=>$::PhysicalScreenWidth . 'x' . $::PhysicalScreenHeight );
  $result = $image->BlobToImage($data); warn $result if $result;
  $result = $image->Flip(); warn $result if $result;
  $result = $image->Write($filename); warn $result if $result;
  $TotalSize += (stat($filename))[7];
}

sub RecordToMovie {
  my ($self, $recordFile) = @_;
  my ($playback, @gameObjects, $difficulty, $tooltip, $i, $totalLength, $startingTime, $pngFile);
  
  $playback = &::LoadRecord($recordFile);
  return warn $playback  unless ref $playback;
  @gameObjects = @::GameObjects;
  @::GameObjects = ($playback);
  $difficulty = $::Difficulty;
  $::Difficulty = 0;
  $self->{silent} = 1;
  $tooltip = $self->{tooltip};
  $self->{tooltip} = [];
  $totalLength = length($playback->{recordedKeys}) / $playback->{snumguys} / 5;
  $TotalSize = 0;
  $startingTime = time;
  
  $i = 0;
  do {
    my $advance = 100/25;  # 25 fps; game runs at 100fps internally
    %::Events = %::MenuEvents = ();
    %::GameEvents = ();
    &::HandleEvents();
    while ($advance--) {
      $self->AdvanceGameObjects();
    }
    $pngFile = &GetPngFilename($i);
    if ( not(-f $pngFile) || ($i % 100 == 0) ) {
      $self->DrawGame();
      $::App->sync();
    }
    &SavePng($pngFile)  unless -f $pngFile;  # Allow resuming
    ++$i;
    my $complete = $playback->{keyPointer} / $totalLength;
    my $projectedSize = $TotalSize / $complete;
    my $projectedTime = (time - $startingTime) * (1 - $complete) / $complete;
    
    print STDERR "\r                                             \r",
      sprintf('%d; %.2f%% %dM / %dM ETA %02d:%02d', 
        $i, $complete * 100, $TotalSize / 1024 / 1024, $projectedSize / 1024 / 1024,
        $projectedTime / 60, $projectedTime % 60
      );
  } until ( $playback->{deleted} or $self->{abortgame} );
  
  @::GameObjects = @gameObjects;
  $::Difficulty = $difficulty;
  delete $self->{silent};
  $self->{tooltip} = $tooltip;
  $playback->Delete();
  $self->{abortgame} = 0;
  $::Game->SetSpecialProjection();
  
  $playback->Delete();
  $self->{abortgame} = 0;
  print STDERR "\nMovie complete.\n";
}


1;
