//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // density.cc // // Vincent LE PRINCE // 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/density.h" #include "include/dlgutils.h" #include "include/texpigment.h" #include "include/tvio.h" #include "include/matlist.h" #include "include/preferences.h" //************************************** // Définitions //************************************** const int dens_type_num = 4; const char *dens_type_list[dens_type_num] = { N_("Pattern"), N_("Density List"), N_("Color map"), N_("Density map") }; MapItem *mapedit_density_feeder_col( gpointer data ) { return (MapItem*)( new MapItem_color( 0, 0, ((PovTexDensity*)data)->app_ref ) ); } MapItem *mapedit_feeder_dens( gpointer data ) { return (MapItem*)( new MapItem_density( 0, 0, ((PovTexDensity*)data)->app_ref ) ); } int PovTexDensity::count=0; //************************************** // Constructeur //************************************** PovTexDensity::PovTexDensity( app_objs *appref, char *tagname, void (*asuicidal_func)(gpointer, gpointer), gpointer amother, bool is_top ) : MaterialItem( app_ref, tagname ) { num = ++count; char text[25]; sprintf( text, "Density %u", num ); set_name( text ); item_type = TV_MITEM_DENSITY; suicidal_func = asuicidal_func; mother = amother; is_mother = is_top; changing_box = NULL; changing_box2 = NULL; blockdens1 = blockdens2 = blockdens3 = NULL; blendmap = new TvWidget_blendmap( N_("Pattern"), "BMAP", NULL, app_ref ); blendmap_mod = NULL; blockpattern = NULL; map_editor = NULL; type = new TvWidget_option_combo( N_("Type"), "TYPE", NULL, app_ref ); type->set_list( dens_type_list, dens_type_num, 0 ); transformation = new TvWidget_transformation_rb( N_("Transformation"), "TRANSFO", NULL, app_ref ); noise = new TvWidget_noise_rb( N_("Noise"), "NOISE", NULL, app_ref ); warp = new TvWidget_warp_rb( N_("Warp"), "WARP", NULL, app_ref ); } void PovTexDensity::set_params( void (*asuicidal_func)(gpointer, gpointer), gpointer amother, bool is_top ) { suicidal_func = asuicidal_func; mother = amother; is_mother = is_top; } PovTexDensity::PovTexDensity( PovTexDensity & res ) : MaterialItem( res ) { num = ++count; //char text[25]; //sprintf( text, "Density %u", num ); //set_name( text ); set_name( res.name->value() ); item_type = TV_MITEM_DENSITY; //suicidal_func = *res.suicidal_func; //mother = *res.mother; //is_mother = *res.is_mother; is_mother = false; changing_box = NULL; changing_box2 = NULL; if ( res.blockdens1 != NULL ) blockdens1 = new PovTexDensity( *res.blockdens1 ); else blockdens1 = NULL; if ( res.blockdens2 != NULL ) blockdens2 = new PovTexDensity( *res.blockdens2 ); else blockdens2 = NULL; if ( res.blockdens3 != NULL ) blockdens3 = new PovTexDensity( *res.blockdens3 ); else blockdens3 = NULL; if ( res.blendmap != NULL ) blendmap = new TvWidget_blendmap( *res.blendmap ); else blendmap = NULL; if ( res.blendmap_mod != NULL ) blendmap_mod = new TvWidget_blendmap_mod( *res.blendmap_mod ); else blendmap_mod = NULL; if ( res.blockpattern != NULL ) blockpattern = new TvWidget_blockpattern( *res.blockpattern ); else blockpattern = NULL; if ( res.map_editor != NULL ) map_editor = new TvWidget_map_editor( *res.map_editor ); else map_editor = NULL; type = new TvWidget_option_combo( *res.type ); transformation = new TvWidget_transformation_rb( *res.transformation ); noise = new TvWidget_noise_rb( *res.noise ); warp = new TvWidget_warp_rb( *res.warp ); } PovTexDensity::~PovTexDensity() { delete type; delete transformation; delete noise; delete warp; if ( blockdens1 != NULL ) delete blockdens1; if ( blockdens2 != NULL ) delete blockdens2; if ( blockdens3 != NULL ) delete blockdens3; if ( blendmap != NULL ) { delete blendmap; delete blendmap_mod; } if ( blockpattern != NULL ) delete blockpattern; if ( map_editor != NULL ) delete map_editor; } // Add to tree void PovTexDensity::add_to_tree( GtkTreeView *view, GtkTreeStore *store, GtkTreeSelection *selection, GtkTreeIter *parent, GtkTreeIter *sibling ) { MaterialItem::add_to_tree( view, store, selection, parent, sibling ); if ( blockdens1 != NULL ) { //cout << "\nAdding block densities for " << name->value(); cout.flush(); blockdens1->add_to_tree( view, store, selection, &node_iter ); blockdens2->add_to_tree( view, store, selection, &node_iter ); if ( blockpattern->value() == 1 ) blockdens3->add_to_tree( view, store, selection, &node_iter ); } else { /*cout << " \nNo block density for " << name->value(); cout.flush();*/ } if ( map_editor != NULL ) map_editor->add_to_tree( view, store, selection, &node_iter ); set_node_state(); } void PovTexDensity::remove_from_tree() { if ( blockdens1 != NULL ) blockdens1->remove_from_tree(); if ( blockdens2 != NULL ) blockdens2->remove_from_tree(); if ( blockdens3 != NULL ) blockdens3->remove_from_tree(); MaterialItem::remove_from_tree(); } void PovTexDensity::save_node_state() { MaterialItem::save_node_state(); if ( blockdens1 != NULL ) blockdens1->save_node_state(); if ( blockdens2 != NULL ) blockdens2->save_node_state(); if ( blockdens3 != NULL ) blockdens3->save_node_state(); if ( map_editor != NULL ) map_editor->save_node_state(); } // Edit widget void PovTexDensity::edit_widget( GtkWidget *box ) { PREF_DEF bool tt = pref->tooltips->value(); MaterialItem::edit_widget( box, _("Density") ); vbox = gtk_vbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX(edit_cont), vbox, TRUE, TRUE, 0 ); type->get_widget( vbox, tt ); type->connect_signal( GTK_SIGNAL_FUNC(sign_density_type_changed), this ); if ( is_mother ) { GtkWidget *del_button = gtk_button_new_with_label( _("Delete this density") ); gtk_box_pack_start( GTK_BOX(vbox), del_button, FALSE, TRUE, 2 ); gtk_signal_connect( GTK_OBJECT(del_button), "clicked", GTK_SIGNAL_FUNC(sign_density_delete), this ); } set_changing_box(); gtk_widget_show_all( widget ); } void PovTexDensity::type_changed() { type->flush(); if ( type->value() != 2 ) { if ( blockdens1 != NULL ) { blockdens1->remove_from_tree(); delete blockdens1; } if ( blockdens2 != NULL ) { blockdens2->remove_from_tree(); delete blockdens2; } if ( blockdens3 != NULL ) { blockdens3->remove_from_tree(); delete blockdens3; } blockdens1 = blockdens2 = blockdens3 = NULL; } if ( blockdens1 == NULL && type->value() == 1 ) { blockdens1 = new PovTexDensity( app_ref, NULL, NULL, NULL, false ); blockdens2 = new PovTexDensity( app_ref, NULL, NULL, NULL, false ); blockdens3 = new PovTexDensity( app_ref, NULL, NULL, NULL, false ); blockdens1->add_to_tree( tree_view, tree_store, tree_selection, &node_iter ); blockdens2->add_to_tree( tree_view, tree_store, tree_selection, &node_iter ); } if ( blockpattern != NULL ) { delete blockpattern; blockpattern = NULL; } if ( blendmap != NULL ) { delete blendmap; blendmap = NULL; } if ( blendmap_mod != NULL && type->value() != 2 && type->value() != 3 ) { delete blendmap_mod; blendmap_mod = NULL; } if ( map_editor != NULL ) { map_editor->remove_from_tree(); delete map_editor; map_editor = NULL; } set_changing_box(); } void PovTexDensity::set_changing_box() { bool tt = true; // Changing box 1 if ( changing_box != NULL ) gtk_widget_destroy( changing_box ); changing_box = gtk_vbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX(vbox), changing_box, FALSE, FALSE, 0 ); switch ( type->value() ) { case 0: if ( blendmap == NULL ) blendmap = new TvWidget_blendmap( _("Pattern"), "BMAP", NULL, app_ref ); blendmap->get_widget( changing_box, tt ); break; case 1: { if ( blockpattern == NULL ) blockpattern = new TvWidget_blockpattern( _("Block Pattern"), "BLKPAT", NULL, app_ref ); blockpattern->get_widget( changing_box, tt ); blockpattern->connect_signal( sign_density_densblocktype_changed, this ); set_densblock_items(); } break; case 2: { if ( blendmap == NULL ) blendmap = new TvWidget_blendmap( _("Map definition"), "BMAP", NULL, app_ref, true ); blendmap->get_widget( changing_box, tt ); if ( map_editor == NULL ) { map_editor = new TvWidget_map_editor( _("Map editor"), "MAPEDIT", NULL, app_ref, mapedit_density_feeder_col, this ); MapItem_color *col = new MapItem_color( 0.0, 0, app_ref ); map_editor->add( col ); col = new MapItem_color( 1.0, 255, app_ref ); map_editor->add( col ); } map_editor->get_widget( changing_box, tt ); } break; case 3: { if ( blendmap == NULL ) blendmap = new TvWidget_blendmap( _("Map definition"), "BMAP", NULL, app_ref ); blendmap->get_widget( changing_box, tt ); if ( map_editor == NULL ) { map_editor = new TvWidget_map_editor( _("Map editor"), "MAPEDIT", NULL, app_ref, mapedit_feeder_dens, this ); MapItem_density *dens = new MapItem_density( 0.0, 0, app_ref ); map_editor->add( dens ); dens = new MapItem_density( 1.0, 255, app_ref ); map_editor->add( dens ); map_editor->add_to_tree( tree_view, tree_store, tree_selection, &node_iter ); } map_editor->get_widget( changing_box, tt ); } break; } // Changing box 2 if ( changing_box2 != NULL ) gtk_widget_destroy( changing_box2 ); changing_box2 = gtk_vbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX(vbox), changing_box2, FALSE, FALSE, 0 ); if ( type->value() == 2 || type->value() == 3 ) { if ( blendmap_mod == NULL ) blendmap_mod = new TvWidget_blendmap_mod( _("Map modifiers"), "BMAPMOD", NULL, app_ref ); blendmap_mod->get_widget( changing_box2, tt ); } transformation->get_widget_rb( changing_box2, tt ); noise->get_widget_rb( changing_box2, tt ); warp->get_widget_rb( changing_box2, tt ); gtk_widget_show_all( changing_box ); gtk_widget_show_all( changing_box2 ); } void PovTexDensity::set_densblock_items() { if ( blockdens3 == NULL ) return; blockpattern->flush(); if ( blockpattern->value() == 2 ) blockdens3->add_to_tree( tree_view, tree_store, tree_selection, &node_iter ); else blockdens3->remove_from_tree(); } void PovTexDensity::destroy_widget() { MaterialItem::destroy_widget(); changing_box = NULL; changing_box2 = NULL; type->clear_widget(); transformation->clear_widget(); noise->clear_widget(); warp->clear_widget(); if ( blendmap != NULL ) blendmap->clear_widget(); if ( blendmap_mod != NULL ) blendmap_mod->clear_widget(); if ( blockpattern != NULL ) blockpattern->clear_widget(); if ( map_editor != NULL ) map_editor->clear_widget(); } void PovTexDensity::flush() { type->flush(); transformation->flush(); noise->flush(); warp->flush(); if ( blendmap != NULL ) blendmap->flush(); if ( blendmap_mod != NULL ) blendmap_mod->flush(); if ( blockpattern != NULL ) blockpattern->flush(); if ( map_editor != NULL ) map_editor->flush(); } void PovTexDensity::output_to_povray( ofstream & file, bool inmap ) { if ( !inmap ) file << "\n\t\t\tdensity {\n\t\t\t\t"; switch ( type->value() ) { case 0: blendmap->output_to_povray( file ); break; case 1: blockpattern->output_to_povray( file ); file << "\n\t\t\t\t"; blockdens1->output_to_povray( file ); file << ",\n\t\t\t\t"; blockdens2->output_to_povray( file ); if ( blockpattern->value() == 2 ) { file << ",\n\t\t\t\t"; blockdens3->output_to_povray( file ); } blockpattern->output_to_povray_options( file ); break; case 2: blendmap->output_to_povray( file ); file << "\n\t\t\tcolor_map {"; map_editor->output_to_povray( file ); file << "\n\t\t\t}\n\t\t\t"; if ( blendmap_mod != NULL ) blendmap_mod->output_to_povray( file ); break; case 3: blendmap->output_to_povray( file ); file << "\n\t\t\tdensity_map {"; map_editor->output_to_povray( file ); file << "\n\t\t\t}\n\t\t\t"; if ( blendmap_mod != NULL ) blendmap_mod->output_to_povray( file ); break; } file << "\n\t\t\t\t"; noise->output_to_povray( file ); warp->output_to_povray( file ); transformation->output_to_povray( file ); if ( !inmap ) file << "\n\t\t\t}"; } void PovTexDensity::save( ofstream & file ) { file << "DENSITY{ "; name->save( file ); expand->save( file ); type->save( file ); switch ( type->value() ) { case 0: blendmap->save( file ); break; case 1: blockpattern->save( file ); blockdens1->save( file ); blockdens2->save( file ); if ( blockpattern->value() == 2 ) blockdens3->save( file ); break; case 2: blendmap->save( file ); map_editor->save( file ); if ( blendmap_mod != NULL ) blendmap_mod->save( file ); break; case 3: blendmap->save( file ); map_editor->save( file ); if ( blendmap_mod != NULL ) blendmap_mod->save( file ); break; } noise->save( file ); warp->save( file ); transformation->save( file ); file << "}\n"; } //********************************************** // Load //********************************************** bool PovTexDensity::load( ifstream & file, char * ltag ) { if ( strcmp( "DENSITY", ltag ) ) return false; char * tag = NULL; do { tag = tvio_get_next_tag( file ); if ( tag == NULL ) break; if (name->load( file , tag ) ) continue; if (expand->load( file , tag ) ) continue; if (type->load( file , tag ) ) continue; if (noise->load( file , tag ) ) continue; if (warp->load( file , tag ) ) continue; if (transformation->load( file , tag ) ) continue; if ( !strcmp( tag, "BMAP" ) ) { if ( blendmap == NULL ) blendmap = new TvWidget_blendmap( _("Pattern"), "BMAP", NULL, app_ref ); blendmap->load( file, tag ); continue; } if ( !strcmp( tag, "BMAPMOD" ) ) { if ( blendmap_mod == NULL ) blendmap_mod = new TvWidget_blendmap_mod( _("Pattern"), "BMAPMOD", NULL, app_ref ); blendmap_mod->load( file, tag ); continue; } if ( !strcmp( tag, "BLKPAT" ) ) { if ( blockpattern == NULL ) blockpattern = new TvWidget_blockpattern( _("Block Pattern"), "BLKPAT", NULL, app_ref ); blockpattern->load( file, tag ); continue; } if ( !strcmp( tag, "DENSITY" ) ) { if ( blockdens1 == NULL ) { blockdens1 = new PovTexDensity( app_ref, NULL, NULL, NULL, false ); blockdens1->load( file, tag ); continue; } if ( blockdens2 == NULL ) { blockdens2 = new PovTexDensity( app_ref, NULL, NULL, NULL, false ); blockdens2->load( file, tag ); continue; } if ( blockdens3 == NULL ) { blockdens3 = new PovTexDensity( app_ref, NULL, NULL, NULL, false ); blockdens3->load( file, tag ); continue; } tvio_skip_section( file ); } if ( !strcmp( tag, "MAPEDIT" ) ) { if ( type->value() == 3 ) map_editor = new TvWidget_map_editor( _("Map editor"), "MAPEDIT", NULL, app_ref, mapedit_feeder_dens, this ); else map_editor = new TvWidget_map_editor( _("Map editor"), "MAPEDIT", NULL, app_ref, mapedit_density_feeder_col, this ); map_editor->load( file, tag ); continue; } tvio_skip_section( file ); } while( tag != NULL ); return true; } bool PovTexDensity::paste( MaterialItem *item ) { if ( item->get_type() != TV_MITEM_DENSITY ) return false; set_name( item->get_name() ); PovTexDensity *dens = (PovTexDensity*)item; if ( blockdens1 != NULL ) { delete blockdens1; blockdens1 = NULL; } if ( blockdens2 != NULL ) { delete blockdens2; blockdens2 = NULL; } if ( blockdens3 != NULL ) { delete blockdens3; blockdens3 = NULL; } if ( blendmap != NULL ) { delete blendmap; blendmap = NULL; } if ( blendmap_mod != NULL ) { delete blendmap_mod; blendmap_mod = NULL; } if ( blockpattern != NULL ) { delete blockpattern; blockpattern = NULL; } if ( map_editor != NULL ) { delete map_editor; map_editor = NULL; } if ( GTK_IS_WIDGET(widget) ) { gtk_widget_destroy( edit_cont ); type->clear_widget(); transformation->clear_widget(); noise->clear_widget(); warp->clear_widget(); } type->copy( dens->type ); transformation->copy( dens->transformation ); noise->copy( dens->noise ); warp->copy( dens->warp ); if ( dens->blockdens1 != NULL ) blockdens1 = new PovTexDensity( *dens->blockdens1 ); else blockdens1 = NULL; if ( dens->blockdens2 != NULL ) blockdens2 = new PovTexDensity( *dens->blockdens2 ); else blockdens2 = NULL; if ( dens->blockdens3 != NULL ) blockdens3 = new PovTexDensity( *dens->blockdens3 ); else blockdens3 = NULL; if ( dens->blendmap != NULL ) blendmap = new TvWidget_blendmap( *dens->blendmap ); if ( dens->blendmap_mod != NULL ) blendmap_mod = new TvWidget_blendmap_mod( *dens->blendmap_mod ); if ( dens->blockpattern != NULL ) blockpattern = new TvWidget_blockpattern( *dens->blockpattern ); if ( dens->map_editor != NULL ) map_editor = new TvWidget_map_editor( *dens->map_editor ); GtkTreeIter *old_node = gtk_tree_iter_copy( &(dens->node_iter) ); add_to_tree( tree_view, tree_store, tree_selection, tree_node_parent, old_node ); gtk_tree_selection_unselect_iter( tree_selection, &node_iter ); select_tree_row(); gtk_tree_iter_free( old_node ); return true; } //********************************************** // Map Item Density //********************************************** int MapItem_density::obj_count = 1; MapItem_density::MapItem_density( float val, guint8 c, app_objs *appref ) : MapItem( _("Density"), val ) { color[0]=color[1]=color[2]=c; color[3]=255; density = new PovTexDensity( appref, NULL, NULL, NULL, false ); char text[25]; sprintf( text, "Map density #%u", obj_count++ ); density->set_name( text ); } MapItem_density::MapItem_density( MapItem_density & res ) : MapItem( res ) { color[0]=color[1]=color[2]=res.color[0]; color[3]=255; density = new PovTexDensity( *res.density ); //char text[25]; //sprintf( text, "Map density #%u", obj_count++ ); //density->set_name( text ); density->set_name( res.density->get_name() ); } void MapItem_density::save( ofstream & file ) { MapItem::save( file ); density->save( file ); file << "} "; } bool MapItem_density::load( ifstream & file, char *ltag ) { if ( strcmp( "MAPITEM", ltag ) ) return false; char * tag = NULL; do { tag = tvio_get_next_tag( file ); if ( tag == NULL ) break; if ( density->load( file , tag ) ) continue; if ( MapItem::load( file , tag ) ) continue; tvio_skip_section( file ); } while( tag != NULL ); return true; }