//*****************************************************************************************
// Truevision - a 3d modeler for gnome and povray
//
// texfinish.cc
//
// Vincent LE PRINCE <vincentleprince@users.sourceforge.net>
// Copyright (C) 2000-2005 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 "include/texfinish.h"
#include "include/dlgutils.h"
#include "include/tvio.h"
#include "include/preferences.h"

PovTexFinish::PovTexFinish( app_objs *appref, char *tagname ) : MaterialItem( app_ref, tagname )
{
set_name( _("Finish") );
item_type = TV_MITEM_FINISH;

	// Attention l'ordre de push est important pour le paste
	
finish = new TvWidget_bool_activator( N_("Use finish"), "USED", NULL, app_ref, false );
	widgets.push_back( finish );
ambient = new TvWidget_color( N_("Ambient"), "AMBIENT", NULL, app_ref );
	ambient->set( 0.1, 0.1, 0.1 );
	widgets.push_back( ambient );

reflection = new TvWidget_color( N_("Reflection"), "REFLEC", NULL, app_ref );
	reflection->set( 0, 0, 0 );
	widgets.push_back( reflection );
reflection_min = new TvWidget_color( N_("Minimum reflection"), "REFLECMIN", NULL, app_ref );
	reflection_min->set( 0, 0, 0 );
	widgets.push_back( reflection_min );
reflection_exponent = new TvWidget_float( N_("Exponent"), "REXP", NULL, app_ref, 1.0 );
	reflection_exponent->set_range( 100, 0, 0.01, 6 );
	widgets.push_back( reflection_exponent );
reflection_falloff = new TvWidget_float( N_("Falloff"), "FALLOFF", NULL, app_ref, 0 );
	reflection_falloff->set_range( 100, 0, 0.01, 6 );
	widgets.push_back( reflection_falloff );
reflection_metallic = new TvWidget_float( N_("Metallic"), "RMETAL", NULL, app_ref, 0 );
	reflection_metallic->set_range( 100, 0, 0.01, 6 );
	widgets.push_back( reflection_metallic );
reflection_fresnel = new TvWidget_bool( N_("Fresnel reflection"), "FRESNEL", NULL, app_ref, false );
	widgets.push_back( reflection_fresnel );
conserve_energy = new TvWidget_bool( N_("Conserve energy"), "CONSEN", NULL, app_ref, false );
	widgets.push_back( conserve_energy );


diffuse = new TvWidget_float( N_("Diffuse"), "DIFFUSE", NULL, app_ref, 0.6 );
	diffuse->set_range( 1, 0, 0.01, 6 );
	widgets.push_back( diffuse );
brilliance = new TvWidget_float( N_("Brilliance"), "BRILLIANCE", NULL, app_ref, 1.0 );
	brilliance->set_range( 10, 0, 0.1, 6 );
	widgets.push_back( brilliance );
phong = new TvWidget_float( N_("Phong"), "PHONG", NULL, app_ref, 0 );
	phong->set_range( 1, 0, 0.01, 6 );
	widgets.push_back( phong );
phong_size = new TvWidget_int( N_("Phong size"), "PSIZE", NULL, app_ref, 40 );
	phong_size->set_range( 400, 0, 1 );
	widgets.push_back( phong_size );
specular = new TvWidget_float( N_("Specular"), "SPEC", NULL, app_ref, 0 );
	specular->set_range( 1, 0, 0.01, 6 );
	widgets.push_back( specular );
roughness = new TvWidget_float( N_("Roughness"), "SROUGH", NULL, app_ref, 0.05 );
	roughness->set_range( 1, 0, 0.01, 6 );
	widgets.push_back( roughness );
metalic = new TvWidget_float( N_("Metallic"), "METAL", NULL, app_ref, 0 );
	metalic->set_range( 1, 0, 0.01, 6 );
	widgets.push_back( metalic );
irid = new TvWidget_bool_activator( N_("Use Iridescence"), "IRID_USED", NULL, app_ref, false );
	widgets.push_back( irid );
irid_amount = new TvWidget_float( N_("Roughness"), "IROUGH", NULL, app_ref, 0.25 );
	irid_amount->set_range( 1, 0, 0.01, 6 );
	widgets.push_back( irid_amount );
irid_thickness = new TvWidget_float( N_("Thickness"), "THICK", NULL, app_ref, 0.0 );
	irid_thickness->set_range( 2, 0, 0.01, 6 );
	widgets.push_back( irid_thickness );
irid_turbulence  = new TvWidget_float( N_("Turbulence"), "ITURB", NULL, app_ref, 0.0 );
	irid_turbulence->set_range( 1, 0, 0.01, 6 );
	widgets.push_back( irid_turbulence );
}


PovTexFinish::PovTexFinish( PovTexFinish & ref )  : MaterialItem( ref )
{
set_name( ref.get_name() );
item_type = TV_MITEM_FINISH;
finish = new TvWidget_bool_activator( *ref.finish ); widgets.push_back( finish );
ambient = new TvWidget_color( *ref.ambient ); widgets.push_back( ambient );
reflection = new TvWidget_color( *ref.reflection ); widgets.push_back( reflection );
reflection_min = new TvWidget_color( *ref.reflection_min ); widgets.push_back( reflection_min );
reflection_exponent = new TvWidget_float( *ref.reflection_exponent );	widgets.push_back( reflection_exponent );
reflection_falloff = new TvWidget_float( *ref.reflection_falloff );	widgets.push_back( reflection_falloff );
reflection_metallic = new TvWidget_float( *ref.reflection_metallic );	widgets.push_back( reflection_metallic );
reflection_fresnel = new TvWidget_bool( *ref.reflection_fresnel ); widgets.push_back( reflection_fresnel );

conserve_energy = new TvWidget_bool( *ref.conserve_energy ); widgets.push_back( conserve_energy );
diffuse = new TvWidget_float( *ref.diffuse  ); widgets.push_back( diffuse );
brilliance = new TvWidget_float( *ref.brilliance ); widgets.push_back( brilliance );
phong = new TvWidget_float( *ref.phong ); widgets.push_back( phong );
phong_size = new TvWidget_int( *ref.phong_size ); 	widgets.push_back( phong_size );
specular = new TvWidget_float( *ref.specular ); widgets.push_back( specular );
roughness = new TvWidget_float( *ref.roughness ); 	widgets.push_back( roughness );
metalic = new TvWidget_float( *ref.metalic ); widgets.push_back( metalic );
irid = new TvWidget_bool_activator( *ref.irid ); widgets.push_back( irid );
irid_amount = new TvWidget_float( *ref.irid_amount );	widgets.push_back( irid_amount );
irid_thickness = new TvWidget_float( *ref.irid_thickness ); 	widgets.push_back( irid_thickness );
irid_turbulence  = new TvWidget_float( *ref.irid_turbulence );	widgets.push_back( irid_turbulence );
}


PovTexFinish::~PovTexFinish()
{
for ( unsigned int i = 0 ; i < widgets.size() ; i++ )
	delete widgets[i];
}

void PovTexFinish::edit_widget( GtkWidget *box )
{
PREF_DEF
bool tt = pref->tooltips->value();
MaterialItem::edit_widget( box, _("Finish") );

GtkWidget *frame_box;
GtkWidget *vbox = gtk_vbox_new( FALSE, 0 );
finish->set_target( vbox );
finish->get_widget_no_toggle( edit_cont, tt );
gtk_box_pack_start( GTK_BOX(edit_cont), vbox, TRUE, TRUE, 0 );
	ambient->get_widget( vbox, tt );
	conserve_energy->get_widget( vbox, tt );

	frame_box = new_table( vbox, _("Diffuse"), 2 );
		diffuse->get_widget( frame_box, tt, 1 );
		brilliance->get_widget( frame_box, tt, 2 );	

	frame_box = new_table( vbox, _("Highlights"), 5 );
		phong->get_widget( frame_box, tt, 1 );
		phong_size->get_widget( frame_box, tt, 2 );
		specular->get_widget( frame_box, tt, 3 );
		roughness->get_widget( frame_box, tt, 4 );
		metalic->get_widget( frame_box, tt, 5 );

	frame_box = new_table( vbox, _("Specular reflection"), 6 );	
		reflection->get_widget( frame_box, tt, 1 );
		reflection_min->get_widget( frame_box, tt, 2 );
		reflection_exponent->get_widget( frame_box, tt, 3 );
		reflection_metallic->get_widget( frame_box, tt, 4 );
		reflection_falloff->get_widget( frame_box, tt, 5 );
		reflection_fresnel->get_widget( frame_box, tt, 6 );
	
	frame_box = dlg_simple_box_frame( _("Iridescence"), vbox );
	irid->get_widget_no_toggle( frame_box, tt );
	GtkWidget *irid_box = new_table_no_frame( frame_box, 3 );
	irid->set_target( irid_box );
		irid_amount->get_widget( irid_box, tt, 1 );
		irid_thickness->get_widget( irid_box, tt, 2 );
		irid_turbulence->get_widget( irid_box, tt, 3 );

gtk_widget_show_all( widget );
finish->update_widget();
irid->update_widget();
}

void PovTexFinish::destroy_widget()
{
MaterialItem::destroy_widget();
	for ( unsigned int i = 0 ; i < widgets.size() ; i++ )
		widgets[i]->clear_widget();
}

void PovTexFinish::flush()
{
for ( unsigned int i = 0 ; i < widgets.size() ; i++ )
	widgets[i]->flush();
}


void PovTexFinish::output_to_povray( ofstream & file )
{
if ( !finish->value() ) return;
file << "\n\t\tfinish {";

file << "\n\t\t\tambient ";
ambient->output_to_povray(file);

file << "\n\t\t\tdiffuse ";
diffuse->output_to_povray(file);

file << "\n\t\t\tbrilliance ";
brilliance->output_to_povray(file);

file << "\n\t\t\tphong ";
phong->output_to_povray(file);

file << "\n\t\t\tphong_size ";
phong_size->output_to_povray(file);

file << "\n\t\t\tspecular ";
specular->output_to_povray(file);

file << "\n\t\t\troughness ";
roughness->output_to_povray(file);

file << "\n\t\t\tmetallic ";
metalic->output_to_povray(file);

file << "\n\t\t\treflection {\n\t\t\t\t";
	reflection_min->output_to_povray(file); file << ", \t\t\t\t";
	reflection->output_to_povray(file);
	file << "\n\t\t\t\texponent ";
	reflection_exponent->output_to_povray(file);
	file << "\n\t\t\t\tfalloff ";
	reflection_falloff->output_to_povray(file);
	file << "\n\t\t\t\tmetallic ";
	reflection_metallic->output_to_povray(file);
	if ( reflection_fresnel->value() ) file << "\n\t\t\t\tfresnel ";
file << "\n\t\t\t\t}";

if ( irid->value() )
	{
	file << "\n\t\t\tirid {\n\t\t\t\t";
	irid_amount->output_to_povray(file);
	file << "\n\t\t\t\tthickness ";
	irid_thickness->output_to_povray(file);
	file << "\n\t\t\t\tturbulence ";
	irid_turbulence->output_to_povray(file);
	file << "\n\t\t\t}";
	}



if ( conserve_energy->value() ) file << "\n\t\t\tconserve_energy";

file << "\n\t\t}";
}


void PovTexFinish::save( ofstream & file )
{
if ( !finish->value() ) return;
file << "FINISH{\n";

finish->save(file);
name->save(file); file << "\n";
ambient->save(file); file << "\n";
diffuse->save(file);
brilliance->save(file); file << "\n";
phong->save(file);
phong_size->save(file); file << "\n";
specular->save(file);
roughness->save(file); file << "\n";
metalic->save(file);
reflection->save(file); file << "\n";
reflection_exponent->save(file); file << "\n";
reflection_falloff->save(file); file << "\n";
reflection_min->save(file); file << "\n";
reflection_metallic->save(file); file << "\n";
reflection_fresnel->save(file); file << "\n";
conserve_energy->save(file); file << "\n";

if ( irid->value() )
	{
	irid_amount->save(file);
	irid_thickness->save(file);
	irid_turbulence->save(file);
	}

file << "}";
}


bool PovTexFinish::load( ifstream & file, char * ltag )
{
if ( strcmp( "FINISH", ltag ) ) return false;
char * tag = NULL;
finish->set( true );

do
	{
	tag = tvio_get_next_tag( file );
	if ( tag == NULL ) break;
	bool found = false;
	for ( register unsigned int i = 0 ; i < widgets.size() ; i++ )
		if ( widgets[i]->load( file , tag ) ) { found = true; break; }
	if ( found ) continue;

	tvio_skip_section( file );
	}
while( tag != NULL );
return true;
}


bool PovTexFinish::paste( MaterialItem *item )
{
if ( item->get_type() != TV_MITEM_FINISH ) return false;
for ( unsigned int i = 0 ; i < widgets.size() ; i++ )
	{
	widgets[i]->copy( ((PovTexFinish*)item)->widgets[i] );
	widgets[i]->update_widget();	
	}
paste_basics( item );
return true;
}
