//*****************************************************************************************
// Truevision - a 3d modeler for gnome and povray
//
// scriptobj.cc
//
// Christian Spoer <spoer@users.sourceforge.net>
// Copyright (C) 2005      Christian SPOER
// 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/scriptobj.h"
#include "include/viewmanager.h"
#include "include/objectlist.h"
#include "include/tvio.h"
#include "include/preferences.h"
#include "include/pyengine.h"
#include "include/dlgutils.h"

//**************************************
// Constructors
//**************************************
ScriptObj::ScriptObj( app_objs *appref ) : Object3D_with_material( appref )
{
	type = TV_OBJ3D_SCRIPTOBJ;
	category = TV_OBJ3D_OBJECTS;
	set_name( _("ScriptObj") );

	// Basic parameters : Geometry and transformation widgets
	location = new ObjParam_point( N_("Translation"), "LOC", _("Translation transformation"), app_ref, true );
	location->set( 0, 0, 0 );
	size = new ObjParam_scale( N_("Scale"), "SIZE", _("Scale transformation"), app_ref, true );
	size->set( 0.2, 0.2, 0.2 );
	rotation = new ObjParam_rotation( N_("Rotation"), "ROT", _("Rotation transformation"), app_ref, true );
	rotation->set( 0, 0, 0 );
	this->set_script_path( NULL );
	triangle_list = new vector<GLTriangle*>;
	quad_list = new vector<GLQuad*>;
	value_list = new vector<ScriptValue*>;

	has_rotation = true;
	has_location = true;
	has_scale = true;
	has_material = true;
	has_editbutton = true;
}

ScriptObj::ScriptObj( ScriptObj & ref ) : Object3D_with_material( ref )
{
	location = new ObjParam_point( *ref.location );
	size = new ObjParam_scale( *ref.size );
	rotation = new ObjParam_rotation( *ref.rotation );
	this->set_script_path( strdup( ref.get_script_path() ) );
	triangle_list = new vector<GLTriangle*>;
	quad_list = new vector<GLQuad*>;
	value_list = new vector<ScriptValue*>;
	has_rotation = ref.is_has_rotation();
	has_location = ref.is_has_location();
	has_scale = ref.is_has_scale();
	has_material = ref.is_has_material();
	has_editbutton = ref.is_has_editbutton();
}


//**************************************
// Destructor
//**************************************
ScriptObj::~ScriptObj()
{
	delete location;
	delete size;
	delete rotation;
}

void
ScriptObj::add_triangle( float x1, float y1, float z1,
						 float x2, float y2, float z2,
						 float x3, float y3, float z3 )
{
	GLTriangle* t = new GLTriangle;
	t->x1 = x1; t->y1 = y1; t->z1 = z1;
	t->x2 = x2; t->y2 = y2; t->z2 = z2;
	t->x3 = x3; t->y3 = y3; t->z3 = z3;

	if ( triangle_list != NULL )
		triangle_list->push_back( t );
	else
		delete t;
}

void
ScriptObj::add_quad( float x1, float y1, float z1,
					 float x2, float y2, float z2,
					 float x3, float y3, float z3,
					 float x4, float y4, float z4 )
{
	GLQuad* q = new GLQuad;
	q->x1 = x1; q->y1 = y1; q->z1 = z1;
	q->x2 = x2; q->y2 = y2; q->z2 = z2;
	q->x3 = x3; q->y3 = y3; q->z3 = z3;
	q->x3 = x4; q->y4 = y4; q->z4 = z4;

	if ( quad_list != NULL )
		quad_list->push_back( q );
	else
		delete q;
}
			   
void
ScriptObj::clear_triangles()
{
	GLTriangle *t;
	vector<GLTriangle*>::iterator itTriangle;
	for(itTriangle = triangle_list->begin(); itTriangle != triangle_list->end(); itTriangle++) {
		t = (GLTriangle*) *(itTriangle);
		delete t;
	}
	triangle_list->clear();
}

void
ScriptObj::clear_quads()
{
	GLQuad *q;
	vector<GLQuad*>::iterator itQuad;
	for(itQuad = quad_list->begin(); itQuad != quad_list->end(); itQuad++) {
		q = (GLQuad*) *(itQuad);
		delete q;
	}
	quad_list->clear();
}

void
ScriptObj::new_int( char* _name, int _i )
{
	ScriptValue *v;
	int *_num;
	
	if ( _name == NULL )
		return;

	v = new ScriptValue;
	_num = (int*) malloc( sizeof( int ) );
	*_num = _i;
	
	v->name = strdup( _name );
	v->type = ST_INT;
	v->value = _num;

	add_value( v );
}

void
ScriptObj::new_float( char* _name, float _f )
{
	ScriptValue *v;
	float *_num;
	
	if ( _name == NULL )
		return;

	v = new ScriptValue;
	_num = (float*) malloc( sizeof( float ) );
	*_num = _f;
	
	v->name = strdup( _name );
	v->type = ST_FLOAT;
	v->value = _num;

	add_value( v );
}

void
ScriptObj::new_double( char* _name, double _d )
{
	ScriptValue *v;
	double *_num;
	
	if ( _name == NULL )
		return;

	v = new ScriptValue;
	_num = (double*) malloc( sizeof( double ) );
	*_num = _d;
	
	v->name = strdup( _name );
	v->type = ST_DOUBLE;
	v->value = _num;

	add_value( v );
}

void
ScriptObj::new_string( char* _name, char* _str )
{
	ScriptValue *v;
	char *_string;
	
	if ( _name == NULL || _str == NULL)
		return;

	v = new ScriptValue;
	_string = strdup( _str );

	v->name = strdup( _name );
	v->type = ST_STRING;
	v->value = _string;

	add_value( v );
}

void
ScriptObj::add_value( ScriptValue* v )
{
	if ( v == NULL )
		return;

	value_list->push_back( v );
}

ScriptValue*
ScriptObj::get_value( char* _name )
{
	ScriptValue* v = NULL;
	
	vector<ScriptValue*>::iterator itValue;
	for(itValue = value_list->begin(); itValue != value_list->end(); itValue++) {
		v = (ScriptValue*)(*itValue);

		if ( strcmp( v->name, _name ) == 0 )
			break;
	}
	return v;
}

int
ScriptObj::get_int( char* _name )
{
	ScriptValue *v = NULL;

	if ( _name == NULL )
		return -666;
	
	v = get_value( _name );

	if ( v == NULL )
		return -666;
			
	return (int)(*((int*)v->value));
}

float
ScriptObj::get_float( char* _name )
{
	ScriptValue *v = NULL;

	if ( _name == NULL )
		return -666.666;
	
	v = get_value( _name );

	if ( v == NULL )
		return -666.666;
			
	return (float)*((float*)v->value);
}

double
ScriptObj::get_double( char* _name )
{
	ScriptValue *v = NULL;

	if ( _name == NULL )
		return -666.666;
	
	v = get_value( _name );

	if ( v == NULL )
		return -666.666;
			
	return (double)*((double*)v->value);
}

char*
ScriptObj::get_string( char* _name )
{
	ScriptValue *v = NULL;

	if ( _name == NULL )
		return NULL;
	
	v = get_value( _name );

	if ( v == NULL )
		return NULL;
			
	return (char*)(v->value);
}

void
ScriptObj::set_value( char* _name, gpointer v )
{
	ScriptValue* val = NULL;
	
	vector<ScriptValue*>::iterator itValue;
	for(itValue = value_list->begin(); itValue != value_list->end(); itValue++) {
		val = (ScriptValue*)(*itValue);

		if ( strcmp( val->name, _name ) == 0 ) {
			val->value = v;
			break;
		}
	}
}

void
ScriptObj::set_int( char* _name, int _i )
{
	ScriptValue* v = NULL;
	
	vector<ScriptValue*>::iterator itValue;
	for(itValue = value_list->begin(); itValue != value_list->end(); itValue++) {
		v = (ScriptValue*)(*itValue);

		if ( strcmp( v->name, _name ) == 0 ) {
			*((int*)(v->value)) = _i;
			break;
		}
	}
}

void
ScriptObj::set_float( char* _name, float _f )
{
	ScriptValue* v = NULL;
	
	vector<ScriptValue*>::iterator itValue;
	for(itValue = value_list->begin(); itValue != value_list->end(); itValue++) {
		v = (ScriptValue*)(*itValue);

		if ( strcmp( v->name, _name ) == 0 ) {
			*((float*)(v->value)) = _f;
			break;
		}
	}
}

void
ScriptObj::set_double( char* _name, double _d )
{
	ScriptValue* v = NULL;
	
	vector<ScriptValue*>::iterator itValue;
	for(itValue = value_list->begin(); itValue != value_list->end(); itValue++) {
		v = (ScriptValue*)(*itValue);

		if ( strcmp( v->name, _name ) == 0 ) {
			*((double*)(v->value)) = _d;
			break;
		}
	}
}

void
ScriptObj::set_string( char* _name, char* _str )
{
	ScriptValue* v = NULL;
	
	vector<ScriptValue*>::iterator itValue;
	for(itValue = value_list->begin(); itValue != value_list->end(); itValue++) {
		v = (ScriptValue*)(*itValue);

		if ( strcmp( v->name, _name ) == 0 ) {
			v->value = _str;
			break;
		}
	}
}

//**************************************
// Display - virtual function from Object3D
//
// OpenGL calls to draw the box in the preview panels
//**************************************
void ScriptObj::display( glview *view, bool set_col )
{
	// If the user doesn't wanna see our nice object, we don't draw it
	if ( hidden->value() )
		return;
	
	// If one parameter has changed since last call we invalidate the OpenGL display list
	if ( location->changed() || size->changed() || rotation->changed() )
		list.invalidate();

	// Set General object parameters : color etc...
	Object3D::display( view );	
	if ( set_col ) 
		set_color();
	
	// Call the OpenGL display list or define it if set as invalid
	if ( ! list.exec() ) {
		// Set all parameters as unchanged
		location->unchange();
		size->unchange();
		rotation->unchange();
	
		// Create the display list
		list.begin();
		glPushMatrix();

	
		// retrieve translation, scale and rotation parameters from TvWidgets
		// apply them to OpenGL transformation matrix
		gfloat x, y, z;
		gfloat a, b, c;
		location->get( x, y, z );
		glTranslatef( x, y, z );
		size->get( a, b, c );
		glScalef( a, b, c );
		rotation->gl_rotate();

		// Draw triangles and quads
		glBegin( GL_TRIANGLES );
		GLTriangle *t;
		vector<GLTriangle*>::iterator itTriangle;
		for(itTriangle = triangle_list->begin(); itTriangle != triangle_list->end(); itTriangle++) {
			t = (GLTriangle*) *(itTriangle);
		
			glVertex3f( t->x1, t->y1, t->z1 );
			glVertex3f( t->x2, t->y2, t->z2 );
			glVertex3f( t->x3, t->y3, t->z3 );
		}
		glEnd();
		
		glBegin( GL_QUADS );
		GLQuad *q;
		vector<GLQuad*>::iterator itQuad;
		for(itQuad = quad_list->begin(); itQuad != quad_list->end(); itQuad++) {
			q = (GLQuad*) *(itQuad);
			//	glNormal3f( normal[i][0], normal[i][1], normal[i][2] );			
			glVertex3f( q->x1, q->y1, q->z1 );
			glVertex3f( q->x2, q->y2, q->z2 );
			glVertex3f( q->x3, q->y3, q->z3 );
			glVertex3f( q->x4, q->y4, q->z4 );
		}
		// End of OpenGL calls and end of display list
		glEnd();
		glPopMatrix();
		list.end();
	}
}

//***********************************************
// Edit Widget - virtual function from Object3D
//
// Display box parameters in the propertiy panel
// when object is selected
//***********************************************
void ScriptObj::edit_widget( GtkWidget *wid )
{
	// Check if we should display tooltips for TvWidgets
	PREF_DEF
	bool tt = pref->tooltips->value();
	
	// General options defined in Object3D.cc
	Object3D::edit_widget( wid );
	// Edit Stuff
	if (is_has_editbutton()) {
		GtkWidget *button = gtk_button_new_with_label( N_("Edit object") );
		gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_scriptobj_edit), this );
		gtk_box_pack_start( GTK_BOX(edit_cont), button, FALSE, FALSE, 1 );
	}
	
	int tab_num = 0;
	// Transformation
	if (is_has_rotation())
		tab_num++;
	if (is_has_location())
		tab_num++;
	if (is_has_scale())
		tab_num++;

	if ( tab_num > 0 ) {
		new_table( edit_cont, N_("Transformation"), tab_num );
		if (is_has_location())
			location->get_widget( table, tt, 1 );
		if (is_has_scale())
			size->get_widget( table, tt, 2 );
		if (is_has_rotation())
			rotation->get_widget( table, tt, 3 );
	}
	// Material & photon definitions from Object3D_with_material ( in Object3D.cc )
	if ( is_has_material() )
		get_texture_widgets( edit_cont, tt );

	// Show all this
	gtk_widget_show_all( wid );
}


//***********************************************
// Destroy editor - virtual from Object3D
//
// Destroy the parameter editor from property panel
// when object is deselected
//***********************************************
void ScriptObj::destroy_editor()
{
	Object3D::destroy_editor();
	location->clear_widget();
	size->clear_widget();
	texture->clear_widget();
	rotation->clear_widget();
	clear_triangles();
	clear_quads();
}


//***********************************************
// Mouse drag - virtual function from Object3D
//
// Callback for mouse interactions on preview panels
//***********************************************
void ScriptObj::mouse_drag( struct drag_info *drag )
{
	VMAN_DEF
	OBJLIST_DEF

	switch( vmanager->get_pointer_mode() ) {
	case TV_PMODE_SELECT:
	case TV_PMODE_TRANSLATE: {
		if (is_has_location())
			location->mouse_drag( drag );
		break;
	}
		
	case TV_PMODE_SCALE: {
		if (is_has_scale())
			size->mouse_drag( drag ); 
		break;
	}

	case TV_PMODE_ROTATE: {
		if (is_has_rotation())
			rotation->mouse_drag( drag ); 
		break; 
	}
		
	case TV_PMODE_CUSTOM: {
		((ObjParam_point*)(objlist->get_current_param()))->mouse_drag( drag );
		break;
	}
		
	default: 
		break;
	}
}



//***********************************************
// Pref_changed - virtual function from Object3D 
//
// Callback for Preferences change signal
//***********************************************
void ScriptObj::pref_changed()
{
	Object3D::pref_changed();
	if (is_has_location())
		location->pref_changed();
	if (is_has_scale())
		size->pref_changed();
	if (is_has_rotation())
		rotation->pref_changed();
}

void
ScriptObj::edit()
{
	PyObject *obj;

	PyEngine *pe = (PyEngine*) app_ref->python_engine;

	obj = PyCObject_FromVoidPtr( this, NULL );

	pe->execute_script(this->get_script_path(), obj, PY_MODE_EDIT);		
}


//***********************************************
// Output to povray - virtual function from Object3D
//
// Output code for povray
// pass1 -> declare object
// pass 2 -> use object
//***********************************************
void ScriptObj::output_to_povray_pass1( ofstream & file )
{
	float x, y, z;
	PyObject *obj;
	PyEngine *pe = (PyEngine*) app_ref->python_engine;

	// Call the script's output method....
	obj = PyCObject_FromVoidPtr( this, NULL );
	pe->execute_script(this->get_script_path(), obj, PY_MODE_POVPASS1);
	
	// Header
	file << "\n\n// ScriptObj : " << name->value();
	file << "\n#declare "; get_underscore_name( file ); file << " ="; 
	file << "\n";
	if ( this->get_pov_pass1_string() != NULL ) {
		file << this->get_pov_pass1_string();
	}
		
	// Material
	if( is_has_material() ) 
		Object3D_with_material::output_to_povray_pass1( file );
	
	file << "\t";
	
	// Transformation
	if (is_has_rotation())
		rotation->output_to_povray( file );
	if (is_has_scale()) {
		size->get( x, y, z );
		file << "\n\tscale <" << x << ',' << y << ',' << z << ">";
	}
	if (is_has_location()) {
		location->get( x, y, z );
		file << "\n\ttranslate <" << x << "," << y << "," << -z << ">";
	}
	file << "\n}  ";
}


//***********************************************
// Save - virtual from Object3D
//
// Save the object to a truevision scene or truevision
// object file
//***********************************************
void ScriptObj::save( ofstream & file )
{
	file << "\nSCRIPTOBJ{\n";
	save_basics( file );

	location->save( file );
	size->save( file );
	rotation->save( file );
	texture->save( file );

	save_script_path( file );
	save_triangles( file );
	save_quads( file );
	save_values( file );
	save_has_transform( file );
	file << "\n}";
}


//***********************************************
// Load - virtual from Object3D
//
// Load the object from a truevision scene or truevision
// object file
//***********************************************
bool ScriptObj::load( ifstream & file, char *ltag )
{
	if ( strcmp( ltag, "SCRIPTOBJ" ) ) 
		return false;
	set_load_progress( file );

	char * tag = NULL;
	do {
		tag = tvio_get_next_tag( file );
		if ( tag == NULL )
			break;
	
		if ( load_basics( file, tag ) ) 
			continue;
 		if ( location->load( file, tag ) ) 
			continue;
 		if ( size->load( file, tag ) ) 
			continue;
 		if ( rotation->load( file, tag ) ) 
			continue;
		if ( load_triangles( file, tag ) )
			continue;
		if ( load_quads( file, tag ) )
			continue;
		if ( load_script_path( file, tag ) )
			continue;
		if ( load_values( file, tag ) )
			continue;
		if ( load_has_transform( file, tag ) )
			continue;
		
		tvio_skip_section(file );
	} while ( tag != NULL );
	
	return true;
}

void
ScriptObj::save_values( ofstream & file )
{
	ScriptValue *val = NULL;
	vector<ScriptValue*>::iterator itValue;
	for(itValue = value_list->begin(); itValue != value_list->end(); itValue++) {
		val = (ScriptValue*) *(itValue);
		file << "SCRIPT_VALUE" << "{";
		file << "SV_NAME{VALUE=\"" << val->name << "\"}";
		switch(val->type) {
		case ST_INT:
			file << "SV_TYPE{VALUE=\"ST_INT\"}";
			file << "SV_VALUE{VALUE=\"" << *((int*)val->value) << "\"}";
			break;
        case ST_FLOAT:
			file << "SV_TYPE{VALUE=\"ST_FLOAT\"}";
			file << "SV_VALUE{VALUE=\"" << *((float*)val->value) << "\"}";
			break;
		case ST_DOUBLE:
			file << "SV_TYPE{VALUE=\"ST_DOUBLE\"}";
			file << "SV_VALUE{VALUE=\"" << *((double*)val->value) << "\"}";
			break;
		case ST_STRING:
		default:
			file << "SV_TYPE{VALUE=\"ST_STRING\"}";
			file << "SV_VALUE{VALUE=\"" << (char*)val->value << "\"}";
			break;
		}
		
		file << "} ";
	}
}

bool
ScriptObj::load_values( ifstream & file, char* tag )
{
	if ( strcmp( "SCRIPT_VALUE", tag ) ) 
		return false;
	
	char *tag2;
	char *name = NULL;
	char *value = NULL;
	ScriptType type;
	do{
		tag2 = tvio_get_next_tag( file );
		if ( tag2 == NULL )
			break;

		if ( load_value_name( file, tag2, &name ) )
			continue;
		if ( load_value_type( file, tag2, &type ) )
			continue;
		if ( load_value_value( file, tag2, &value ) )
			continue;
		
		tvio_skip_section(file );
	} while ( tag2 != NULL );
	
	if ( (name != NULL) && (value != NULL) ) {
			
		if ( type == ST_INT ) {
			new_int( name, atoi( value ) );
		} else if ( type == ST_FLOAT ) {
			new_float( name, (float)atof( value ) );
		} else if ( type == ST_DOUBLE ) {
			new_double( name, (double)atof( value ) );
		} else {
			new_string( name, value );
		}
	}
	
	return true;
}

bool
ScriptObj::load_value_name(ifstream & file, char* tag, char** _name )
{
	if ( strcmp( "SV_NAME", tag ) )
		return false;
	
	char *val = NULL;
	do {
		val = tvio_get_next_val( file );
		if ( val == NULL )
			return true;
		if ( !strcmp( val, "VALUE" ) )
		{
			*_name = strdup( tvio_get_value_as_string( file ) ) ;
			continue;
		}
	} while ( val != NULL );
	return true;
}

bool
ScriptObj::load_value_type(ifstream & file, char* tag, ScriptType *t )
{
	if ( strcmp( "SV_TYPE", tag ) )
		return false;
	
	char *val = NULL;
	char *_type = NULL;
	do {
		val = tvio_get_next_val( file );
		if ( val == NULL )
			break;
		if ( !strcmp( val, "VALUE" ) )
		{
			_type = strdup( tvio_get_value_as_string( file ) ) ;
			continue;
		}
	} while ( val != NULL );

	if ( !strcmp( _type, "ST_INT" ) ) 
		*t = ST_INT;
	else if( !strcmp( _type, "ST_FLOAT" ) )
		*t = ST_FLOAT;
	else if( !strcmp( _type, "ST_DOUBLE" ) )
		*t = ST_DOUBLE;
	else
		*t = ST_STRING;
	
	return true;
}


bool
ScriptObj::load_value_value(ifstream & file, char* tag, char** vali )
{
	if ( strcmp( "SV_VALUE", tag ) )
		return false;
	
	char *val = NULL;
	do {
		val = tvio_get_next_val( file );
		if ( val == NULL )

			return true;
		if ( !strcmp( val, "VALUE" ) )
		{
			*vali = strdup( tvio_get_value_as_string( file ) ) ;
			continue;
		}
	} while ( val != NULL );
}
		

void
ScriptObj::save_has_transform( ofstream & file )
{
	file << "HAS_TRAFO" << "{";
	file << "R=" << ( has_rotation ? 'Y' : 'N' );
	file << "L=" << ( has_location ? 'Y' : 'N' );
	file << "S=" << ( has_scale ? 'Y' : 'N' );
	file << "M=" << ( has_material ? 'Y' : 'N' );
	file << "E=" << ( has_editbutton ? 'Y' : 'N' );
	file << "} ";
}
bool
ScriptObj::load_has_transform( ifstream & file, char* tag )
{
	if ( strcmp( "HAS_TRAFO", tag ) ) 
		return false;
	
	char * val = (char*)malloc(32);;
	bool rot, loc, sca, mat, edi;
	rot = false;
	loc = false;
	sca = false;
	mat = false;
	edi = false;
	do{
		val = tvio_get_next_val( file );
		if ( val == NULL )
			break;
		
		if ( ! strcmp( val, "R" ) ) { rot = tvio_get_value_as_bool( file ); continue; }
		if ( ! strcmp( val, "L" ) ) { loc = tvio_get_value_as_bool( file ); continue; }
		if ( ! strcmp( val, "S" ) ) { sca = tvio_get_value_as_bool( file ); continue; }
		if ( ! strcmp( val, "M" ) ) { mat = tvio_get_value_as_bool( file ); continue; }
		if ( ! strcmp( val, "E" ) ) { edi = tvio_get_value_as_bool( file ); continue; }
	}while ( val != NULL );
	set_has_rotation( rot );
	set_has_location( loc );
	set_has_scale( sca );
	set_has_material( mat );
	set_has_editbutton( edi );
	return true;
}


bool
ScriptObj::load_triangles( ifstream & file, char* tag )
{
	if ( strcmp( "SOTRI", tag ) ) 
		return false;
	
	char * val = (char*)malloc(32);;
	float x1, y1, z1, x2, y2, z2, x3, y3, z3;
	x1 = 0.0; y1 = 0.0; z1 = 0.0;
	x2 = 0.0; y2 = 0.0; z2 = 0.0;
	x3 = 0.0; y3 = 0.0; z3 = 0.0;

	do{
		val = tvio_get_next_val( file );
		if ( val == NULL )
			break;
		
		if ( ! strcmp( val, "A" ) ) { x1 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "B" ) ) { y1 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "C" ) ) { z1 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "D" ) ) { x2 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "E" ) ) { y2 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "F" ) ) { z2 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "G" ) ) { x3 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "H" ) ) { y3 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "I" ) ) { z3 = tvio_get_value_as_float( file ); continue; }
	}while ( val != NULL );
	add_triangle(x1, y1, z1, x2, y2, z2, x3, y3, z3);
	return true;
}
void
ScriptObj::save_triangles( ofstream & file )
{
	GLTriangle *t;
	vector<GLTriangle*>::iterator itTriangle;
	for(itTriangle = triangle_list->begin(); itTriangle != triangle_list->end(); itTriangle++) {
		t = (GLTriangle*) *(itTriangle);
		file << "SOTRI" << "{";
		file << "A=" << t->x1 << " B=" << t->y1 << " C=" << t->z1;
		file << "D=" << t->x2 << " E=" << t->y2 << " F=" << t->z2;
		file << "G=" << t->x3 << " H=" << t->y3 << " I=" << t->z3;
		file << "} ";
	}
}

bool
ScriptObj::load_quads( ifstream & file, char* tag )
{
	if ( strcmp( "SOQUAD", tag ) )
		return false;
	
	char * val = (char*)malloc(32);
	float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4;
	x1 = 0.0; y1 = 0.0; z1 = 0.0;
	x2 = 0.0; y2 = 0.0; z2 = 0.0;
	x3 = 0.0; y3 = 0.0; z3 = 0.0;
	x4 = 0.0; y4 = 0.0; z4 = 0.0;
	
	do {
		val = tvio_get_next_val( file );
		if ( val == NULL )
			break;
		
		if ( ! strcmp( val, "A" ) ) { x1 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "B" ) ) { y1 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "C" ) ) { z1 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "D" ) ) { x2 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "E" ) ) { y2 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "F" ) ) { z2 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "G" ) ) { x3 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "H" ) ) { y3 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "I" ) ) { z3 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "J" ) ) { x4 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "K" ) ) { y4 = tvio_get_value_as_float( file ); continue; }
		if ( ! strcmp( val, "L" ) ) { z4 = tvio_get_value_as_float( file ); continue; }
	}while ( val != NULL );
	add_quad(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4);
	return true;
}
void
ScriptObj::save_quads( ofstream & file )
{
	GLQuad *q;
	vector<GLQuad*>::iterator itQuad;
	for(itQuad = quad_list->begin(); itQuad != quad_list->end(); itQuad++) {
		q = (GLQuad*) *(itQuad);
		file << "SOQUAD" << "{";
		file << "A=" << q->x1 << " B=" << q->y1 << " C=" << q->z1;
		file << "D=" << q->x2 << " E=" << q->y2 << " F=" << q->z2;
		file << "G=" << q->x3 << " H=" << q->y3 << " I=" << q->z3;
		file << "J=" << q->x4 << " K=" << q->y3 << " L=" << q->z3;
		file << "} ";
	}
}

void
ScriptObj::save_script_path( ofstream & file )
{
	if( this->get_script_path() == NULL )
		return;
	file << "SCRIPT_PATH" << "{";
	file << "VALUE=\"" << this->get_script_path() << "\"} ";
}

bool
ScriptObj::load_script_path( ifstream & file, char* tag )
{
	if ( strcmp( "SCRIPT_PATH", tag ) )
		return false;
	
	char * val = NULL;
	do {
		val = tvio_get_next_val( file );
		if ( val == NULL )
			return true;
		if ( !strcmp( val, "VALUE" ) )
		{
			this->set_script_path( strdup( tvio_get_value_as_string( file ) ) );
			continue;
		}
	} while ( val != NULL );
	return true;
}
