//*****************************************************************************************
// Truevision - a 3d modeler for gnome and povray
//
// scene.cc
//
// Vincent LE PRINCE <vincentleprince@users.sourceforge.net>
// Copyright (C) 2000-2001 Vincent LE PRINCE
// This file is part of the TRUEVISION Package

//   This program is free software; you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation; either version 2 of the License, or
//   (at your option) any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
//*******************************************************************************************
#include "config.h"
#include "include/scene.h"
#include "include/interface.h"
#include "include/dlgutils.h"
#include "include/povfe.h"
#include "include/tvio.h"
#include "include/undo.h"

// Définitions
const gchar *def_filename = N_("Untitled.tvs");
const char *scene_file_ext = ".tvs";

//***********************************************
// Constructeur
//***********************************************
Scene::Scene( app_objs *appref )
{
app_ref = appref;
app_ref->scene = this;
modified = false;
load_file_size = -1;
save_file_state = -1;

filename = NULL;
set_filename( def_filename );
default_path = NULL;
objlist = new ObjectList( app_ref );
texlist = new TexList( app_ref );
}


//***********************************************
// Nom
//***********************************************
void Scene::set_filename( const char *fname )
{
if ( filename != NULL ) delete filename;

int fname_len = strlen(fname);
filename = new char[ strlen(fname) + 5 ];
strcpy( filename, fname );
if ( strcmp( filename + fname_len - 4, scene_file_ext ) )
	strcat( filename, scene_file_ext );
set_win_title();
}

void Scene::set_win_title()
{
INTERF_DEF
if ( interf == NULL ) return;

int filename_len = strlen( filename );
int path_len = filename_len;
while ( path_len > 0 && filename[ --path_len ] != '/' );

char *title = new char[ strlen(APP_NAME) + filename_len - path_len + 5 ];
strcpy( title, APP_NAME );
strcat( title, " - " );
strcat( title, filename + (( path_len == 0 ) ? 0 : path_len+1 ) );
if ( modified ) strcat( title, "*" );
gtk_window_set_title( &(GNOME_APP(interf->get_gtkwin())->parent_object), title );
delete title;
}

void Scene::set_modified()
{
if ( modified == true ) return;
modified = true;
set_win_title();
save_widgets_active( TRUE );
}


void Scene::save_widgets_active( gboolean var )
{
gtk_widget_set_sensitive( tbw_save, var );
gtk_widget_set_sensitive( mew_save, var );
}


//***********************************************
// Output to povray
//***********************************************
void Scene::output_to_povray( const char *filename )
{
ofstream file( filename, ios::out );
if ( file == NULL ) { app_warning( _("Cannot open file : "), filename ); return; }
file.setf( ios::fixed, ios::floatfield );
//file.setf( ios::showpoint, ios::floatfield );



file << "//---------------------------------------------\n";
file << "// Created with Truevision, version " << VERSION;
file << "\n//---------------------------------------------\n";
if ( file == NULL ) return;

POVFE_DEF
povfe->output_to_povray( file );

texlist->output_to_povray( file );
objlist->output_to_povray( file );
file.close();
}

void Scene::export_to_povray_ask_fname()
{
filebox = gtk_file_selection_new( _("Export ...") );
GtkFileSelection *box = GTK_FILE_SELECTION(filebox);
gtk_signal_connect( GTK_OBJECT(box->ok_button), "clicked", GTK_SIGNAL_FUNC(sign_export_to_povray_with_fbox), this );
gtk_signal_connect( GTK_OBJECT(box->cancel_button), "clicked", GTK_SIGNAL_FUNC(sign_del_filebox), this );
gtk_widget_show( filebox );
}

void Scene::export_to_povray_with_fbox()
{
gchar *fname = (char*)gtk_file_selection_get_filename( GTK_FILE_SELECTION(filebox) );
ifstream file( fname );
if ( file )
	{
	file.close();
	//GtkWidget *dialog =  gnome_message_box_new ( _("File already exist, overwrite ?"),  GNOME_MESSAGE_BOX_WARNING, GNOME_STOCK_BUTTON_YES, GNOME_STOCK_BUTTON_NO, NULL);
	//gint button = gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
	//if ( button == 1 ) return;
	GtkWidget *dialog =  gtk_message_dialog_new ( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("File already exists, overwrite ?"));	
	gint button = gtk_dialog_run( GTK_DIALOG(dialog));
	gtk_widget_destroy( dialog );
	if ( button == GTK_RESPONSE_NO ) return;
	}

output_to_povray( fname );
sign_del_filebox( filebox, this );
}

char *Scene::get_temp_povray_file()
{
char *res = get_temp_filename();
output_to_povray( res );
return res;
}




//*******************************************
// Save
//*******************************************
void Scene::save()
{
if ( ! strcmp(  def_filename, filename ) ) { save_as(); return; }

ofstream file( filename, ios::out );
if ( file == NULL ) { app_warning( _("Cannot open file : "), filename ); return; }
file.setf( ios::fixed, ios::floatfield );

// Statistics & progress bar
INTERF_DEF
interf->set_status( _(" Saving..." ) );
save_file_state = 0;
save_file_size = texlist->get_size() + objlist->get_size();

file << "TRUEVISION SCENE";
file << "\nVERSION " << VERSION;

interf->save( file );
POVFE_DEF
povfe->save( file );

texlist->save( file );
objlist->save( file );

file.close();
modified = false;
set_win_title();
save_widgets_active( FALSE );
interf->set_progress( 0 );
interf->clear_status();
save_file_state = -1;
}

void Scene::set_save_progress()
{
if ( save_file_state == -1 ) return;
save_file_state++;
float val = (float)save_file_state / (float)save_file_size;
INTERF_DEF
interf->set_progress( val );
}

void Scene::save_as()
{
filebox = gtk_file_selection_new( _("Save as...") );
GtkFileSelection *box = GTK_FILE_SELECTION(filebox);
if ( filename != NULL ) gtk_file_selection_set_filename( box, filename );
gtk_signal_connect( GTK_OBJECT(box->ok_button), "clicked", GTK_SIGNAL_FUNC(sign_save_as_with_fbox), this );
gtk_signal_connect( GTK_OBJECT(box->cancel_button), "clicked", GTK_SIGNAL_FUNC(sign_del_filebox), this );
//gtk_window_set_modal( & box->window, TRUE );
gtk_widget_show( filebox );
}


void Scene::save_as_with_fbox()
{
gchar *fname = (gchar*)gtk_file_selection_get_filename( GTK_FILE_SELECTION(filebox) );

ifstream file( fname );
if ( file )
	{
	file.close();
	//GtkWidget *dialog =  gnome_message_box_new ( _("File already exist, overwrite ?"),  GNOME_MESSAGE_BOX_WARNING, GNOME_STOCK_BUTTON_YES, GNOME_STOCK_BUTTON_NO, NULL);
	//gint button = gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
	//if ( button == 1 ) return;
	GtkWidget *dialog =  gtk_message_dialog_new ( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("File already exists, overwrite ?"));	
	gint button = gtk_dialog_run( GTK_DIALOG(dialog));
	gtk_widget_destroy( dialog );
	if ( button == GTK_RESPONSE_NO ) return;
	}

set_filename( fname );
sign_del_filebox( filebox, this );
save();
}




//****************************************
// New
//****************************************
void Scene::new_scene()
{
if ( modified )
	{
	//GtkWidget *dialog =  gnome_message_box_new ( _("Current scene is unsaved, close anyway ?"),  GNOME_MESSAGE_BOX_WARNING, GNOME_STOCK_BUTTON_YES, GNOME_STOCK_BUTTON_NO, NULL);
	//gint button = gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
	//if ( button == 1 ) return;
	GtkWidget *dialog =  gtk_message_dialog_new ( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("Current scene is unsaved, close anyway ?"));	
	gint button = gtk_dialog_run( GTK_DIALOG(dialog));
	gtk_widget_destroy( dialog );
	if ( button == GTK_RESPONSE_NO ) return;
	}

clear_scene();
modified = false;
filename = NULL;
set_filename( def_filename );
objlist->new_scene();
save_widgets_active( FALSE );
}


void Scene::clear_scene()
{
texlist->clear();
objlist->clear();
INTERF_DEF
interf->clear();
POVFE_DEF
povfe->reset_defaults();
UNDO_DEF
undoman->init();
}

//***************************************
// Load
//***************************************
void Scene::load_as()
{
filebox = gtk_file_selection_new( _("Open ...") );
GtkFileSelection *box = GTK_FILE_SELECTION(filebox);
if ( default_path != NULL ) gtk_file_selection_set_filename( box, default_path );
gtk_signal_connect( GTK_OBJECT(box->ok_button), "clicked", GTK_SIGNAL_FUNC(sign_load_with_fbox), this );
gtk_signal_connect( GTK_OBJECT(box->cancel_button), "clicked", GTK_SIGNAL_FUNC(sign_del_filebox), this );
//gtk_window_set_modal( & box->window, TRUE );
gtk_widget_show( filebox );
}


void Scene::load_with_fbox()
{
gchar *gname =  (gchar*)gtk_file_selection_get_filename( GTK_FILE_SELECTION(filebox) );
char *fname = new char[ strlen(gname) + 1 ];
strcpy( fname,  gname );
store_default_path( gname );
sign_del_filebox( filebox, this );

ifstream file( fname, ios::binary );
if ( file == NULL )
	{
	app_warning( _("Cannot open : "), fname );
	delete fname;
	return;
	}
if ( ! tvio_check_file_sig( file, "TRUEVISION SCENE" ) )
	{
	app_warning( _("File type unknown : "), fname );
	file.close();
	delete fname;
	return;
	}
tvio_get_soft_version( file );

if ( modified )
	{
	//GtkWidget *dialog =  gnome_message_box_new ( _("Current scene is unsaved, close anyway ?"),  GNOME_MESSAGE_BOX_WARNING, GNOME_STOCK_BUTTON_YES, GNOME_STOCK_BUTTON_NO, NULL);
	//gint button = gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
	//if ( button == 1 ) { file.close(); delete fname; return; }
	GtkWidget *dialog =  gtk_message_dialog_new ( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("Current scene is unsaved, close anyway ?"));	
	gint button = gtk_dialog_run( GTK_DIALOG(dialog));
	gtk_widget_destroy( dialog );
	if ( button == GTK_RESPONSE_NO ) return;
	}

// Statistics
INTERF_DEF
interf->set_status( _(" Loading...") );
file.seekg( 0, ios::end );	
load_file_size = file.tellg();
file.seekg( 0, ios::beg );	
	
// Clear scene	
texlist->clear();
objlist->clear();
POVFE_DEF
UNDO_DEF
undoman->init();
povfe->reset_defaults();
	
// Chargement
char * tag = NULL;
do {
	tag = tvio_get_next_tag( file );
	set_load_progress( file );
	if ( tag == NULL ) { break; }
	if( interf->load( file, tag ) ) continue;
	if( povfe->load( file, tag ) ) continue;
	if( texlist->load( file, tag ) ) continue;
	if( objlist->load( file, tag ) ) continue;
	tvio_skip_section(file );
	} while ( tag != NULL );	

file.close();
modified = false;
set_filename( fname );
delete fname;
save_widgets_active( FALSE );

interf->clear_status();
interf->set_progress( 0 );
load_file_size = -1;
}


void Scene::set_load_progress( ifstream & file )
{
if (  load_file_size == -1 ) return;
int state = file.tellg();
float val = (float)state / (float)load_file_size;
if ( val > 1.0 || val < 0 ) return;
INTERF_DEF
interf->set_progress( val );
}



void Scene::store_default_path( char *path )
{
if ( default_path != NULL ) delete default_path;
int len = strlen( path );
while ( len > 0 && path[len] != '/' ) len--;
if ( len == 0 ) return;
default_path = new char[ len +2 ];
strncpy( default_path, path, len+1 );
default_path[len+1] = '\0';
}
