Beispiel #1
0
static rc_t write_statistic( statistic_writer *writer, statistic *data,
                             uint64_t * written, bool show_progress )
{
    writer_ctx ctx;
    uint64_t count;

    ctx.writer = writer;
    ctx.rc = 0;
    ctx.progress = NULL;

    if ( show_progress )
    {
        make_progressbar( &ctx.progress );
        ctx.entries = data->entries;
        ctx.fract_digits = progressbar_calc_fract_digits( ctx.entries );
        ctx.n = 0;
    }

    count = foreach_statistic( data, write_cb, &ctx );

    if ( show_progress )
    {
        destroy_progressbar( ctx.progress );
        OUTMSG(( "\n" ));
    }

    if ( written != NULL ) *written = count;

    return ctx.rc;
}
Beispiel #2
0
static rc_t cg_dump_setup_progressbar( cg_dump_ctx * cg_ctx )
{
    rc_t rc = make_progressbar( &cg_ctx->progress );
    if ( rc == 0 )
    {
        uint64_t count;
        const num_gen_iter * iter;
        cg_ctx->fract_digits = 0;
        rc = num_gen_iterator_make( cg_ctx->rows, &iter );
        if ( rc == 0 )
        {
            if ( num_gen_iterator_count( iter, &count ) == 0 )
            {
                if ( count > 10000 )
                {
                    if ( count > 100000 )
                        cg_ctx->fract_digits = 2;
                    else
                        cg_ctx->fract_digits = 1;
                }
            }
            num_gen_iterator_destroy( iter );
        }
    }
    return rc;
}
Beispiel #3
0
static void ShellDeleteMsg(const string& Name, DEL_MODE Mode, int Percent, int WipePercent, ConsoleTitle* DeleteTitle)
{
	string strProgress, strWipeProgress;
	size_t Width=ScrX/2;
	if(Mode==DEL_WIPEPROCESS || Mode==DEL_WIPE)
	{
		strWipeProgress = make_progressbar(Width, WipePercent, true, Percent == -1);
	}

	if (Mode!=DEL_SCAN && Percent!=-1)
	{
		strProgress = make_progressbar(Width, Percent, true, true);
		*DeleteTitle << L"{" << Percent << L"%} " << MSG((Mode==DEL_WIPE || Mode==DEL_WIPEPROCESS)?MDeleteWipeTitle:MDeleteTitle) << fmt::Flush();
	}

	string strOutFileName(Name);
	TruncPathStr(strOutFileName,static_cast<int>(Width));
	CenterStr(strOutFileName,strOutFileName,static_cast<int>(Width));
	const wchar_t* Progress1 = nullptr;
	const wchar_t* Progress2 = nullptr;
	if(!strWipeProgress.empty())
	{
		Progress1 = strWipeProgress.data();
		Progress2 = strProgress.empty()? nullptr : strProgress.data();
	}
	else
	{
		Progress1 = strProgress.empty()? nullptr : strProgress.data();
	}
	Message(0,0,
		MSG((Mode==DEL_WIPE || Mode==DEL_WIPEPROCESS)?MDeleteWipeTitle:MDeleteTitle),
		Mode==DEL_SCAN? MSG(MScanningFolder) : MSG((Mode==DEL_WIPE || Mode==DEL_WIPEPROCESS)?MDeletingWiping:MDeleting),
		strOutFileName.data(), Progress1, Progress2);

	if (!PreRedrawStack().empty())
	{
		auto item = dynamic_cast<DelPreRedrawItem*>(PreRedrawStack().top());
		item->name = Name;
		item->Title = DeleteTitle;
		item->Mode = Mode;
		item->Percent = Percent;
		item->WipePercent = WipePercent;
	}
}
Beispiel #4
0
rc_t write_output_file( KDirectory *dir, statistic * data,
                        const char * path, uint64_t * written )
{
    write_ctx wctx;
    rc_t rc;

    if ( written != NULL )
    {
        *written = 0;
    }
    wctx.out = NULL;
    wctx.pos = 0;
    wctx.lines = 0;
    rc = KDirectoryCreateFile ( dir, &wctx.out, false, 0664, kcmInit, path );
    if ( rc != 0 )
        LogErr( klogInt, rc, "KDirectoryCreateFile() failed\n" );
    else
    {
        char buffer[ 256 ];
        size_t num_writ;
        rc = string_printf ( buffer, sizeof buffer, &num_writ,
          "SPOTGROUP\tCYCLE\tNRead\tDIMER\tGC_CONTENT\tHP_RUN\tMaxQ\tQuality\tTOTAL\tMISMATCH\n" );
        if ( rc == 0 )
        {
            size_t f_writ;
            rc = KFileWrite ( wctx.out, wctx.pos, buffer, num_writ, &f_writ );
            if ( rc == 0 )
            {
                if ( written != NULL ) *written = f_writ;
                wctx.pos += f_writ;

                make_progressbar( &wctx.progress );
                wctx.entries = data->entries;
                wctx.fract_digits = progressbar_calc_fract_digits( wctx.entries );

                foreach_statistic( data, write_to_file_cb, &wctx );

                destroy_progressbar( wctx.progress );
                OUTMSG(( "\n" ));

                KFileRelease ( wctx.out );
                if ( written != NULL )
                {
                    *written = wctx.lines;
                }
            }
        }
    }
    return rc;
}
Beispiel #5
0
static rc_t CC bg_progress_thread_func( const KThread *self, void *data )
{
    rc_t rc = 0;
    bg_progress * bgp = data;
    if ( bgp != NULL )
    {
        rc = make_progressbar( & bgp -> progressbar, bgp -> digits );
        if ( rc == 0 )
        {
            bgp -> cur = 0;
            update_progressbar( bgp -> progressbar, bgp -> cur );
            while ( atomic_read( &bgp -> done ) == 0 )
            {
                bg_progress_steps( bgp );
                KSleepMs( bgp -> sleep_time );
            }
            
            bg_progress_steps( bgp );
            destroy_progressbar( bgp -> progressbar );
        }
    }
    return rc;
}
static rc_t read_loop( statistic * data,
                       context *ctx,
                       statistic_reader *reader,
                       const VCursor *my_cursor )
{
    int64_t first;
    uint64_t count;
    rc_t rc = query_reader_rowrange( reader, &first, &count );
    if ( rc != 0 )
        LogErr( klogInt, rc, "query_statistic_rowrange() failed\n" );
    else
    {
        if ( num_gen_empty( ctx->row_generator ) )
        {
            rc = num_gen_add( ctx->row_generator, first, count );
            if ( rc != 0 )
                LogErr( klogInt, rc, "num_gen_add() failed() failed\n" );
        }
        else
        {
            rc = num_gen_trim( ctx->row_generator, first, count );
            if ( rc != 0 )
                LogErr( klogInt, rc, "num_gen_trim() failed() failed\n" );
        }

        if ( rc == 0 )
        {
            const num_gen_iter *iter;
            rc = num_gen_iterator_make( ctx->row_generator, &iter );
            if ( rc != 0 )
                LogErr( klogInt, rc, "num_gen_iterator_make() failed\n" );
            else
            {
                uint64_t row_id;
                progressbar * progress;

                rc = make_progressbar( &progress );
                if ( rc != 0 )
                    LogErr( klogInt, rc, "make_progressbar() failed\n" );
                else
                {
                    uint8_t fract_digits = calc_fract_digits( iter );
                    uint32_t percent;
                    row_input row_data;

                    while ( ( num_gen_iterator_next( iter, &row_id ) == 0 )&&
                            ( rc == 0 ) )
                    {
                        rc = Quitting();
                        if ( rc == 0 )
                        {
                            /* ******************************************** */
                            rc = reader_get_data( reader, &row_data, row_id );
                            if ( rc == 0 )
                            {
                                rc = extract_statistic_from_row( data, &row_data, row_id );
                            }
                            /* ******************************************** */
                            if ( ctx->show_progress )
                                if ( num_gen_iterator_percent( iter, fract_digits, &percent ) == 0 )
                                    update_progressbar( progress, fract_digits, percent );
                        }
                    }
                    destroy_progressbar( progress );
                    if ( ctx->show_progress )
                        OUTMSG(( "\n" ));
                }
                num_gen_iterator_destroy( iter );
            }
        }
    }
    return rc;
}
Beispiel #7
0
bool generate_image(std::string part_of_name, video::IImage *& baseimg,
		IrrlichtDevice *device)
{
	video::IVideoDriver* driver = device->getVideoDriver();
	assert(driver);

	// Stuff starting with [ are special commands
	if(part_of_name[0] != '[')
	{
		// A normal texture; load it from a file
		std::string path = getTexturePath(part_of_name.c_str());
		/*infostream<<"generate_image(): Loading path \""<<path
				<<"\""<<std::endl;*/
		
		video::IImage *image = driver->createImageFromFile(path.c_str());

		if(image == NULL)
		{
			infostream<<"generate_image(): Could not load image \""
                    <<part_of_name<<"\" from path \""<<path<<"\""
					<<" while building texture"<<std::endl;

			//return false;

			infostream<<"generate_image(): Creating a dummy"
                    <<" image for \""<<part_of_name<<"\""<<std::endl;

			// Just create a dummy image
			//core::dimension2d<u32> dim(2,2);
			core::dimension2d<u32> dim(1,1);
			image = driver->createImage(video::ECF_A8R8G8B8, dim);
			assert(image);
			/*image->setPixel(0,0, video::SColor(255,255,0,0));
			image->setPixel(1,0, video::SColor(255,0,255,0));
			image->setPixel(0,1, video::SColor(255,0,0,255));
			image->setPixel(1,1, video::SColor(255,255,0,255));*/
			image->setPixel(0,0, video::SColor(255,myrand()%256,
					myrand()%256,myrand()%256));
			/*image->setPixel(1,0, video::SColor(255,myrand()%256,
					myrand()%256,myrand()%256));
			image->setPixel(0,1, video::SColor(255,myrand()%256,
					myrand()%256,myrand()%256));
			image->setPixel(1,1, video::SColor(255,myrand()%256,
					myrand()%256,myrand()%256));*/
		}

		// If base image is NULL, load as base.
		if(baseimg == NULL)
		{
			//infostream<<"Setting "<<part_of_name<<" as base"<<std::endl;
			/*
				Copy it this way to get an alpha channel.
				Otherwise images with alpha cannot be blitted on 
				images that don't have alpha in the original file.
			*/
			core::dimension2d<u32> dim = image->getDimension();
			baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
			image->copyTo(baseimg);
			image->drop();
		}
		// Else blit on base.
		else
		{
			//infostream<<"Blitting "<<part_of_name<<" on base"<<std::endl;
			// Size of the copied area
			core::dimension2d<u32> dim = image->getDimension();
			//core::dimension2d<u32> dim(16,16);
			// Position to copy the blitted to in the base image
			core::position2d<s32> pos_to(0,0);
			// Position to copy the blitted from in the blitted image
			core::position2d<s32> pos_from(0,0);
			// Blit
			image->copyToWithAlpha(baseimg, pos_to,
					core::rect<s32>(pos_from, dim),
					video::SColor(255,255,255,255),
					NULL);
			// Drop image
			image->drop();
		}
	}
	else
	{
		// A special texture modification

		infostream<<"generate_image(): generating special "
				<<"modification \""<<part_of_name<<"\""
				<<std::endl;
		
		/*
			This is the simplest of all; it just adds stuff to the
			name so that a separate texture is created.

			It is used to make textures for stuff that doesn't want
			to implement getting the texture from a bigger texture
			atlas.
		*/
		if(part_of_name == "[forcesingle")
		{
		}
		/*
			[crackN
			Adds a cracking texture
		*/
		else if(part_of_name.substr(0,6) == "[crack")
		{
			if(baseimg == NULL)
			{
				infostream<<"generate_image(): baseimg==NULL "
						<<"for part_of_name=\""<<part_of_name
						<<"\", cancelling."<<std::endl;
				return false;
			}
			
			// Crack image number
			u16 progression = stoi(part_of_name.substr(6));

			// Size of the base image
			core::dimension2d<u32> dim_base = baseimg->getDimension();
			
			/*
				Load crack image.

				It is an image with a number of cracking stages
				horizontally tiled.
			*/
			video::IImage *img_crack = driver->createImageFromFile(
					getTexturePath("crack.png").c_str());
		
			if(img_crack)
			{
				// Dimension of original image
				core::dimension2d<u32> dim_crack
						= img_crack->getDimension();
				// Count of crack stages
				u32 crack_count = dim_crack.Height / dim_crack.Width;
				// Limit progression
				if(progression > crack_count-1)
					progression = crack_count-1;
				// Dimension of a single scaled crack stage
				core::dimension2d<u32> dim_crack_scaled_single(
					dim_base.Width,
					dim_base.Height
				);
				// Dimension of scaled size
				core::dimension2d<u32> dim_crack_scaled(
					dim_crack_scaled_single.Width,
					dim_crack_scaled_single.Height * crack_count
				);
				// Create scaled crack image
				video::IImage *img_crack_scaled = driver->createImage(
						video::ECF_A8R8G8B8, dim_crack_scaled);
				if(img_crack_scaled)
				{
					// Scale crack image by copying
					img_crack->copyToScaling(img_crack_scaled);
					
					// Position to copy the crack from
					core::position2d<s32> pos_crack_scaled(
						0,
						dim_crack_scaled_single.Height * progression
					);
					
					// This tiling does nothing currently but is useful
					for(u32 y0=0; y0<dim_base.Height
							/ dim_crack_scaled_single.Height; y0++)
					for(u32 x0=0; x0<dim_base.Width
							/ dim_crack_scaled_single.Width; x0++)
					{
						// Position to copy the crack to in the base image
						core::position2d<s32> pos_base(
							x0*dim_crack_scaled_single.Width,
							y0*dim_crack_scaled_single.Height
						);
						// Rectangle to copy the crack from on the scaled image
						core::rect<s32> rect_crack_scaled(
							pos_crack_scaled,
							dim_crack_scaled_single
						);
						// Copy it
						img_crack_scaled->copyToWithAlpha(baseimg, pos_base,
								rect_crack_scaled,
								video::SColor(255,255,255,255),
								NULL);
					}

					img_crack_scaled->drop();
				}
				
				img_crack->drop();
			}
		}
		/*
			[combine:WxH:X,Y=filename:X,Y=filename2
			Creates a bigger texture from an amount of smaller ones
		*/
		else if(part_of_name.substr(0,8) == "[combine")
		{
			Strfnd sf(part_of_name);
			sf.next(":");
			u32 w0 = stoi(sf.next("x"));
			u32 h0 = stoi(sf.next(":"));
			infostream<<"combined w="<<w0<<" h="<<h0<<std::endl;
			core::dimension2d<u32> dim(w0,h0);
			baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
			while(sf.atend() == false)
			{
				u32 x = stoi(sf.next(","));
				u32 y = stoi(sf.next("="));
				std::string filename = sf.next(":");
				infostream<<"Adding \""<<filename
						<<"\" to combined ("<<x<<","<<y<<")"
						<<std::endl;
				video::IImage *img = driver->createImageFromFile(
						getTexturePath(filename.c_str()).c_str());
				if(img)
				{
					core::dimension2d<u32> dim = img->getDimension();
					infostream<<"Size "<<dim.Width
							<<"x"<<dim.Height<<std::endl;
					core::position2d<s32> pos_base(x, y);
					video::IImage *img2 =
							driver->createImage(video::ECF_A8R8G8B8, dim);
					img->copyTo(img2);
					img->drop();
					img2->copyToWithAlpha(baseimg, pos_base,
							core::rect<s32>(v2s32(0,0), dim),
							video::SColor(255,255,255,255),
							NULL);
					img2->drop();
				}
				else
				{
					infostream<<"img==NULL"<<std::endl;
				}
			}
		}
		/*
			[progressbarN
			Adds a progress bar, 0.0 <= N <= 1.0
		*/
		else if(part_of_name.substr(0,12) == "[progressbar")
		{
			if(baseimg == NULL)
			{
				infostream<<"generate_image(): baseimg==NULL "
						<<"for part_of_name=\""<<part_of_name
						<<"\", cancelling."<<std::endl;
				return false;
			}

			float value = stof(part_of_name.substr(12));
			make_progressbar(value, baseimg);
		}
		/*
			"[noalpha:filename.png"
			Use an image without it's alpha channel.
			Used for the leaves texture when in old leaves mode, so
			that the transparent parts don't look completely black 
			when simple alpha channel is used for rendering.
		*/
		else if(part_of_name.substr(0,8) == "[noalpha")
		{
			if(baseimg != NULL)
			{
				infostream<<"generate_image(): baseimg!=NULL "
						<<"for part_of_name=\""<<part_of_name
						<<"\", cancelling."<<std::endl;
				return false;
			}

			std::string filename = part_of_name.substr(9);

			std::string path = getTexturePath(filename.c_str());

			infostream<<"generate_image(): Loading path \""<<path
					<<"\""<<std::endl;
			
			video::IImage *image = driver->createImageFromFile(path.c_str());
			
			if(image == NULL)
			{
				infostream<<"generate_image(): Loading path \""
						<<path<<"\" failed"<<std::endl;
			}
			else
			{
				core::dimension2d<u32> dim = image->getDimension();
				baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
				
				// Set alpha to full
				for(u32 y=0; y<dim.Height; y++)
				for(u32 x=0; x<dim.Width; x++)
				{
					video::SColor c = image->getPixel(x,y);
					c.setAlpha(255);
					image->setPixel(x,y,c);
				}
				// Blit
				image->copyTo(baseimg);

				image->drop();
			}
		}
		/*
			"[makealpha:R,G,B:filename.png"
			Use an image with converting one color to transparent.
		*/
		else if(part_of_name.substr(0,11) == "[makealpha:")
		{
			if(baseimg != NULL)
			{
				infostream<<"generate_image(): baseimg!=NULL "
						<<"for part_of_name=\""<<part_of_name
						<<"\", cancelling."<<std::endl;
				return false;
			}

			Strfnd sf(part_of_name.substr(11));
			u32 r1 = stoi(sf.next(","));
			u32 g1 = stoi(sf.next(","));
			u32 b1 = stoi(sf.next(":"));
			std::string filename = sf.next("");

			std::string path = getTexturePath(filename.c_str());

			infostream<<"generate_image(): Loading path \""<<path
					<<"\""<<std::endl;
			
			video::IImage *image = driver->createImageFromFile(path.c_str());
			
			if(image == NULL)
			{
				infostream<<"generate_image(): Loading path \""
						<<path<<"\" failed"<<std::endl;
			}
			else
			{
				core::dimension2d<u32> dim = image->getDimension();
				baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
				
				for(u32 y=0; y<dim.Height; y++)
				for(u32 x=0; x<dim.Width; x++)
				{
					video::SColor c = image->getPixel(x,y);
					u32 r = c.getRed();
					u32 g = c.getGreen();
					u32 b = c.getBlue();
					if(!(r == r1 && g == g1 && b == b1))
						continue;
					c.setAlpha(0);
					image->setPixel(x,y,c);
				}
				// Blit
				image->copyTo(baseimg);

				image->drop();
			}
		}
		/*
			"[makealpha2:R,G,B;R2,G2,B2:filename.png"
			Use an image with converting two colors to transparent.
		*/
		else if(part_of_name.substr(0,12) == "[makealpha2:")
		{
			if(baseimg != NULL)
			{
				infostream<<"generate_image(): baseimg!=NULL "
						<<"for part_of_name=\""<<part_of_name
						<<"\", cancelling."<<std::endl;
				return false;
			}

			Strfnd sf(part_of_name.substr(12));
			u32 r1 = stoi(sf.next(","));
			u32 g1 = stoi(sf.next(","));
			u32 b1 = stoi(sf.next(";"));
			u32 r2 = stoi(sf.next(","));
			u32 g2 = stoi(sf.next(","));
			u32 b2 = stoi(sf.next(":"));
			std::string filename = sf.next("");

			std::string path = getTexturePath(filename.c_str());

			infostream<<"generate_image(): Loading path \""<<path
					<<"\""<<std::endl;
			
			video::IImage *image = driver->createImageFromFile(path.c_str());
			
			if(image == NULL)
			{
				infostream<<"generate_image(): Loading path \""
						<<path<<"\" failed"<<std::endl;
			}
			else
			{
				core::dimension2d<u32> dim = image->getDimension();
				baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
				
				for(u32 y=0; y<dim.Height; y++)
				for(u32 x=0; x<dim.Width; x++)
				{
					video::SColor c = image->getPixel(x,y);
					u32 r = c.getRed();
					u32 g = c.getGreen();
					u32 b = c.getBlue();
					if(!(r == r1 && g == g1 && b == b1) &&
					   !(r == r2 && g == g2 && b == b2))
						continue;
					c.setAlpha(0);
					image->setPixel(x,y,c);
				}
				// Blit
				image->copyTo(baseimg);

				image->drop();
			}
		}
		/*
			[inventorycube{topimage{leftimage{rightimage
			In every subimage, replace ^ with &.
			Create an "inventory cube".
			NOTE: This should be used only on its own.
			Example (a grass block (not actually used in game):
			"[inventorycube{grass.png{mud.png&grass_side.png{mud.png&grass_side.png"
		*/
		else if(part_of_name.substr(0,14) == "[inventorycube")
		{
			if(baseimg != NULL)
			{
				infostream<<"generate_image(): baseimg!=NULL "
						<<"for part_of_name=\""<<part_of_name
						<<"\", cancelling."<<std::endl;
				return false;
			}

			str_replace_char(part_of_name, '&', '^');
			Strfnd sf(part_of_name);
			sf.next("{");
			std::string imagename_top = sf.next("{");
			std::string imagename_left = sf.next("{");
			std::string imagename_right = sf.next("{");

#if 1
			//TODO

			if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
			{
				infostream<<"generate_image(): EVDF_RENDER_TO_TARGET"
						" not supported. Creating fallback image"<<std::endl;
				baseimg = generate_image_from_scratch(
						imagename_top, device);
				return true;
			}
			
			u32 w0 = 64;
			u32 h0 = 64;
			//infostream<<"inventorycube w="<<w0<<" h="<<h0<<std::endl;
			core::dimension2d<u32> dim(w0,h0);
			
			// Generate images for the faces of the cube
			video::IImage *img_top = generate_image_from_scratch(
					imagename_top, device);
			video::IImage *img_left = generate_image_from_scratch(
					imagename_left, device);
			video::IImage *img_right = generate_image_from_scratch(
					imagename_right, device);
			assert(img_top && img_left && img_right);

			// TODO: Create textures from images
			video::ITexture *texture_top = driver->addTexture(
					(imagename_top + "__temp__").c_str(), img_top);
			assert(texture_top);
			
			// Drop images
			img_top->drop();
			img_left->drop();
			img_right->drop();
			
			// Create render target texture
			video::ITexture *rtt = NULL;
			std::string rtt_name = part_of_name + "_RTT";
			rtt = driver->addRenderTargetTexture(dim, rtt_name.c_str(),
					video::ECF_A8R8G8B8);
			assert(rtt);
			
			// Set render target
			driver->setRenderTarget(rtt, true, true,
					video::SColor(0,0,0,0));
			
			// Get a scene manager
			scene::ISceneManager *smgr_main = device->getSceneManager();
			assert(smgr_main);
			scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
			assert(smgr);
			
			/*
				Create scene:
				- An unit cube is centered at 0,0,0
				- Camera looks at cube from Y+, Z- towards Y-, Z+
				NOTE: Cube has to be changed to something else because
				the textures cannot be set individually (or can they?)
			*/

			scene::ISceneNode* cube = smgr->addCubeSceneNode(1.0, NULL, -1,
					v3f(0,0,0), v3f(0, 45, 0));
			// Set texture of cube
			cube->setMaterialTexture(0, texture_top);
			//cube->setMaterialFlag(video::EMF_LIGHTING, false);
			cube->setMaterialFlag(video::EMF_ANTI_ALIASING, false);
			cube->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);

			scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
					v3f(0, 1.0, -1.5), v3f(0, 0, 0));
			// Set orthogonal projection
			core::CMatrix4<f32> pm;
			pm.buildProjectionMatrixOrthoLH(1.65, 1.65, 0, 100);
			camera->setProjectionMatrix(pm, true);

			/*scene::ILightSceneNode *light =*/ smgr->addLightSceneNode(0,
					v3f(-50, 100, 0), video::SColorf(0.5,0.5,0.5), 1000);

			smgr->setAmbientLight(video::SColorf(0.2,0.2,0.2));

			// Render scene
			driver->beginScene(true, true, video::SColor(0,0,0,0));
			smgr->drawAll();
			driver->endScene();
			
			// NOTE: The scene nodes should not be dropped, otherwise
			//       smgr->drop() segfaults
			/*cube->drop();
			camera->drop();
			light->drop();*/
			// Drop scene manager
			smgr->drop();
			
			// Unset render target
			driver->setRenderTarget(0, true, true, 0);

			//TODO: Free textures of images
			driver->removeTexture(texture_top);
			
			// Create image of render target
			video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim);

			assert(image);
			
			baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);

			if(image)
			{
				image->copyTo(baseimg);
				image->drop();
			}
#endif
		}
		else
		{
			infostream<<"generate_image(): Invalid "
					" modification: \""<<part_of_name<<"\""<<std::endl;
		}
	}

	return true;
}