/// Play from memory.
bool CMusicChannelFMod::playSync(const std::string &filepath, bool loop)
{
    CIFile ifile;
    ifile.allowBNPCacheFileOnOpen(false);
    ifile.setCacheFileOnOpen(false);
    ifile.open(filepath);

    // try to load the music in memory
    uint32 fs = ifile.getFileSize();
    if (!fs) {
        nlwarning("NLSOUND FMod Driver: Empty music file");
        return false;
    }

    // read Buffer
    nlassert(!_MusicBuffer);
    _MusicBuffer = new uint8[fs];
    try {
        ifile.serialBuffer(_MusicBuffer, fs);
    }
    catch (...)
    {
        nlwarning("NLSOUND FMod Driver: Error while reading music file");
        delete[] _MusicBuffer;
        _MusicBuffer = NULL;
        return false;
    }

    // open FMOD stream
    _MusicStream = FSOUND_Stream_Open((const char*)_MusicBuffer,
                                      FSOUND_2D | FSOUND_LOADMEMORY | (loop ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF), 0, fs);
    if (!_MusicStream)
    {
        nlwarning("NLSOUND FMod Driver: Error while creating the FMOD stream for music file");
        delete[] _MusicBuffer;
        _MusicBuffer = NULL;
        return false;
    }

    if (!playStream())
    {
        nlwarning("NLSOUND FMod Driver: Error While trying to play sync music file");
        FSOUND_Stream_Close(_MusicStream);
        _MusicStream = NULL;
        delete[] _MusicBuffer;
        _MusicBuffer = NULL;
        return false;
    }

    return true;
}
//=======================================================================================
// ryzom specific build bbox of a village in a zone
static void computeBBoxFromVillage(const NLGEORGES::UFormElm *villageItem, 
								   const std::string &continentName,
								   uint villageIndex,
								   TShapeMap &shapeMap,
								   CLightingBBox &result
								  )
{	
	result = CLightingBBox();
	const NLGEORGES::UFormElm *igNamesItem;
	if (! (villageItem->getNodeByName (&igNamesItem, "IgList") && igNamesItem) )
	{
		nlwarning("No list of IGs was found in the continent form %s, village #%d", continentName.c_str(), villageIndex);
		return;
	}	
	// Get number of village
	uint numIgs;
	nlverify (igNamesItem->getArraySize (numIgs));
	const NLGEORGES::UFormElm *currIg;
	for(uint l = 0; l < numIgs; ++l)
	{														
		if (!(igNamesItem->getArrayNode (&currIg, l) && currIg))
		{
			nlwarning("Couldn't get ig #%d in the continent form %s, in village #%d", l, continentName.c_str(), villageIndex);
			continue;
		}			
		const NLGEORGES::UFormElm *igNameItem;
		currIg->getNodeByName (&igNameItem, "IgName");
		std::string igName;
		if (!igNameItem->getValue (igName))
		{
			nlwarning("Couldn't get ig name of ig #%d in the continent form %s, in village #%d", l, continentName.c_str(), villageIndex);
			continue;
		}
		if (igName.empty())
		{
			nlwarning("Ig name of ig #%d in the continent form %s, in village #%d is an empty string", l, continentName.c_str(), villageIndex);
			continue;
		}

		igName = CFile::getFilenameWithoutExtension(igName) + ".ig";
		string nameLookup = CPath::lookup (igName, false, true);
		if (!nameLookup.empty())
		{		
			CIFile inputFile;
			// Try to open the file
			if (inputFile.open (nameLookup))
			{				
				CInstanceGroup group;
				try
				{
					CLightingBBox currBBox;
					group.serial (inputFile);
					computeIGBBox(group, currBBox, shapeMap);											
					result.makeUnion(currBBox);					
				}
				catch(NLMISC::Exception &)
				{
					nlwarning ("Error while loading instance group %s\n", igName.c_str());	
					continue;
				}								
				inputFile.close();				
			}
			else
			{
				// Error
				nlwarning ("Can't open instance group %s\n", igName.c_str());
			}
		}								
	}	
}
/** Load and compute the bbox of the models that are contained in a given instance group
  * \return true if the computed bbox is valid
  */
static void computeIGBBox(const NL3D::CInstanceGroup &ig, CLightingBBox &result, TShapeMap &shapeMap)
{
	result = CLightingBBox(); // starts with void result
	bool firstBBox = true;	
	/// now, compute the union of all bboxs
	for (CInstanceGroup::TInstanceArray::const_iterator it = ig._InstancesInfos.begin(); it != ig._InstancesInfos.end(); ++it)
	{		
		CLightingBBox currBBox;
		
		bool validBBox = false;
		/// get the bbox from file or from map
		if (shapeMap.count(it->Name)) // already loaded ?
		{
			currBBox = shapeMap[it->Name];
			validBBox = true;
		}
		else // must load the shape to get its bbox
		{		
			std::string shapePathName;
			std::string toLoad = it->Name;
			if (getExt(toLoad).empty()) toLoad += ".shape";
			shapePathName = NLMISC::CPath::lookup(toLoad, false, false);

			if (shapePathName.empty())
			{
				nlwarning("Unable to find shape %s", it->Name.c_str());				
			}
			else
			{
				CIFile shapeInputFile;
				
				if (shapeInputFile.open (shapePathName.c_str()))
				{					
					NL3D::CShapeStream shapeStream;
					try
					{
						shapeStream.serial (shapeInputFile);
						// NB Nico :
						// Deal with water shape -> their 'Receiving' box is set to 'void'
						// this prevent the case where a huge surface of water will cause the zone it is attached to (the 'Zone'
						// field in the villages sheets) to load all the zones that the water surface cover. (This caused
						// an 'out of memory error' in the zone lighter due to too many zone being loaded)
						
						// FIXME : test for water case hardcoded for now						
						CWaterShape *ws = dynamic_cast<CWaterShape *>(shapeStream.getShapePointer());
						if (ws)
						{
							CAABBox bbox;
							shapeStream.getShapePointer()->getAABBox(bbox);
							currBBox.OccludingBox = CPotentialBBox(bbox); // occluding box is used, though the water shape
																		 // doesn't cast shadow -> the tiles flag ('above', 'intersect', 'below water')
																		 // are updated inside the zone_lighter
							currBBox.ReceivingBox.IsVoid = true; // no lighted by the zone lighter !!!
							currBBox.removeVoid();
							shapeMap[it->Name] = currBBox;							
						}
						else
						{

							CAABBox bbox;
							shapeStream.getShapePointer()->getAABBox(bbox);
							currBBox.OccludingBox = CPotentialBBox(bbox);
							currBBox.ReceivingBox = CPotentialBBox(bbox);
							currBBox.removeVoid();
							shapeMap[it->Name] = currBBox;
						}
						validBBox = true;
					}
					
					catch (NLMISC::Exception &e)
					{
						nlwarning("Error while loading shape %s. \n\t Reason : %s ", it->Name.c_str(), e.what());
					}				
				}
				else
				{
					nlwarning("Unable to open shape file %s to get its bbox", it->Name.c_str());
				}
			}
		}


		if (validBBox)
		{
			/// build the model matrix
			NLMISC::CMatrix mat;
			mat.scale(it->Scale);
			NLMISC::CMatrix rotMat;
			rotMat.setRot(it->Rot);
			mat = rotMat * mat;
			mat.setPos(it->Pos);

			/// transform the bbox
			currBBox.transform(mat);
			currBBox.removeVoid();			
			if (firstBBox)
			{
				result = currBBox;
				firstBBox = false;
			}
			else // add to previous one
			{						
				result.makeUnion(currBBox);
			}			
		}		
	}	
}
///=========================================================
int main (int argc, char* argv[])
{
	// Filter addSearchPath
	NLMISC::createDebug();
	InfoLog->addNegativeFilter ("adding the path");

	TShapeMap shapeMap;

	// Check number of args
	if (argc<5)
	{
		// Help message
		printf ("zone_dependencies [properties.cfg] [firstZone.zone] [lastzone.zone] [output_dependencies.cfg]\n");
	}
	else
	{
		NL3D::registerSerial3d();
		// Light direction
		CVector lightDirection;

		// Config file handler
		try
		{
			// Read the properties file
			CConfigFile properties;
			
			// Load and parse the properties file
			properties.load (argv[1]);

			// Get the light direction
			CConfigFile::CVar &sun_direction = properties.getVar ("sun_direction");
			lightDirection.set (sun_direction.asFloat(0), sun_direction.asFloat(1), sun_direction.asFloat(2));
			lightDirection.normalize();


			// Get the search pathes
			CConfigFile::CVar &search_pathes = properties.getVar ("search_pathes");
			uint path;
			for (path = 0; path < (uint)search_pathes.size(); path++)
			{
				// Add to search path
				CPath::addSearchPath (search_pathes.asString(path));
			}
/*
			CConfigFile::CVar &ig_path = properties.getVar ("ig_path");
			NLMISC::CPath::addSearchPath(ig_path.asString(), true, true);

			CConfigFile::CVar &shapes_path = properties.getVar ("shapes_path");
			NLMISC::CPath::addSearchPath(shapes_path.asString(), true, true);
*/
			CConfigFile::CVar &compute_dependencies_with_igs = properties.getVar ("compute_dependencies_with_igs");
			bool computeDependenciesWithIgs = compute_dependencies_with_igs.asInt() != 0;								


			// Get the file extension
			string ext=getExt (argv[2]);

			// Get the file directory
			string dir=getDir (argv[2]);

			// Get output extension
			string outExt=getExt (argv[4]);

			// Get output directory
			string outDir=getDir (argv[4]);

			// Get the first and last name
			string firstName=getName (argv[2]);
			string lastName=getName (argv[3]);

			// Get the coordinates
			uint16 firstX, firstY;
			uint16 lastX, lastY;
			if (getZoneCoordByName (firstName.c_str(), firstX, firstY))
			{
				// Last zone
				if (getZoneCoordByName (lastName.c_str(), lastX, lastY))
				{
					// Take care
					if (lastX<firstX)
					{
						uint16 tmp=firstX;
						firstX=lastX;
						lastX=firstX;
					}
					if (lastY<firstY)
					{
						uint16 tmp=firstY;
						firstY=lastY;
						lastY=firstY;
					}

					// Min z
					float minZ=FLT_MAX;

					// Make a quad grid
					CQuadGrid<CZoneDescriptorBB>	quadGrid;
					quadGrid.create (256, 100);

					// The dependencies list
					vector< CZoneDependencies > dependencies;
					dependencies.resize ((lastX-firstX+1)*(lastY-firstY+1));

					// Ryzom specific: build bbox for villages
					TString2LightingBBox villagesBBox;					
					computeIGBBoxFromContinent(properties, shapeMap, villagesBBox);		


					// Insert each zone in the quad tree
					sint y, x;
					for (y=firstY; y<=lastY; y++)
					for (x=firstX; x<=lastX; x++)
					{
						

						// Progress
						progress ("Build bounding boxes", (float)(x+y*lastX)/(float)(lastX*lastY));

						// Make a zone file name
						string zoneName;
						getZoneNameByCoord (x, y, zoneName);

						// Open the file
						CIFile file;
						if (file.open (dir+zoneName+ext))
						{							
							// The zone
							CZone zone;

							try
							{
								// Serial the zone
								file.serial (zone);

								/// get bbox from the ig of this zone
								CLightingBBox igBBox;								
								if (computeDependenciesWithIgs)
								{
									computeZoneIGBBox(zoneName.c_str(), igBBox, shapeMap, villagesBBox);
								}								
								// Create a zone descriptor
								

								
								NLMISC::CAABBox zoneBox;
								zoneBox.setCenter(zone.getZoneBB().getCenter());
								zoneBox.setHalfSize(zone.getZoneBB().getHalfSize());

								CLightingBBox zoneLBox;
								zoneLBox.OccludingBox = zoneLBox.ReceivingBox = zoneBox; // can't be void
								zoneLBox.makeUnion(igBBox);								
								nlassert(!zoneLBox.ReceivingBox.IsVoid);
								//
								CZoneDescriptorBB zoneDesc;
								zoneDesc.X=x;
								zoneDesc.Y=y;
								zoneDesc.BBox=zoneLBox.ReceivingBox.Box;
								//
								if (!zoneLBox.OccludingBox.IsVoid)
								{
									quadGrid.insert (zoneLBox.ReceivingBox.Box.getMin(), zoneLBox.ReceivingBox.Box.getMax(), zoneDesc);
								}
																								
								// Insert in the dependencies
								// Index 
								uint index=(x-firstX)+(y-firstY)*(lastX-firstX+1);
								

								// Loaded
								dependencies[index].Loaded=true;
								dependencies[index].X=x;
								dependencies[index].Y=y;
								dependencies[index].BBox=zoneLBox.OccludingBox.Box;

								// ZMin
								float newZ=zoneLBox.ReceivingBox.Box.getMin().z;
								if (newZ<minZ)
									minZ=newZ;
							}
							catch (Exception& e)
							{
								// Error handling
								nlwarning ("ERROR in file %s, %s", (dir+zoneName+ext).c_str(), e.what ());
							}
						}
					}

					// Now select each zone in others and make a depencies list
					for (y=firstY; y<=lastY; y++)
					for (x=firstX; x<=lastX; x++)
					{
						// Progress
						progress ("Compute dependencies", (float)(x+y*lastX)/(float)(lastX*lastY));

						// Index 
						uint index=(x-firstX)+(y-firstY)*(lastX-firstX+1);

						// Loaded ?
						if (dependencies[index].Loaded)
						{
							// Min max vectors
							CVector vMin (dependencies[index].BBox.getMin());
							CVector vMax (dependencies[index].BBox.getMax());

							// Make a corner array 
							CVector corners[4] = 
							{
								CVector (vMin.x, vMin.y, vMax.z), CVector (vMax.x, vMin.y, vMax.z), 
								CVector (vMax.x, vMax.y, vMax.z), CVector (vMin.x, vMax.y, vMax.z)
							};

							// Extended bbox
							CAABBox	bBox=dependencies[index].BBox.getAABBox();

							// For each corner
							uint corner;
							for (corner=0; corner<4; corner++)
							{
								// Target position
								CVector target;
								if (lightDirection.z!=0)
								{
									// Not horizontal target
									target=corners[corner]+(lightDirection*((minZ-corners[corner].z)/lightDirection.z));
								}
								else
								{
									// Horizontal target, select 500 meters around.
									target=(500*lightDirection)+corners[corner];
								}

								// Extend the bbox
								bBox.extend (target);
							}

							// Clear quad tree selection
							quadGrid.clearSelection ();

							// Select
							quadGrid.select (bBox.getMin(), bBox.getMax());

							// Check selection
							CQuadGrid<CZoneDescriptorBB>::CIterator it=quadGrid.begin();
							while (it!=quadGrid.end())
							{
								// Index 
								uint targetIndex=((*it).X-firstX)+((*it).Y-firstY)*(lastX-firstX+1);

								// Not the same
								if (targetIndex!=index)
								{
									// Target min z
									float targetMinZ=dependencies[targetIndex].BBox.getMin().z;
									if (targetMinZ<vMax.z)
									{
										// Min z inf to max z ?
										// Target optimized bbox
										CAABBox	bBoxOptimized=dependencies[index].BBox.getAABBox();

										// For each corner
										for (corner=0; corner<4; corner++)
										{
											// Target position
											CVector target;
											if (lightDirection.z!=0)
											{
												// Not horizontal target
												target=corners[corner]+(lightDirection*((targetMinZ-corners[corner].z)
													/lightDirection.z));
											}
											else
											{
												// Horizontal target, select 500 meters around.
												target=(500*lightDirection)+corners[corner];
											}

											// Extend the bbox
											bBoxOptimized.extend (target);
										}

										// Check it more presisly
										//if ((*it).BBox.intersect (bBoxOptimized))
										if ((*it).BBox.intersect (bBox))
										{
											// Insert in the set
											dependencies[targetIndex].Dependences.insert (CZoneDependenciesValue (x, y));
										}
									}
								}

								// Next selected
								it++;
							}
						}
					}

					// For each zone
					for (y=firstY; y<=lastY; y++)
					for (x=firstX; x<=lastX; x++)
					{
						// Progress
						progress ("Save depend files", (float)(x+y*lastX)/(float)(lastX*lastY));

						// Index 
						uint index=(x-firstX)+(y-firstY)*(lastX-firstX+1);

						// Loaded ?
						if (dependencies[index].Loaded)
						{
							// Make a file name
							string outputFileName;
							getZoneNameByCoord(x, y, outputFileName);
							outputFileName=outDir+outputFileName+outExt;

							// Write the dependencies file
							FILE *outputFile;
							if ((outputFile=fopen (toLower (outputFileName).c_str(), "w")))
							{
								// Add a dependency entry
								fprintf (outputFile, "dependencies =\n{\n");

								// Add dependent zones
								set<CZoneDependenciesValue>::iterator ite=dependencies[index].Dependences.begin();
								while (ite!=dependencies[index].Dependences.end())
								{
									// Name of the dependent zone
									std::string zoneName;
									getZoneNameByCoord(ite->first, ite->second, zoneName);

									// Write it
									string message="\t\""+zoneName+"\"";
									fprintf (outputFile, "%s", toLower (message).c_str());

									// Next ite;
									ite++;
									if (ite!=dependencies[index].Dependences.end())
										fprintf (outputFile, ",\n");
								}

								// Close the variable
								fprintf (outputFile, "\n};\n\n");
							}
							else
							{
								nlwarning ("ERROR can't open %s for writing.\n", outputFileName.c_str());
							}

							// Close the file
							fclose (outputFile);
						}
					}

				}
				else
				{
					// Not valid
					nlwarning ("ERROR %s is not a valid zone name.\n", lastName.c_str());
				}
			}
			else
			{
				// Not valid
				nlwarning ("ERROR %s is not a valid zone name.\n", firstName.c_str());
			}
		}
		catch (Exception &ee)
		{
			nlwarning ("ERROR %s\n", ee.what());
		}
	}

	return 0;
}
Ejemplo n.º 5
0
BOOL CTexGenThumbnailDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
	CIFile file;
	if (file.open (lpszPathName))
	{
		try
		{
			NLTEXGEN::CTexGenDocument	doc;
			file.serial(doc);

			CFloatBitmap bitmap;
			CRenderParameter renderParameters (false, false, false);
			doc.Operators[0]->eval (bitmap, renderParameters);
			if ((bitmap.getWidth() != 0) && (bitmap.getHeight() != 0))
			{
				bitmap.resample (m_sizeDoc.cx, m_sizeDoc.cy);

				_DibBitmapInfo.bmiHeader.biSize	= sizeof(BITMAPINFO);
				_DibBitmapInfo.bmiHeader.biWidth	= m_sizeDoc.cx;
				_DibBitmapInfo.bmiHeader.biHeight	= m_sizeDoc.cy;
				_DibBitmapInfo.bmiHeader.biPlanes	= 1;
				_DibBitmapInfo.bmiHeader.biBitCount = 32;
				_DibBitmapInfo.bmiHeader.biCompression  = BI_RGB;
				_DibBitmapInfo.bmiHeader.biSizeImage	= 0;
				_DibBitmapInfo.bmiHeader.biXPelsPerMeter	= 0;
				_DibBitmapInfo.bmiHeader.biYPelsPerMeter	= 0;
				_DibBitmapInfo.bmiHeader.biClrUsed	= 0;
				_DibBitmapInfo.bmiHeader.biClrImportant	= 0;
				HWND desktop = ::GetDesktopWindow();
				HDC dc = ::GetDC (desktop);
				nlverify(_Dib = CreateDIBSection(dc, &_DibBitmapInfo, DIB_RGB_COLORS, (void**)&_DibBits, NULL, 0));

				const float *pixels = bitmap.getPixels();
				if (pixels)
				{
					uint8 *dst = _DibBits;
					const uint height = m_sizeDoc.cy;
					uint y;
					for (y=0; y<height; y++)
					{
						const uint width = m_sizeDoc.cx*4 + y*m_sizeDoc.cx*4;
						uint i = y*m_sizeDoc.cx*4;
						uint j = (height-y-1)*m_sizeDoc.cx*4;
						for (;i<width; i+=4, j+=4)
						{
							/*if (alpha)
							{
								int r = (int)(pixels[i+0] * 255.f);
								clamp (r, 0, 255);
								dst[j+0] = r;
								dst[j+1] = r;
								dst[j+2] = r;
							}
							else*/
							{
								int r = (int)(pixels[i+0] * 255.f);
								int g = (int)(pixels[i+1] * 255.f);
								int b = (int)(pixels[i+2] * 255.f);
								clamp (r, 0, 255);
								clamp (g, 0, 255);
								clamp (b, 0, 255);
								dst[j+0] = b;
								dst[j+1] = g;
								dst[j+2] = r;
							}
						}
					}
				}

				::ReleaseDC (desktop, dc);
				
				return TRUE;
			}
		}
		catch (Exception &)
		{
		}
	}
	
	return FALSE;
}
void CSheetId::loadSheetId ()
{
	H_AUTO(CSheetIdInit);
	//nldebug("Loading sheet_id.bin");

	// Open the sheet id to sheet file name association
	CIFile file;
	std::string path = CPath::lookup("sheet_id.bin", false, false);
	if(!path.empty() && file.open(path))
	{
		// clear entries
		_FileExtensions.clear ();
		_SheetIdToName.clear ();
		_SheetNameToId.clear ();

		// reserve space for the vector of file extensions
		_FileExtensions.resize(1 << (NL_SHEET_ID_TYPE_BITS));

		// Get the map from the file
		map<uint32,string> tempMap;
		contReset(tempMap);
		file.serialCont(tempMap);
		file.close();

		if (_RemoveUnknownSheet)
		{
			uint32 removednbfiles = 0;
			uint32 nbfiles = (uint32)tempMap.size();

			// now we remove all files that not available
			map<uint32,string>::iterator itStr2;
			for( itStr2 = tempMap.begin(); itStr2 != tempMap.end(); )
			{
				if (CPath::exists ((*itStr2).second))
				{
					++itStr2;
				}
				else
				{
					map<uint32,string>::iterator olditStr = itStr2;
					//nldebug ("Removing file '%s' from CSheetId because the file not exists", (*olditStr).second.c_str ());
					itStr2++;
					tempMap.erase (olditStr);
					removednbfiles++;
				}
			}
			nlinfo ("SHEETID: Removed %d files on %d from CSheetId because these files doesn't exists", removednbfiles, nbfiles);
		}

		// Convert the map to one big string and 1 static map (id to name)
		{
			// Get the number and size of all strings
			vector<CChar> tempVec; // Used to initialise the first map
			uint32 nNb = 0;
			uint32 nSize = 0;
			map<uint32,string>::const_iterator it = tempMap.begin();
			while (it != tempMap.end())
			{
				nSize += (uint32)it->second.size()+1;
				nNb++;
				it++;
			}

			// Make the big string (composed of all strings) and a vector referencing each string
			tempVec.resize(nNb);
			_AllStrings.Ptr = new char[nSize];
			it = tempMap.begin();
			nSize = 0;
			nNb = 0;
			while (it != tempMap.end())
			{
				tempVec[nNb].Ptr = _AllStrings.Ptr+nSize;
				strcpy(_AllStrings.Ptr+nSize, it->second.c_str());
				toLower(_AllStrings.Ptr+nSize);
				nSize += (uint32)it->second.size()+1;
				nNb++;
				it++;
			}

			// Finally build the static map (id to name)
			_SheetIdToName.reserve(tempVec.size());
			it = tempMap.begin();
			nNb = 0;
			while (it != tempMap.end())
			{
				_SheetIdToName.add(pair<uint32, CChar>(it->first, CChar(tempVec[nNb])));

				nNb++;
				it++;
			}

			// The vector of all small string is not needed anymore we have all the info in
			// the static map and with the pointer AllStrings referencing the beginning.
		}

		// Build the invert map (Name to Id) & file extension vector
		{
			uint32 nSize = (uint32)_SheetIdToName.size();
			_SheetNameToId.reserve(nSize);
			CStaticMap<uint32,CChar>::iterator itStr;
			for( itStr = _SheetIdToName.begin(); itStr != _SheetIdToName.end(); ++itStr )
			{
				// add entry to the inverse map
				_SheetNameToId.add( make_pair((*itStr).second, (*itStr).first) );

				// work out the type value for this entry in the map
				TSheetId sheetId;
				sheetId.Id=(*itStr).first;
				uint32 type = sheetId.IdInfos.Type;

				// check whether we need to add an entry to the file extensions vector
				if (_FileExtensions[type].empty())
				{
					// find the file extension part of the given file name
					_FileExtensions[type] = toLower(CFile::getExtension((*itStr).second.Ptr));
				}
				nSize--;
			}
			_SheetNameToId.endAdd();
		}
	}
	else
	{
		nlerror("<CSheetId::init> Can't open the file sheet_id.bin");
	}
	nldebug("Finished loading sheet_id.bin: %u entries read",_SheetIdToName.size());
}
Ejemplo n.º 7
0
// ***************************************************************************
int main(int argc, char *argv[])
{
	NLMISC::createDebug();

	// make_anim_melee_impact animset_dir
	if(argc!=2)
		return usage();
	string animSetDir= argv[1];

	// *** parse the anim.txt file
	set<CAnimCombatSet>		combatAnimSets;
	CIFile	animFile;
	if(!animFile.open("anim.txt", true))
	{
		nlwarning("Can't open anim.txt file. abort");
		return 0;
	}
	else
	{
		char	tmp[5000];
		CAnimCombatSet	lastAnimSet;
		// parse all lines
		while(!animFile.eof())
		{
			animFile.getline(tmp, 5000);
			string	line= tmp;
			if(line.empty())
				continue;

			// new anim set?
			if(line[0]!=' ')
			{
				// insert the last anim state
				if(!lastAnimSet.States.empty())
					combatAnimSets.insert(lastAnimSet);
				lastAnimSet.States.clear();
				lastAnimSet.Name= line;
			}
			// new anim state?
			else if(!lastAnimSet.Name.empty())
			{
				CAnimCombatState	state;
				state.build(line);
				lastAnimSet.States.insert(state);
			}
		}

		// append the last anim set if needed
		if(!lastAnimSet.States.empty())
			combatAnimSets.insert(lastAnimSet);

		animFile.close();
	}
	
	// *** Get the list of .animset to make by race
	vector<string>	files;
	files.clear();
	CPath::getPathContent(animSetDir, true, false, true, files);
	vector<string>	animSetList;
	InfoLog->displayRawNL("");
	InfoLog->displayRawNL("*****************************");
	InfoLog->displayRawNL("**** .animation_set list ****");
	InfoLog->displayRawNL("*****************************");
	for(uint i=0;i<files.size();i++)
	{
		if(testWildCard(files[i], "*.animation_set"))
		{
			animSetList.push_back(files[i]);
			InfoLog->displayRawNL(animSetList.back().c_str());
		}
	}
	
	// *** Init StateNameToStateCode
	StateNameToStateCode["attack1"]= "A1";
	StateNameToStateCode["attack2"]= "A2";
	StateNameToStateCode["walk atk"]= "Wa";
	StateNameToStateCode["run atk"]= "Ra";
	StateNameToStateCode["backward atk"]= "Ba";
	StateNameToStateCode["default atk low"]= "Dl";
	StateNameToStateCode["default atk middle"]= "Dm";
	StateNameToStateCode["default atk high"]= "Dh";
	StateNameToStateCode["powerful atk low"]= "Pl";
	StateNameToStateCode["powerful atk middle"]= "Pm";
	StateNameToStateCode["powerful atk high"]= "Ph";
	StateNameToStateCode["area atk low"]= "Al";
	StateNameToStateCode["area atk middle"]= "Am";
	StateNameToStateCode["area atk high"]= "Ah";

	
	// *** For each animset, test if can replace some anim
	InfoLog->displayRawNL("");
	InfoLog->displayRawNL("**************************");
	InfoLog->displayRawNL("**** Starting Process ****");
	InfoLog->displayRawNL("**************************");
	for(uint i=0;i<animSetList.size();i++)
	{
		makeAnimMeleeImpact(animSetList[i], combatAnimSets);
	}

	return 0;
}
// ***************************************************************************
int main(int argc, char* argv[])
{
	// Filter addSearchPath
	NLMISC::createDebug();
	InfoLog->addNegativeFilter ("adding the path");

	// Register 3d
	registerSerial3d ();

	// Good number of args ?
	if (argc<4)
	{
		// Help message
		printf ("ig_lighter [directoryIn] [pathOut] [parameter_file] \n");
	}
	else
	{
		try
		{
			string	directoryIn= argv[1];
			string	pathOut= argv[2];
			string	paramFile= argv[3];
			CInstanceLighter::CLightDesc	lighterDesc;
			string	grFile, rbankFile;

			// Verify directoryIn.
			directoryIn= CPath::standardizePath(directoryIn);
			if( !CFile::isDirectory(directoryIn) )
			{
				printf("DirectoryIn %s is not a directory", directoryIn.c_str());
				return -1;
			}
			// Verify pathOut.
			pathOut= CPath::standardizePath(pathOut);
			if( !CFile::isDirectory(pathOut) )
			{
				printf("PathOut %s is not a directory", pathOut.c_str());
				return -1;
			}

			// Load and setup configFile.
			//=================
			CConfigFile parameter;
			// Load and parse the param file
			parameter.load (paramFile);

			// Get the search pathes
			CConfigFile::CVar &search_pathes = parameter.getVar ("search_pathes");
			uint path;
			for (path = 0; path < (uint)search_pathes.size(); path++)
			{
				// Add to search path
				CPath::addSearchPath (search_pathes.asString(path));
			}

			// Light direction
			CConfigFile::CVar &sun_direction = parameter.getVar ("sun_direction");
			lighterDesc.LightDirection.x=sun_direction.asFloat(0);
			lighterDesc.LightDirection.y=sun_direction.asFloat(1);
			lighterDesc.LightDirection.z=sun_direction.asFloat(2);
			lighterDesc.LightDirection.normalize ();

			// Grid size
			CConfigFile::CVar &quad_grid_size = parameter.getVar ("quad_grid_size");
			lighterDesc.GridSize=quad_grid_size.asInt();

			// Grid size
			CConfigFile::CVar &quad_grid_cell_size = parameter.getVar ("quad_grid_cell_size");
			lighterDesc.GridCellSize=quad_grid_cell_size.asFloat();

			// Shadows enabled ?
			CConfigFile::CVar &shadow = parameter.getVar ("shadow");
			lighterDesc.Shadow=shadow.asInt ()!=0;

			// OverSampling
				CConfigFile::CVar &ig_oversampling = parameter.getVar ("ig_oversampling");
				lighterDesc.OverSampling= ig_oversampling.asInt ();
			// validate value: 0, 2, 4, 8, 16
			lighterDesc.OverSampling= raiseToNextPowerOf2(lighterDesc.OverSampling);
			clamp(lighterDesc.OverSampling, 0U, 16U);
			if(lighterDesc.OverSampling<2)
				lighterDesc.OverSampling= 0;

			// gr
			CConfigFile::CVar &grbank = parameter.getVar ("grbank");
			grFile= grbank.asString ();

			// rbank
			CConfigFile::CVar &rbank = parameter.getVar ("rbank");
			rbankFile= rbank.asString ();

			// CellSurfaceLightSize;
			CConfigFile::CVar &cell_surface_light_size = parameter.getVar ("cell_surface_light_size");
			float cellSurfaceLightSize= cell_surface_light_size.asFloat ();
			if(cellSurfaceLightSize<=0)
				throw Exception("cell_surface_light_size must be > 0");

			// CellRaytraceDeltaZ
			CConfigFile::CVar &cell_raytrace_delta_z = parameter.getVar ("cell_raytrace_delta_z");
			float cellRaytraceDeltaZ= cell_raytrace_delta_z.asFloat ();


			// colIdentifierPrefix
			CConfigFile::CVar &col_identifier_prefix = parameter.getVar ("col_identifier_prefix");
			string colIdentifierPrefix= col_identifier_prefix.asString ();

			// colIdentifierSuffix
			CConfigFile::CVar &col_identifier_suffix = parameter.getVar ("col_identifier_suffix");
			string colIdentifierSuffix= col_identifier_suffix.asString ();

			// colIdentifierSuffix
			CConfigFile::CVar &build_debug_surface_shape = parameter.getVar ("build_debug_surface_shape");
			bool	buildDebugSurfaceShape= build_debug_surface_shape.asInt()!=0;
			

			// try to open gr and rbank
			CRetrieverBank		*retrieverBank= NULL;
			CGlobalRetriever	*globalRetriever= NULL;
			uint32		grFileDate= 0;
			uint32		rbankFileDate= 0;
			if( grFile!="" && rbankFile!="" )
			{
				CIFile	fin;
				// serial the retrieverBank. Exception if not found.
				fin.open(CPath::lookup(rbankFile));
				retrieverBank= new CRetrieverBank;
				retrieverBank->setNamePrefix(CFile::getFilenameWithoutExtension(rbankFile).c_str ());

				// Add the search path for LR files
				CPath::addSearchPath (CFile::getPath(rbankFile));

				fin.serial(*retrieverBank);
				fin.close();

				// serial the globalRetriever. Exception if not found.
				fin.open(CPath::lookup(grFile));
				globalRetriever= new CGlobalRetriever;

				// set the RetrieverBank before loading
				globalRetriever->setRetrieverBank(retrieverBank);
				fin.serial(*globalRetriever);
				fin.close();

				// Get File Dates
				rbankFileDate= CFile::getFileModificationDate(CPath::lookup(rbankFile));
				grFileDate= CFile::getFileModificationDate(CPath::lookup(grFile));

				// And init them.
				globalRetriever->initAll();
			}


			// Scan and load all files .ig in directories
			//=================
			vector<string>				listFile;
			vector<CInstanceGroup*>		listIg;
			vector<string>				listIgFileName;
			vector<string>				listIgPathName;
			CPath::getPathContent(directoryIn, false, false, true, listFile);
			for(uint iFile=0; iFile<listFile.size(); iFile++)
			{
				string	&igFile= listFile[iFile];
				// verify it is a .ig.
				if( CFile::getExtension(igFile) == "ig" )
				{
					// Read the InstanceGroup.
					CInstanceGroup	*ig= new CInstanceGroup;
					CIFile	fin;
					fin.open(CPath::lookup(igFile));
					fin.serial(*ig);

					// add to list.
					listIg.push_back(ig);
					listIgPathName.push_back(igFile);
					listIgFileName.push_back(CFile::getFilename(igFile));
				}
			}


			// For all ig, light them, and save.
			//=================
			for(uint iIg= 0; iIg<listIg.size(); iIg++)
			{
				string	fileNameIn= listIgFileName[iIg];
				string	fileNameOut= pathOut + fileNameIn;

				// If File Out exist 
				if(CFile::fileExists(fileNameOut))
				{
					// If newer than file In (and also newer than retrieverInfos), skip
					uint32		fileOutDate= CFile::getFileModificationDate(fileNameOut);
					if(	fileOutDate > CFile::getFileModificationDate(listIgPathName[iIg]) &&
						fileOutDate > rbankFileDate && 
						fileOutDate > grFileDate 
						)
					{
						printf("Skiping %s\n", fileNameIn.c_str());
						continue;
					}
				}

				// progress
				printf("Processing %s\n", fileNameIn.c_str());

				CInstanceGroup	igOut;

				// Export a debugSun Name.
				string	debugSunName;
				debugSunName= pathOut + "/" + CFile::getFilenameWithoutExtension(fileNameIn) + "_debug_sun_.shape";
				string	debugPLName;
				debugPLName= pathOut + "/" + CFile::getFilenameWithoutExtension(fileNameIn) + "_debug_pl_.shape";

				// light the ig.
				CIgLighterLib::CSurfaceLightingInfo	slInfo;
				slInfo.CellSurfaceLightSize= cellSurfaceLightSize;
				slInfo.CellRaytraceDeltaZ= cellRaytraceDeltaZ;
				slInfo.RetrieverBank= retrieverBank;
				slInfo.GlobalRetriever= globalRetriever;
				slInfo.IgFileName= CFile::getFilenameWithoutExtension(fileNameIn);
				slInfo.ColIdentifierPrefix= colIdentifierPrefix;
				slInfo.ColIdentifierSuffix= colIdentifierSuffix;
				slInfo.BuildDebugSurfaceShape= buildDebugSurfaceShape;
				slInfo.DebugSunName= debugSunName;
				slInfo.DebugPLName= debugPLName;
				lightIg(*listIg[iIg], igOut, lighterDesc, slInfo, fileNameIn.c_str ());

				// Save this ig.
				COFile	fout;
				fout.open(fileNameOut);
				fout.serial(igOut);
				fout.close();

				// skip a line
				printf("\n");
			}

		}
		catch (Exception& except)
		{
			// Error message
			nlwarning ("ERROR %s\n", except.what());
		}
	}


	// Landscape is not deleted, nor the instanceGroups, for faster quit.
	// Must disalbe BlockMemory checks (for pointLights).
	NL3D_BlockMemoryAssertOnPurge= false;


	// exit.
	return 0;
}
Ejemplo n.º 9
0
int main(int argc, char* argv[])
{
	// Filter addSearchPath
	NLMISC::createDebug();
	InfoLog->addNegativeFilter ("adding the path");

	// Register 3d
	registerSerial3d ();

	// Good number of args ?
	if (argc<5)
	{
		// Help message
		printf ("%s [zonein.zonel] [igout.ig] [parameter_file] [dependancy_file]\n", argv[0]);
	}
	else
	{
		// Ok, read the zone
		CIFile inputFile;

		// Get extension
		string ext=getExt (argv[1]);
		string dir=getDir (argv[1]);

		// Open it for reading
		if (inputFile.open (argv[1]))
		{
			// Zone name
			string zoneName=toLower (string ("zone_"+getName (argv[1])));

			// Load the zone
			try
			{
				// Read the config file
				CConfigFile parameter;

				// Load and parse the parameter file
				parameter.load (argv[3]);

				// **********
				// *** Build the lighter descriptor
				// **********

				CInstanceLighter::CLightDesc lighterDesc;

				// Light direction
				CConfigFile::CVar &sun_direction = parameter.getVar ("sun_direction");
				lighterDesc.LightDirection.x=sun_direction.asFloat(0);
				lighterDesc.LightDirection.y=sun_direction.asFloat(1);
				lighterDesc.LightDirection.z=sun_direction.asFloat(2);
				lighterDesc.LightDirection.normalize ();

				// Grid size
				CConfigFile::CVar &quad_grid_size = parameter.getVar ("quad_grid_size");
				lighterDesc.GridSize=quad_grid_size.asInt();

				// Grid size
				CConfigFile::CVar &quad_grid_cell_size = parameter.getVar ("quad_grid_cell_size");
				lighterDesc.GridCellSize=quad_grid_cell_size.asFloat();

				// Shadows enabled ?
				CConfigFile::CVar &shadow = parameter.getVar ("shadow");
				lighterDesc.Shadow=shadow.asInt ()!=0;

				// OverSampling
				CConfigFile::CVar &ig_oversampling = parameter.getVar ("ig_oversampling");
				lighterDesc.OverSampling= ig_oversampling.asInt ();
				// validate value: 0, 2, 4, 8, 16
				lighterDesc.OverSampling= raiseToNextPowerOf2(lighterDesc.OverSampling);
				clamp(lighterDesc.OverSampling, 0U, 16U);
				if(lighterDesc.OverSampling<2)
					lighterDesc.OverSampling= 0;

				// For ig of Zones, never disable Sun contrib !!!
				lighterDesc.DisableSunContribution= false;

				// Get the search pathes
				CConfigFile::CVar &search_pathes = parameter.getVar ("search_pathes");
				uint path;
				for (path = 0; path < (uint)search_pathes.size(); path++)
				{
					// Add to search path
					CPath::addSearchPath (search_pathes.asString(path));
				}

				// A landscape allocated with new: it is not delete because destruction take 3 secondes more!
				CLandscape *landscape=new CLandscape;
				landscape->init();

				// A zone lighter
				CMyIgZoneLighter lighter;
				lighter.init ();

				// A vector of zone id
				vector<uint> listZoneId;

				// The zone
				CZone zone;

				// List of ig
				std::list<CInstanceGroup*> instanceGroup;

				// Load
				zone.serial (inputFile);
				inputFile.close();

				// Load ig of the zone
				string igName = getName (argv[1])+".ig";
				string igNameLookup = CPath::lookup (igName, false, false);
				if (!igNameLookup.empty())
					igName = igNameLookup;

				bool zoneIgLoaded;

				// Try to open the file
				CInstanceGroup *centerInstanceGroup= NULL;
				if (inputFile.open (igName))
				{
					// load the center ig
					centerInstanceGroup=new CInstanceGroup;

					// Serial it
					centerInstanceGroup->serial (inputFile);
					inputFile.close();

					// Add to the list
					instanceGroup.push_back (centerInstanceGroup);
					zoneIgLoaded = true;
				}
				else
				{
					// Warning
					fprintf (stderr, "Warning: can't load instance group %s\n", igName.c_str());
					zoneIgLoaded = false;
				}

				// If can't load the center instanceGroup, skip it.
				if(!zoneIgLoaded)
					return 0;

				// Get bank path
				CConfigFile::CVar &bank_name_var = parameter.getVar ("bank_name");
				string bank_name = bank_name_var.asString ();
				string bank_name_lookup = CPath::lookup (bank_name);
				if (!bank_name_lookup.empty())
					bank_name = bank_name_lookup;

				// Load the bank
				if (inputFile.open (bank_name))
				{
					try
					{
						// Load
						landscape->TileBank.serial (inputFile);
						landscape->initTileBanks();
					}
					catch (const Exception &e)
					{
						// Error
						nlwarning ("ERROR error loading tile bank %s\n%s\n", bank_name.c_str(), e.what());
					}
				}
				else
				{
					// Error
					nlwarning ("ERROR can't load tile bank %s\n", bank_name.c_str());
				}

				// Add the zone
				landscape->addZone (zone);
				listZoneId.push_back (zone.getZoneId());

				// Load instance group ?
				CConfigFile::CVar &load_ig= parameter.getVar ("load_ig");
				bool loadInstanceGroup = load_ig.asInt ()!=0;

				// Continue to build ?
				bool continu=true;

				// Try to load additionnal instance group.
				if (loadInstanceGroup)
				{
					// Additionnal instance group
					try
					{
						CConfigFile::CVar &additionnal_ig = parameter.getVar ("additionnal_ig");									
						for (uint add=0; add<(uint)additionnal_ig.size(); add++)
						{
							// Input file
							CIFile inputFile;

							// Name of the instance group
							string name = additionnal_ig.asString(add);
							string nameLookup = CPath::lookup (name, false, false);
							if (!nameLookup.empty())
								name = nameLookup;

							// Try to open the file
							if (inputFile.open (name))
							{
								// New ig
								CInstanceGroup *group=new CInstanceGroup;

								// Serial it
								group->serial (inputFile);
								inputFile.close();

								// Add to the list
								instanceGroup.push_back (group);
							}
							else
							{
								// Error
								nlwarning ("ERROR can't load instance group %s\n", name.c_str());

								// Stop before build
								continu=false;
							}
						}
					}
					catch (const NLMISC::EUnknownVar &)
					{
						nlinfo("No additionnal ig's to load");
					}
				}
				
				// Shadow ?
				if (lighterDesc.Shadow)
				{
					// Load and parse the dependency file
					CConfigFile dependency;
					dependency.load (argv[4]);

					// *** Scan dependency file
					CConfigFile::CVar &dependant_zones = dependency.getVar ("dependencies");
					for (uint i=0; i<(uint)dependant_zones.size(); i++)
					{
						// Get zone name
						string zoneName=dependant_zones.asString(i);

						// Load the zone
						CZone zoneBis;

						// Open it for reading
						if (inputFile.open (dir+zoneName+ext))
						{
							// Read it
							zoneBis.serial (inputFile);
							inputFile.close();

							// Add the zone
							landscape->addZone (zoneBis);
							listZoneId.push_back (zoneBis.getZoneId());
						}
						else
						{
							// Error message and continue
							nlwarning ("ERROR can't load zone %s\n", (dir+zoneName+ext).c_str());
						}

						// Try to load an instance group.
						if (loadInstanceGroup)
						{
							string name = zoneName+".ig";
							string nameLookup = CPath::lookup (name, false, false);
							if (!nameLookup.empty())
								name = nameLookup;

							// Name of the instance group
							if (inputFile.open (name))
							{
								// New ig
								CInstanceGroup *group=new CInstanceGroup;

								// Serial it
								group->serial (inputFile);
								inputFile.close();

								// Add to the list
								instanceGroup.push_back (group);
							}
							else
							{
								// Error message and continue
								nlwarning ("WARNING can't load instance group %s\n", name.c_str());
							}
						}
					}
				}

				// A vector of CInstanceLighter::CTriangle
				vector<CInstanceLighter::CTriangle> vectorTriangle;

				// **********
				// *** Build triangle array
				// **********

				landscape->checkBinds ();

				// Add triangles from landscape, for pointLight lighting.
				landscape->enableAutomaticLighting (false);
				lighter.addTriangles (*landscape, listZoneId, 0, vectorTriangle);

				// Load and add shapes

				// Map of shape
				std::map<string, IShape*> shapeMap;

				// For each instance group
				std::list<CInstanceGroup*>::iterator ite=instanceGroup.begin();
				while (ite!=instanceGroup.end())
				{
					// Instance group
					CInstanceGroup *group=*ite;

					// For each instance
					for (uint instance=0; instance<group->getNumInstance(); instance++)
					{
						// Get the instance shape name
						string name=group->getShapeName (instance);

						// Skip it?? use the DontCastShadowForExterior flag. See doc of this flag
						if(group->getInstance(instance).DontCastShadow || group->getInstance(instance).DontCastShadowForExterior)
							continue;

						// Add a .shape at the end ?
						if (!name.empty())
						{
							if (name.find('.') == std::string::npos)
								name += ".shape";

							// Find the file
							string nameLookup = CPath::lookup (name, false, false);
							if (!nameLookup.empty())
								name = nameLookup;

							// Find the shape in the bank
							std::map<string, IShape*>::iterator iteMap=shapeMap.find (name);
							if (iteMap==shapeMap.end())
							{
								// Input file
								CIFile inputFile;

								if (inputFile.open (name))
								{
									// Load it
									CShapeStream stream;
									stream.serial (inputFile);

									// Get the pointer
									iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first;
								}
								else
								{
									// Error
									nlwarning ("WARNING can't load shape %s\n", name.c_str());
								}
							}
							
							// Loaded ?
							if (iteMap!=shapeMap.end())
							{
								// Build the matrix
								CMatrix scale;
								scale.identity ();
								scale.scale (group->getInstanceScale (instance));
								CMatrix rot;
								rot.identity ();
								rot.setRot (group->getInstanceRot (instance));
								CMatrix pos;
								pos.identity ();
								pos.setPos (group->getInstancePos (instance));
								CMatrix mt=pos*rot*scale;

								// If centerInstanceGroup, take good instanceId, to avoid selfShadowing
								sint	instanceId;
								if(group == centerInstanceGroup)
									instanceId= instance;
								else
									instanceId= -1;

								// Add triangles
								lighter.addTriangles (*iteMap->second, mt, vectorTriangle, instanceId);
							}
						}
					}

					// For each point light of the ig
					const std::vector<CPointLightNamed>	&pointLightList= group->getPointLightList();
					for (uint plId=0; plId<pointLightList.size(); plId++)
					{
						// Add it to the Ig.
						lighter.addStaticPointLight(pointLightList[plId], igName.c_str ());
					}

					// Next instance group
					ite++;
				}

				// Continue ?
				if (continu)
				{
					// **********
					// *** Light!
					// **********

					// Start time
					TTime time=CTime::getLocalTime ();

					// Output ig
					CInstanceGroup	output;

					// Light the zone
					lighter.light (*centerInstanceGroup, output, lighterDesc, vectorTriangle, landscape);

					// Compute time
					printf ("\rCompute time: %d ms                                                      \r", 
						(uint)(CTime::getLocalTime ()-time));

					// Save the zone
					COFile outputFile;

					// Open it
					if (outputFile.open (argv[2]))
					{
						try
						{
							// Save the new ig
							outputFile.serial(output);
						}
						catch (const Exception& except)
						{
							// Error message
							nlwarning ("ERROR writing %s: %s\n", argv[2], except.what());
						}
					}
					else
					{
						// Error can't open the file
						nlwarning ("ERROR Can't open %s for writing\n", argv[2]);
					}
				}
				else
				{
					// Error
					nlwarning ("ERROR Abort: files are missing.\n");
				}
			}
			catch (const Exception& except)
			{
				// Error message
				nlwarning ("ERROR %s\n", except.what());
			}
		}
		else
		{
			// Error can't open the file
			nlwarning ("ERROR Can't open %s for reading\n", argv[1]);
		}

	}
	

	// Landscape is not deleted, nor the instanceGroups, for faster quit.
	// Must disalbe BlockMemory checks (for pointLights).
	NL3D_BlockMemoryAssertOnPurge= false;

	// exit.
	return 0;
}
void CRingAccess::init()
{



	if (_Initialised ) { return; } // no double initialisation
	_CustomNpcSheetId.clear();
	//CSheetId::init() must be called first
	_CustomNpcSheetId.insert(CSheetId("basic_matis_male.creature"));
	_CustomNpcSheetId.insert(CSheetId("basic_fyros_male.creature"));
	_CustomNpcSheetId.insert(CSheetId("basic_tryker_male.creature"));
	_CustomNpcSheetId.insert(CSheetId("basic_zorai_male.creature"));

	_CustomNpcSheetId.insert(CSheetId("basic_matis_female.creature"));
	_CustomNpcSheetId.insert(CSheetId("basic_fyros_female.creature"));
	_CustomNpcSheetId.insert(CSheetId("basic_tryker_female.creature"));
	_CustomNpcSheetId.insert(CSheetId("basic_zorai_female.creature"));


	for (uint32 i = 0 ; i <= 184 ; ++i)
	{
		_R2PlotItemSheetId.insert( CSheetId( NLMISC::toString("r2_plot_item_%d.sitem", i)));
	}

	_SheetIdToAccess.clear();//only usefull when manualy re init file
	// File stream
	CIFile file;


	std::string pathFileName = CPath::lookup(RingAccessFilename, false, false, false);
	// Open the file
	if (pathFileName.empty() || !file.open(pathFileName.c_str()))
	{
		nlinfo("Can't open the file for reading : %s", RingAccessFilename.c_str());
		return;
	}



	// Create the XML stream
	CIXml input;

	// Init
	if(input.init(file))
	{
		xmlNodePtr entitiesAccess = input.getRootNode();
		xmlNodePtr entityAccess = input.getFirstChildNode(entitiesAccess, "entityAccess");

		while (entityAccess != 0)
		{

			// island name
			CXMLAutoPtr namePtr( (const char*) xmlGetProp(entityAccess, (xmlChar*) "name") );
			CXMLAutoPtr packagePtr( (const char*) xmlGetProp(entityAccess, (xmlChar*) "package") );
			CXMLAutoPtr sheetClientPtr( (const char*) xmlGetProp(entityAccess, (xmlChar*) "sheetClient") );
			CXMLAutoPtr sheetPtr( (const char*) xmlGetProp(entityAccess, (xmlChar*) "sheetServer") );

			if (!namePtr.getDatas()|| !packagePtr.getDatas() || !sheetPtr.getDatas() || !sheetPtr.getDatas())
			{
				nlerror( "Syntax error in %s", pathFileName.c_str());
				return;
			}

			std::string sheet( sheetPtr.getDatas() );
			std::string package( packagePtr.getDatas() );
			std::string sheetClient(sheetClientPtr.getDatas());


			CSheetId sheetClientId(sheetClient);
			CSheetId sheetId; // no sheet server

			if (sheet.empty())
			{
				bool ok = _SheetIdToAccess.insert( std::make_pair(std::make_pair(sheetClientId, sheetId), package)).second;
				if (!ok)
				{
					std::string previousPackage = _SheetIdToAccess[std::make_pair(sheetClientId, sheetId)];
					// only display warning if one key has multiple package
					if ( previousPackage != package )
					{
						nlwarning("%s: Entity %s sheet(%s) is defined more than once with different package definition. Previous definition is '%s', current definition is '%s'", RingAccessFilename.c_str(), namePtr.getDatas(), sheetClientPtr.getDatas(), previousPackage.c_str(), package.c_str());
					}

				}
			}
			else
			{


				sheetId = CSheetId(sheet);
				if (_CustomNpcSheetId.find(sheetClientId) != _CustomNpcSheetId.end())
				{

					bool ok = _SheetIdToAccess.insert( std::make_pair(std::make_pair(sheetClientId, sheetId), package)).second;
					if (!ok)
					{
						std::string previousPackage = _SheetIdToAccess[std::make_pair(sheetClientId, sheetId)];
						// only display warning if one key has multiple package
						if ( previousPackage != package )
						{
							nlwarning("%s: Entity %s sheet(%s) is defined more than once. Previous definition is '%s', current definition is '%s'", RingAccessFilename.c_str(), namePtr.getDatas(), sheetPtr.getDatas(), previousPackage.c_str(), package.c_str());
						}
					}
				}
				else
				{
					nlwarning("%s: Entity %s has invalid sheets %s %s", RingAccessFilename.c_str(), namePtr.getDatas(), sheetClientPtr.getDatas(), sheetPtr.getDatas());
				}
			}


			entityAccess = input.getNextChildNode(entityAccess, "entityAccess");
		}
	}

	// Close the file
	file.close ();

	_Initialised = true;

}
// ***************************************************************************
int main(int argc, char* argv[])
{
	// Register 3d
	registerSerial3d ();

	// Avoid some stupids warnings.
	NLMISC::createDebug();
	skipLog("variable \"RootConfigFilename\"");
	skipLog("variable \"anim_low_precision_tracks\"");
	skipLog("variable \"anim_sample_rate\"");
	InfoLog->addNegativeFilter("FEHTIMER>");
	InfoLog->addNegativeFilter("adding the path");


	// Good number of args ?
	if (argc<4)
	{
		// Help message
		printf ("anim_builder [directoryIn] [pathOut] [parameter_file] \n");
	}
	else
	{
		try
		{
			string	directoryIn= argv[1];
			string	pathOut= argv[2];
			string	paramFile= argv[3];

			// Verify directoryIn.
			directoryIn= CPath::standardizePath(directoryIn);
			if( !CFile::isDirectory(directoryIn) )
			{
				printf("DirectoryIn %s is not a directory", directoryIn.c_str());
				return -1;
			}
			// Verify pathOut.
			pathOut= CPath::standardizePath(pathOut);
			if( !CFile::isDirectory(pathOut) )
			{
				printf("PathOut %s is not a directory", pathOut.c_str());
				return -1;
			}

			// Our Animation optimizer.
			//=================
			CAnimationOptimizer		animationOptimizer;
			// Leave thresholds as default.
			animationOptimizer.clearLowPrecisionTracks();


			// Load and setup configFile.
			//=================
			CConfigFile parameter;
			// Load and parse the param file
			parameter.load (paramFile);

			// Get the Low Precision Track Key Names
			try
			{
				CConfigFile::CVar &anim_low_precision_tracks = parameter.getVar ("anim_low_precision_tracks");
				uint lpt;
				for (lpt = 0; lpt < (uint)anim_low_precision_tracks.size(); lpt++)
				{
					animationOptimizer.addLowPrecisionTrack(anim_low_precision_tracks.asString(lpt));
				}
			}
			catch(EUnknownVar &)
			{
				nlwarning("\"anim_low_precision_tracks\" not found in the parameter file. Add \"Finger\" and \"Ponytail\" by default");
				animationOptimizer.addLowPrecisionTrack("Finger");
				animationOptimizer.addLowPrecisionTrack("Ponytail");
			}

			// Sample Rate.
			try
			{
				CConfigFile::CVar &anim_sample_rate = parameter.getVar ("anim_sample_rate");
				float	sr= anim_sample_rate.asFloat(0);
				// Consider values > 1000 as error values.
				if(sr<=0 || sr>1000)
				{
					nlwarning("Bad \"anim_sample_rate\" value. Use Default of 30 fps.");
					animationOptimizer.setSampleFrameRate(30);
				}
				else
				{
					animationOptimizer.setSampleFrameRate(sr);
				}
			}
			catch(EUnknownVar &)
			{
				nlwarning("\"anim_sample_rate\" not found in the parameter file. Use Default of 30 fps.");
				animationOptimizer.setSampleFrameRate(30);
			}


			// Scan and load all files .ig in directories
			//=================
			uint		numSkipped= 0;
			uint		numBuilded= 0;
			vector<string>				listFile;
			CPath::getPathContent(directoryIn, false, false, true, listFile);
			for(uint iFile=0; iFile<listFile.size(); iFile++)
			{
				string	&igFile= listFile[iFile];
				// verify it is a .anim.
				if( CFile::getExtension(igFile) == "anim" )
				{
					string	fileNameIn= CFile::getFilename(igFile);
					string	fileNameOut= pathOut + fileNameIn;

					// skip the file?
					bool	mustSkip= false;

					// If File Out exist 
					if(CFile::fileExists(fileNameOut))
					{
						// If newer than file In, skip
						uint32		fileOutDate= CFile::getFileModificationDate(fileNameOut);
						if(	fileOutDate > CFile::getFileModificationDate(igFile) )
						{
							mustSkip= true;
						}
					}

					// If must process the file.
					if(!mustSkip)
					{
						// Read the animation.
						CAnimation	animIn;
						CIFile	fin;
						fin.open(CPath::lookup(igFile));
						fin.serial(animIn);

						// process.
						CAnimation	animOut;
						animationOptimizer.optimize(animIn, animOut);

						// Save this animation.
						COFile	fout;
						fout.open(fileNameOut);
						fout.serial(animOut);
						fout.close();

						numBuilded++;
					}
					else
					{
						numSkipped++;
					}

					// progress
					printf("Anim builded: %4d. Anim Skipped: %4d\r", numBuilded, numSkipped);
				}
			}

			// Add some info in the log.
			nlinfo("Anim builded: %4d", numBuilded);
			nlinfo("Anim skipped: %4d", numSkipped);

		}
		catch (Exception& except)
		{
			// Error message
			nlwarning ("ERROR %s\n", except.what());
		}
	}

	// exit.
	return 0;
}
Ejemplo n.º 12
0
/*
 *		init()
 */
bool	CPrimChecker::build(const string &primitivesPath, const string &igLandPath, const string &igVillagePath, const string &outputDirectory, bool forceRebuild)
{
	if (Verbose)
		nlinfo("Checking pacs.packed_prims consistency");

	NLLIGO::Register();

	// Init ligo
	if (!LigoConfig.readPrimitiveClass ("world_editor_classes.xml", false))
	{
		// Should be in l:\leveldesign\world_edit_files
		nlwarning ("Can't load ligo primitive config file world_editor_classes.xml");
		return false;
	}

	uint	i, j;
	string	outputfname = CPath::standardizePath(outputDirectory)+"pacs.packed_prims";

	_Grid.clear();

	vector<string>	files;
	CPath::getPathContent(primitivesPath, true, false, true, files);

	for (i=0; i<files.size(); ++i)
	{
		if (CFile::getExtension(files[i]) == "primitive")
		{
			readFile(files[i]);
		}
	}

	files.clear();
	CPath::getPathContent(igLandPath, true, false, true, files);
	CPath::getPathContent(igVillagePath, true, false, true, files);

	set<string>		noWaterShapes;

	for (i=0; i<files.size(); ++i)
	{
		try
		{
			// load ig associated to the zone
			string	igname = files[i];

			string	ignamelookup = CPath::lookup(igname);
			//nlinfo("Reading ig '%s'", ignamelookup.c_str());
			CIFile			igStream(ignamelookup);
			CInstanceGroup	ig;
			igStream.serial(ig);

			// search in group for water instance
			for (j=0; j<ig._InstancesInfos.size(); ++j)
			{
				string	shapeName = ig._InstancesInfos[j].Name;
				if (CFile::getExtension (shapeName) == "")
					shapeName += ".shape";

				if (noWaterShapes.find(shapeName) != noWaterShapes.end())
					continue;

				string	shapeNameLookup = CPath::lookup (shapeName, false, false);
				if (!shapeNameLookup.empty())
				{
					CIFile			f;
					if (f.open (shapeNameLookup))
					{
						CShapeStream	shape;
						shape.serial(f);

						CWaterShape	*wshape = dynamic_cast<CWaterShape*>(shape.getShapePointer());
						if (wshape == NULL)
						{
							noWaterShapes.insert(shapeName);
							continue;
						}

						//nlinfo("Render water shape '%s'", shapeNameLookup.c_str());

						CMatrix	matrix;
						ig.getInstanceMatrix(j, matrix);

						CPolygon			wpoly;
						//wshape->getShapeInWorldSpace(wpoly);
						CPolygon2D			wpoly2d = wshape->getShape();

						uint	k;
						for (k=0; k<wpoly2d.Vertices.size(); ++k)
						{
							wpoly.Vertices.push_back(matrix * wpoly2d.Vertices[k]);
						}

						float	zwater = wpoly.Vertices[0].z - WaterThreshold;
						uint16	idx = (uint16)_WaterHeight.size();
						_WaterHeight.push_back(zwater);
						render(wpoly, idx);

						if (Verbose)
							nlinfo("Rendered water shape '%s' in instance '%s'", CFile::getFilenameWithoutExtension(shapeName).c_str(), CFile::getFilenameWithoutExtension(igname).c_str());
					}
					else if (Verbose)
					{
						noWaterShapes.insert(shapeName);
						nlwarning ("Can't load shape %s", shapeNameLookup.c_str());
					}
				}
				else if (Verbose)
				{
					noWaterShapes.insert(shapeName);
					nlwarning ("Can't find shape %s", shapeName.c_str());
				}
			}
		}
		catch (const Exception &e)
		{
			nlwarning("%s", e.what());
		}
	}

	COFile	f;
	if (f.open(outputfname))
	{
		f.serial(_Grid);
		f.serialCont(_WaterHeight);
	}
	else
	{
		nlwarning("Couldn't save pacs.packed_prims file '%s'", outputfname.c_str());
	}

	return true;
}
Ejemplo n.º 13
0
// ***************************************************************************
void	makeAnimByRace(const std::string &animSetFile, const std::vector<string> &animList)
{
	// *** Read the animset file.
	CIFile	iFile;
	iFile.open(animSetFile, true);
	// Read all text
	static vector<string>	animSetText;
	animSetText.clear();
	while(!iFile.eof())
	{
		char	tmp[50000];
		iFile.getline(tmp, 50000);
		animSetText.push_back(tmp);
	}
	iFile.close();


	bool	someChangeDone= false;

	// *** For each possible anim
	for(uint i=0;i<animList.size();i++)
	{
		// get the possible anim file name (lowered)
		static vector<string>	raceAnimNames;
		raceAnimNames.clear();
		buildRaceAnimNames(raceAnimNames, toLower(CFile::getFilename(animList[i])));

		// For each line of the animSet
		uint	lastStructLine= 0;
		bool	raceRestrictionFound= false;
		for(uint j=0;j<animSetText.size();)
		{
			string	line= animSetText[j];
			string	lineLwr= toLower(line);

			// Find <LOG> TAg? => stop
			if(line.find("<LOG>")!=string::npos)
				break;

			// Find a STRUCT start?
			if(line.find("<STRUCT>")!=string::npos)
			{
				lastStructLine= j;
				raceRestrictionFound= false;
			}
			
			// Find a RaceRestriction?
			if( line.find("Name=\"Race Restriction\"")!=string::npos )
				raceRestrictionFound= true;

			// Find the anim name?
			uint	nameIndexInLine= findAnimName(lineLwr, raceAnimNames);
			if(nameIndexInLine!=-1)
			{
				// Find the enclosing struct
				nlassert(lastStructLine!=0);
				uint	startBlock= lastStructLine;
				uint	nameLineInBlock= j-startBlock;
				uint	endBlock= 0;
				for(uint k=j+1;k<animSetText.size();k++)
				{
					string	line= animSetText[k];

					// Find a RaceRestriction?
					if( line.find("Name=\"Race Restriction\"")!=string::npos )
						raceRestrictionFound= true;

					// end of block?
					if(line.find("</STRUCT>")!=string::npos)
					{
						// endBlock is exclusive 
						endBlock= k+1;
						break;
					}
				}

				// if not found, abort
				if(endBlock==0)
					break;

				// if a raceRestriction has been found, no op (already done)
				if(raceRestrictionFound)
				{
					j= endBlock;
				}
				else
				{
					// LOG
					InfoLog->displayRawNL("%s: Specifying %s by race", 
						CFile::getFilename(animSetFile).c_str(), 
						CFile::getFilename(animList[i]).c_str());

					// *** Start a copy paste ^^
					// Copy
					static vector<string>	copyText;
					copyText.clear();
					for(uint k=startBlock;k<endBlock;k++)
					{
						// add an empty line before </STRUCT>, for race selection node (filled later)
						if(k==endBlock-1)
							copyText.push_back(string());
						copyText.push_back(animSetText[k]);
					}

					// erase this part
					animSetText.erase(animSetText.begin()+startBlock, animSetText.begin()+endBlock);
					uint	nextBlock= startBlock;

					// Append for each race
					for(uint k=0;k<raceAnimNames.size();k++)
					{
						appendRaceAnim(animSetText, nextBlock, copyText, nameLineInBlock, nameIndexInLine, raceAnimNames[k]);
						// nextBlock is then shifted
						nextBlock+= copyText.size();
					}

					someChangeDone= true;

					// *** then let j point to next block
					j= nextBlock;
				}
			}
			else
			{
				j++;
			}
		}
	}

	// *** Write the animset file.
	if(someChangeDone)
	{
		COFile	oFile;
		oFile.open(animSetFile, false, true);
		// Write all text
		for(uint i=0;i<animSetText.size();i++)
		{
			string	str= animSetText[i];
			str+= "\n";
			oFile.serialBuffer((uint8*)str.c_str(), str.size());
		}
	}
}
Ejemplo n.º 14
0
void Browse::OnImportBorder() 
{
	// Select a file
	CFileDialog sFile (true, NULL, NULL, OFN_ENABLESIZING,
		"Targa bitmap (*.tga)|*.tga|All files (*.*)|*.*||",NULL);
	if (sFile.DoModal()==IDOK)
	{
		// Get the border of the bank
		std::vector<NLMISC::CBGRA> array(128*128);

		// The bitmap
		NLMISC::CBitmap bitmap;

		// Read the bitmap
		bool error=false;
		CString pathName=sFile.GetPathName();
		try
		{
			CIFile file;
			if (file.open ((const char*)pathName))
			{
				// Export
				bitmap.load (file);
			}
			else
				error=true;
		}
		catch (Exception& e)
		{
			const char *toto=e.what ();
			error=true;
		}

		// Error during import ?
		if (error)
		{
			// Error message
			char tmp[512];
			sprintf (tmp, "Can't read bitmap %s", (const char*)pathName);
			MessageBox (tmp, "Import border", MB_OK|MB_ICONEXCLAMATION);
		}

		// Get pixel
		CRGBA *pPixel=(CRGBA*)&bitmap.getPixels()[0];

		// Good size
		if ((bitmap.getWidth()==128)&&(bitmap.getHeight()==128))
		{
			// Make a copy
			for (int i=0; i<128*128; i++)
			{
				// Copy the pixel
				array[i].R=pPixel->R;
				array[i].G=pPixel->G;
				array[i].B=pPixel->B;
				array[i].A=pPixel->A;
				pPixel++;
			}
		}
		else
		{
			// Error message
			char tmp[512];
			sprintf (tmp, "The bitmap must have a size of 128x128 (%s)", (const char*)pathName);
			MessageBox (tmp, "Import border", MB_OK|MB_ICONEXCLAMATION);
		}

		// 256 or 128 ?
		CTileBorder border;
		border.set (128, 128, array);
		tileBank2.getTileSet (land)->setBorder (m_ctrl.Texture==1?CTile::diffuse:CTile::additive, border);

		// Message
		MessageBox ("The border has been changed.", "Import border", MB_OK|MB_ICONINFORMATION);
	}
}
Ejemplo n.º 15
0
// ---------------------------------------------------------------------------
int main(int nNbArg, char**ppArgs)
{
	if (!NLMISC::INelContext::isContextInitialised())
		new CApplicationContext();

	NL3D_BlockMemoryAssertOnPurge = false;
	char sCurDir[MAX_PATH];
	getcwd (sCurDir, MAX_PATH);

	if (nNbArg != 2)
	{
		printf ("Use : ig_elevation configfile.cfg\n");
		printf ("\nExample of config.cfg\n\n");
		printf ("InputIGDir = \"ig_land_max\";\n");
		printf ("OutputIGDir = \"ig_land_max_elev\";\n");
		printf ("CellSize = 160.0;\n");
		printf ("HeightMapFile1 = \"w:/database/landscape/ligo/jungle/big.tga\";\n");
		printf ("ZFactor1 = 1.0;\n");
		printf ("HeightMapFile2 = \"w:/database/landscape/ligo/jungle/noise.tga\";\n");
		printf ("ZFactor2 = 0.5;\n");
		printf ("LandFile = \"w:/matis.land\";\n");

		return -1;
	}

	SExportOptions options;
	if (!options.load(ppArgs[1]))
	{
		return -1;
	}

	// Get all ig files in the input directory and elevate to the z of the double heightmap

	// Load the land
	CZoneRegion *ZoneRegion = loadLand(options.LandFile);

	CZoneLimits zl;
	if (ZoneRegion)
	{
		zl._ZoneMinX = ZoneRegion->getMinX() < 0	? 0		: ZoneRegion->getMinX();
		zl._ZoneMaxX = ZoneRegion->getMaxX() > 255	? 255	: ZoneRegion->getMaxX();
		zl._ZoneMinY = ZoneRegion->getMinY() > 0	? 0		: ZoneRegion->getMinY();
		zl._ZoneMaxY = ZoneRegion->getMaxY() < -255 ? -255	: ZoneRegion->getMaxY();
	}
	else
	{
		nlwarning("A ligo .land file cannot be found");
		zl._ZoneMinX = 0;
		zl._ZoneMaxX = 255;
		zl._ZoneMinY = 0;
		zl._ZoneMaxY = 255;
	}

	// Load the 2 height maps
	CBitmap *HeightMap1 = NULL;
	if (!options.HeightMapFile1.empty())
	{
		HeightMap1 = new CBitmap;
		try 
		{
			CIFile inFile;
			if (inFile.open(options.HeightMapFile1))
			{
				HeightMap1->load (inFile);
			}
			else
			{
				string sTmp = string("Couldn't not open ")+string(options.HeightMapFile1)
					+string(" : heightmap 1 map ignored");
				outString(sTmp);
				delete HeightMap1;
				HeightMap1 = NULL;
			}
		}
		catch (const Exception &e)
		{
			string sTmp = string("Cant load height map : ") + options.HeightMapFile1 + " : " + e.what();
			outString (sTmp);
			delete HeightMap1;
			HeightMap1 = NULL;
		}
	}
	CBitmap *HeightMap2 = NULL;
	if (!options.HeightMapFile2.empty())
	{
		HeightMap2 = new CBitmap;
		try 
		{
			CIFile inFile;
			if (inFile.open(options.HeightMapFile2))
			{
				HeightMap2->load (inFile);
			}
			else
			{
				string sTmp = string("Couldn't not open ")+string(options.HeightMapFile2)
					+string(" : heightmap 2 map ignored\n");
				outString(sTmp);
				delete HeightMap2;
				HeightMap2 = NULL;
			}
		}
		catch (const Exception &e)
		{
			string sTmp = string("Cant load height map : ") + options.HeightMapFile2 + " : " + e.what() + "\n";
			outString (sTmp);
			delete HeightMap2;
			HeightMap1 = NULL;
		}
	}

	// Get all files
	vector<string> vAllFiles;
	chdir (options.InputIGDir.c_str());
	dir (".ig", vAllFiles, false);
	chdir (sCurDir);

	for (uint32 i = 0; i < vAllFiles.size(); ++i)
	{
		chdir (options.InputIGDir.c_str());
		CInstanceGroup *pIG = LoadInstanceGroup (vAllFiles[i].c_str());
		chdir (sCurDir);
		if (pIG != NULL)
		{
			bool realTimeSunContribution = pIG->getRealTimeSunContribution();
			// For all instances !!!
			CVector vGlobalPos;
			CInstanceGroup::TInstanceArray IA;
			vector<CCluster> Clusters;
			vector<CPortal> Portals;
			vector<CPointLightNamed> PLN;
			pIG->retrieve (vGlobalPos, IA, Clusters, Portals, PLN);

			if (IA.empty() && PLN.empty() && Portals.empty() && Clusters.empty()) continue;


			uint k;

			// elevate instance
			for(k = 0; k < IA.size(); ++k)
			{
				CVector instancePos = vGlobalPos + IA[k].Pos;
				IA[k].Pos.z += getHeightMapZ(instancePos.x, instancePos.y, zl, options, HeightMap1, HeightMap2);
			}

			// lights
			for(k = 0; k < PLN.size(); ++k)
			{
				CVector lightPos = vGlobalPos + PLN[k].getPosition();
				PLN[k].setPosition( PLN[k].getPosition() + getHeightMapZ(lightPos.x, lightPos.y, zl, options, HeightMap1, HeightMap2) * CVector::K);
			}

			// portals
			std::vector<CVector> portal;
			for(k = 0; k < Portals.size(); ++k)
			{
				Portals[k].getPoly(portal);
				if (portal.empty())
				{
					nlwarning("Empty portal found");
					continue;
				}
				// compute mean position of the poly
				CVector meanPos(0, 0, 0);
				uint l;
				for(l = 0; l < portal.size(); ++l)
					meanPos += portal[l];
				meanPos /= (float) portal.size();
				meanPos += vGlobalPos;
				float z = getHeightMapZ(meanPos.x, meanPos.y, zl, options, HeightMap1, HeightMap2);
				for(l = 0; l < portal.size(); ++l)
				{
					portal[l].z += z;
				}
				Portals[k].setPoly(portal);
			}

			// clusters
			std::vector<CPlane> volume;
			CMatrix transMatrix;
			for(k = 0; k < Clusters.size(); ++k)
			{
				CVector clusterPos = vGlobalPos + Clusters[k].getBBox().getCenter();
				float z = getHeightMapZ(clusterPos.x, clusterPos.y, zl, options, HeightMap1, HeightMap2);
				transMatrix.setPos(z * CVector::K);
				Clusters[k].applyMatrix(transMatrix);
			}

			CInstanceGroup *pIGout = new CInstanceGroup;
			pIGout->build (vGlobalPos, IA, Clusters, Portals, PLN);
			pIGout->enableRealTimeSunContribution(realTimeSunContribution);


			chdir (options.OutputIGDir.c_str());
			SaveInstanceGroup (vAllFiles[i].c_str(), pIGout);
			chdir (sCurDir);
			delete pIG;
		}
	}

	return 1;
}
Ejemplo n.º 16
0
int main(int argc, char **argv)
{
	if (argc != 2)
	{
		printf("usage : %s file.ig\n", argv[0]);
		return -1;
	}
	try
	{
		uint k;
		CInstanceGroup ig;
		CIFile inputStream;
		if (!inputStream.open(string(argv[1])))
		{
			printf("unable to open %s\n", argv[1]);
			return -1;
		}
		ig.serial(inputStream);
		printf("Origine\n");
		printf("---------\n");
		CVector gpos = ig.getGlobalPos();
		printf("global pos : x = %.1f, y = %.1f, z =%.1f\n", gpos.x, gpos.y, gpos.z);
		printf("Instances\n");
		printf("---------\n");
		for(k = 0; k < ig._InstancesInfos.size(); ++k)
		{
			printf("instance %s : x = %.1f, y = %.1f, z = %.1f, sx = %.1f, sy = %.1f, sz = %.1f\n", ig._InstancesInfos[k].Name.c_str(), ig._InstancesInfos[k].Pos.x + gpos.x, ig._InstancesInfos[k].Pos.y + gpos.y, ig._InstancesInfos[k].Pos.z + gpos.z, ig._InstancesInfos[k].Scale.x, ig._InstancesInfos[k].Scale.y, ig._InstancesInfos[k].Scale.z);
		}
		printf("\n");
		printf("Lights\n");
		printf("---------\n");
		for(k = 0; k < ig.getNumPointLights(); ++k)
		{
			const CPointLightNamed &pl = ig.getPointLightNamed(k);
			printf("light group = %d, anim = \"%s\" x = %.1f, y = %.1f, z = %.1f\n", pl.LightGroup, pl.AnimatedLight.c_str(), pl.getPosition().x + gpos.x, pl.getPosition().y + gpos.y, pl.getPosition().z + gpos.z);
		}
		printf("---------\n");
		printf("Realtime sun contribution = %s\n", ig.getRealTimeSunContribution() ? "on" : "off");
		printf("---------\n");
		// IGSurfaceLight info.
		const CIGSurfaceLight::TRetrieverGridMap	&rgm= ig.getIGSurfaceLight().getRetrieverGridMap();
		printf("IGSurfaceLighting: CellSize: %f. NumGridRetriever: %u\n", 
			ig.getIGSurfaceLight().getCellSize(), (uint)rgm.size() );
		uint	rgmInst= 0;
		uint	totalCells= 0;
		CIGSurfaceLight::TRetrieverGridMap::const_iterator	it= rgm.begin();
		for(;it!=rgm.end();it++)
		{
			for(uint i=0;i<it->second.Grids.size();i++)
			{
				printf("grid(%d, %d): %dx%d\n", rgmInst, i, it->second.Grids[i].Width, it->second.Grids[i].Height );
				totalCells+= it->second.Grids[i].Cells.size();
			}
			rgmInst++;
		}
		printf("TotalCells: %d\n", totalCells);

	}
	catch (const std::exception &e)
	{
		printf("%s\n", e.what());
	}
}
// ***************************************************************************
void	CIgLighterLib::lightIg(CInstanceLighter &instanceLighter,
	const CInstanceGroup &igIn, CInstanceGroup &igOut, CInstanceLighter::CLightDesc &lightDesc, 
	CSurfaceLightingInfo &slInfo, const char *igName)
{
	sint				i;


	// Setup.
	//=======
	// Init
	instanceLighter.init();

	// For interiors ig, disable Sun contrib according to ig.
	lightDesc.DisableSunContribution= !igIn.getRealTimeSunContribution();
	// Copy it to igOut, just to keep same setup data for in and out.
	igOut.enableRealTimeSunContribution(!lightDesc.DisableSunContribution);


	// Add obstacles.
	std::vector<CInstanceLighter::CTriangle>	obstacles;
	// only if Shadowing On.
	if(lightDesc.Shadow)
	{
		// Map of shape to load
		std::map<string, IShape*> shapeMap;

		// For all instances of igIn.
		for(i=0; i<(sint)igIn.getNumInstance();i++)
		{
			// progress
			instanceLighter.progress("Loading Shapes obstacles", float(i)/igIn.getNumInstance());

			// Skip it?? IgLighterLib use the DontCastShadowForInterior flag. See doc of this flag
			if(igIn.getInstance(i).DontCastShadow || igIn.getInstance(i).DontCastShadowForInterior)
				continue;

			// Get the instance shape name
			string name= igIn.getShapeName(i);
			bool	shapeFound= true;

			// Try to find the shape in the UseShapeMap.
			std::map<string, IShape*>::const_iterator iteMap= lightDesc.UserShapeMap.find (name);

			// If not found in userShape map, try to load it from the temp loaded ShapeBank.
			if( iteMap == lightDesc.UserShapeMap.end() )
			{
				// Add a .shape at the end ?
				if (name.find('.') == std::string::npos)
					name += ".shape";

				// Lookup the file
				string nameLookup = CPath::lookup (name, false, false);
				if (!nameLookup.empty())
					name = nameLookup;

				// Find the shape in the bank
				iteMap= shapeMap.find (name);
				if (iteMap==shapeMap.end())
				{
					// Input file
					CIFile inputFile;

					if (inputFile.open (name))
					{
						// Load it
						CShapeStream stream;
						stream.serial (inputFile);

						// Get the pointer
						iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first;
					}
					else
					{
						// Error
						nlwarning ("WARNING can't load shape %s\n", name.c_str());
						shapeFound= false;
					}
				}
			}

			if(shapeFound)
			{
				CMatrix		matInst;
				matInst.setPos(igIn.getInstancePos(i));
				matInst.setRot(igIn.getInstanceRot(i));
				matInst.scale(igIn.getInstanceScale(i));
				// Add triangles of this shape
				CInstanceLighter::addTriangles(*iteMap->second, matInst, obstacles, i);
			}

		}

		// Clean Up shapes.
		//-----------
		std::map<string, IShape*>::iterator iteMap;
		iteMap= shapeMap.begin();
		while(iteMap!= shapeMap.end())
		{
			// delte shape
			delete	iteMap->second;
			// delete entry in map
			shapeMap.erase(iteMap);
			// next
			iteMap= shapeMap.begin();
		}
	}

	// Add pointLights of the IG.
	for(i=0; i<(sint)igIn.getPointLightList().size();i++)
	{
		instanceLighter.addStaticPointLight( igIn.getPointLightList()[i], igName );
	}


	// Setup a CIGSurfaceLightBuild if needed.
	//=======
	CIGSurfaceLightBuild	*igSurfaceLightBuild= NULL;
	CGlobalRetriever		*globalRetriever= slInfo.GlobalRetriever;
	CRetrieverBank			*retrieverBank= slInfo.RetrieverBank;
	float	cellSurfaceLightSize= slInfo.CellSurfaceLightSize;
	if(retrieverBank && globalRetriever)
	{
		igSurfaceLightBuild= new CIGSurfaceLightBuild;
		igSurfaceLightBuild->CellSize= cellSurfaceLightSize;
		// col Identifier.
		string	colIdent= slInfo.ColIdentifierPrefix + slInfo.IgFileName + slInfo.ColIdentifierSuffix;

		// For any retreiverInstance with this identifier.
		//----------------
		uint	numInstances= (uint)globalRetriever->getInstances().size();
		for(uint instanceId=0; instanceId<numInstances; instanceId++)
		{
			const CRetrieverInstance	&instance= globalRetriever->getInstance(instanceId);
			// If this instance is an interior
			if ( instance.getType() == CLocalRetriever::Interior )
			{
				uint					localRetrieverId= instance.getRetrieverId();
				const CLocalRetriever	&localRetriever= retrieverBank->getRetriever(localRetrieverId);
				// get the identifer of this localRetriever
				string	retIdent= localRetriever.getIdentifier();

				// Match the ident??
				if( retIdent.find(colIdent)!=string::npos )
				{
					// check CRetrieverLightGrid not already present
					CIGSurfaceLightBuild::ItRetrieverGridMap	itRgm;
					itRgm= igSurfaceLightBuild->RetrieverGridMap.find(localRetrieverId);
					if( itRgm != igSurfaceLightBuild->RetrieverGridMap.end() )
					{
						nlwarning ("ERROR Found 2 different collision retriever with same identifier: '%s'. The 2nd is discared\n", retIdent.c_str());
					}
					else
					{
						// Append CRetrieverLightGrid.
						itRgm= igSurfaceLightBuild->RetrieverGridMap.insert(
							make_pair(localRetrieverId, CIGSurfaceLightBuild::CRetrieverLightGrid() ) ).first;
						CIGSurfaceLightBuild::CRetrieverLightGrid	&rlg= itRgm->second;

						// Resize Grids.
						uint	numSurfaces= (uint)localRetriever.getSurfaces().size();
						rlg.Grids.resize( numSurfaces );

						// Compute the bbox for all surfaces. (NB: local to the localRetriever).
						vector<CAABBox>		surfaceBBoxes;
						localRetriever.buildInteriorSurfaceBBoxes(surfaceBBoxes);

						// For each surface, compute it.
						for(uint surfaceId=0; surfaceId<numSurfaces; surfaceId++)
						{
							// Progress.
							char	stmp[256];
							sprintf(stmp, "Sample surfaces of %s", retIdent.c_str());
							instanceLighter.progress(stmp, surfaceId / float(numSurfaces));

							// Compute surface and size of the grid.
							CIGSurfaceLightBuild::CSurface		&surfDst= rlg.Grids[surfaceId];

							// Snap Origin on cellSize
							surfDst.Origin= surfaceBBoxes[surfaceId].getMin();
							surfDst.Origin.x= floorf(surfDst.Origin.x/cellSurfaceLightSize) * cellSurfaceLightSize;
							surfDst.Origin.y= floorf(surfDst.Origin.y/cellSurfaceLightSize) * cellSurfaceLightSize;

							// Snap Width / Height on cellSize.
							float	sizex= surfaceBBoxes[surfaceId].getMax().x - surfDst.Origin.x;
							float	sizey= surfaceBBoxes[surfaceId].getMax().y - surfDst.Origin.y;
							surfDst.Width= (uint)floorf(sizex/cellSurfaceLightSize) + 2;
							surfDst.Height= (uint)floorf(sizey/cellSurfaceLightSize) + 2;
							// Get Zcenter.
							float	zCenter= surfaceBBoxes[surfaceId].getCenter().z;

							// Allocate elements.
							surfDst.Cells.resize(surfDst.Width * surfDst.Height);

							// For all elements
							for(sint yCell=0; yCell<(sint)surfDst.Height; yCell++)
							{
								for(sint xCell=0; xCell<(sint)surfDst.Width; xCell++)
								{
									// compute pos of the cell.
									ULocalPosition	localPos;
									localPos.Estimation.x= surfDst.Origin.x + xCell*cellSurfaceLightSize;
									localPos.Estimation.y= surfDst.Origin.y + yCell*cellSurfaceLightSize;
									localPos.Estimation.z= zCenter;

									// snap the pos to the surface.
									localPos.Surface= surfaceId;
									bool	snapped;
									localRetriever.snapToInteriorGround(localPos, snapped);

									// if snapped then this point is IN the surface.
									CIGSurfaceLightBuild::CCellCorner	&cell= 
										surfDst.Cells[yCell * surfDst.Width + xCell];
									cell.InSurface= snapped;

									// If ok, retrieve the global (ie world) position
									if(snapped)
									{
										// build a valid globalPosition.
										UGlobalPosition	globalPos;
										globalPos.InstanceId= instanceId;
										globalPos.LocalPosition= localPos;
										// retrieve from globalRetriever.
										cell.CenterPos= globalRetriever->getGlobalPosition(globalPos);
										// Add a delta to simulate entity center
										cell.CenterPos.z+= slInfo.CellRaytraceDeltaZ;

										// OverSample
										if(lightDesc.OverSampling==0)
										{
											// No OverSample, just add CenterPos to the samples.
											cell.NumOverSamples= 1;
											cell.OverSamples[0]= cell.CenterPos;
										}
										else
										{
											// OverSample.
											overSampleCell(cell, lightDesc.OverSampling, localRetriever, 
												*globalRetriever, instanceId, localPos, cellSurfaceLightSize, 
												slInfo.CellRaytraceDeltaZ);
											// it is possible that no samples lies in surfaces (small surface).
											// In this case, just copy CenterPos into samples.
											if(cell.NumOverSamples==0)
											{
												cell.NumOverSamples= 1;
												cell.OverSamples[0]= cell.CenterPos;
											}
										}
									}
									else
									{
										// For debug mesh only, get an approximate pos.
										cell.CenterPos= localPos.Estimation + instance.getOrigin();
										cell.CenterPos.z+= slInfo.CellRaytraceDeltaZ;
									}

									// Init cell defaults
									cell.Dilated= false;
									cell.SunContribution= 0;
								}
							}
						}
					}
				}
			}
		}

	}


	// Run.
	//=======
	instanceLighter.light(igIn, igOut, lightDesc, obstacles, NULL, igSurfaceLightBuild);

	// Output a debug mesh??
	if(igSurfaceLightBuild && slInfo.BuildDebugSurfaceShape && !igSurfaceLightBuild->RetrieverGridMap.empty() )
	{
		// Do it for the sun and point lights.
		for(uint i=0;i<2;i++)
		{
			// compute
			CMesh::CMeshBuild			meshBuild;
			CMeshBase::CMeshBaseBuild	meshBaseBuild;
			CVector	deltaPos= CVector::Null;
			deltaPos.z= - slInfo.CellRaytraceDeltaZ + 0.1f;
			// What kind of debug?
			if( i==0 )
				igSurfaceLightBuild->buildSunDebugMesh(meshBuild, meshBaseBuild, deltaPos);
			else
				igSurfaceLightBuild->buildPLDebugMesh(meshBuild, meshBaseBuild, deltaPos, igOut);

			// build
			CMesh	mesh;
			mesh.build(meshBaseBuild, meshBuild);

			// Save.
			CShapeStream	shapeStream;
			shapeStream.setShapePointer(&mesh);
			COFile		file;
			if( i==0 )
				file.open(slInfo.DebugSunName);
			else
				file.open(slInfo.DebugPLName);
			shapeStream.serial(file);
		}
	}


	// Clean.
	//=======
	if(igSurfaceLightBuild)
		delete igSurfaceLightBuild;
}
int	main(int argc, char *argv[])
{
	uint	i;

	// Avoid warnings.
	NLMISC::createDebug();
	DebugLog->addNegativeFilter("Exception will be launched");
	WarningLog->addNegativeFilter("Exception will be launched");
	InfoLog->addNegativeFilter("FEHTIMER>");
	InfoLog->addNegativeFilter("adding the path");

	// Init serial
	registerSerial3d();

	if(argc<4)
	{
		puts("Usage:    build_clod_bank  path_file.cfg  config_file.cfg  destfile.clodbank  [bakeFrameRate=20] ");
		return 0;
	}


	try
	{
		// The bank to fill
		CLodCharacterShapeBank	lodShapeBank;


		// Read the frameRate to process bake of anims
		float	bakeFrameRate= 20;
		if(argc>=5)
		{
			bakeFrameRate= (float)atof(argv[4]);
			if(bakeFrameRate<=1)
			{
				nlwarning("bad bakeFrameRate value, use a default of 20");
				bakeFrameRate= 20;
			}
		}


		// parse the path file.
		//==================

		// try to load the config file.
		CConfigFile pathConfig;
		pathConfig.load (argv[1]);

		// Get the search pathes
		CConfigFile::CVar &search_pathes = pathConfig.getVar ("search_pathes");
		for (i = 0; i < (uint)search_pathes.size(); i++)
		{
			// Add to search path
			CPath::addSearchPath (search_pathes.asString(i));
		}

		// parse the config file.
		//==================

		// try to load the config file.
		CConfigFile config;
		config.load (argv[2]);

		// For all .clod to process
		//==================
		CConfigFile::CVar &clod_list = config.getVar ("clod_list");
		uint	lodId;
		for (lodId = 0; lodId < (uint)clod_list.size(); lodId++)
		{
			string	lodName= clod_list.asString(lodId);

			printf("Process LOD: %s\n", lodName.c_str());

			// Search the variable with this name.
			try
			{
				CIFile		iFile;

				// get the anim list.
				CConfigFile::CVar &clod_anim_list = config.getVar (lodName);

				// Correct format?
				if(clod_anim_list.size()<3)
				{
					nlwarning("%s skipped. Must have at least the skeleton file name, the lod file name, and one animation", lodName.c_str());
					// go to next.
					continue;
				}

				// Init lod shape process
				//===========================

				// The first variable is the name of the skeleton.
				string	skeletonName= clod_anim_list.asString(0);
				CSmartPtr<CSkeletonShape>	skeletonShape;

				// Load it.
				iFile.open(CPath::lookup(skeletonName));
				CShapeStream		strShape;
				strShape.serial(iFile);
				iFile.close();

				// Get the pointer, check it's a skeleton
				if(dynamic_cast<CSkeletonShape*>(strShape.getShapePointer()) == NULL)
					throw Exception("%s is not a Skeleton", skeletonName.c_str());
				skeletonShape= (CSkeletonShape*)strShape.getShapePointer();

				// The second var is the filename of the lod.
				string	lodFileName= clod_anim_list.asString(1);

				// Load the shape.
				CLodCharacterShapeBuild		lodShapeBuild;
				iFile.open( CPath::lookup(lodFileName) );
				iFile.serial(lodShapeBuild);
				iFile.close();

				// Prepare to build the lod.
				CLodCharacterBuilder		lodBuilder;
				lodBuilder.setShape(lodName, skeletonShape, &lodShapeBuild);


				// Traverse all anim in the list.
				//===========================
				uint	animId;
				for (animId = 2; animId < (uint)clod_anim_list.size(); animId++)
				{
					string	animFileName= clod_anim_list.asString(animId);

					// display.
					printf("Process Anim: %d/%d\r", animId-1, clod_anim_list.size()-2);

					// Try to load the animation
					CAnimation			*anim= new CAnimation;
					// NB: continue, to list all ANIM if anim not found
					try
					{
						iFile.open( CPath::lookup(animFileName) );
						iFile.serial(*anim);
						iFile.close();
						// Add to the builder. NB: animation will be delete in this method.
						// NB: the key name here is the entire file, with the .anim, for easier georges editing.
						lodBuilder.addAnim(animFileName.c_str(), anim, bakeFrameRate);
					}
					catch(EPathNotFound &)
					{
						printf("ERROR anim not found %s\n", animFileName.c_str());
						delete	anim;
					}
				}
				printf("\n");

				// Add to the bank.
				//===========================
				uint32	shapeId= lodShapeBank.addShape();
				*lodShapeBank.getShapeFullAcces(shapeId)= lodBuilder.getLodShape();
			}
			catch(EUnknownVar &evar)
			{
				nlwarning(evar.what());
				// Any other exception will make the program quit.
			}

		}

		// Save bank.
		//===========================

		// compile
		lodShapeBank.compile();

		// Save
		COFile	oFile(argv[3]);
		oFile.serial(lodShapeBank);
		oFile.close();
	}
	catch (Exception& except)
	{
		// Error message
		printf ("ERROR %s.\n Aborting.\n", except.what());
	}


	return 0;
}
Ejemplo n.º 19
0
int main(int argc, char **argv)
{
	// Filter addSearchPath
	NLMISC::createDebug();
	InfoLog->addNegativeFilter("adding the path");

	createDebug();

	try
	{
		// Init
		init();

		uint	i, j, k;

		for (i=0; i<IGs.size(); ++i)
		{
			// load ig associated to the zone
			string			igName = IGs[i]+".ig";
			CIFile			igStream(CPath::lookup(igName));
			CInstanceGroup	ig;
			igStream.serial(ig);

			CAABBox			igBBox;
			bool			boxSet = false;

			nlinfo("Generating BBOX for %s", igName.c_str());

			// search in group for water instance
			for (j=0; j<ig._InstancesInfos.size(); ++j)
			{
				/*
				   Ben: c'est degueulasse, mais c'est les coders a la 3D, y savent pas coder
				   Hld: ouai, mais ca marche pas ton truc, alors p'tet qu'on sait pas coder mais toi non plus :p Special Dedicace to SupaGreg!
				string	shapeName = ig._InstancesInfos[j].Name+".shape";
				*/
				string	shapeName = ig._InstancesInfos[j].Name;
				if (CFile::getExtension (shapeName) == "")
					shapeName += ".shape";

				if (NonWaterShapes.find(shapeName) != NonWaterShapes.end())
					continue;

				string	shapeNameLookup = CPath::lookup (shapeName, false, false);
				if (!shapeNameLookup.empty())
				{
					CIFile			f;
					if (f.open (shapeNameLookup))
					{
						CShapeStream	shape;
						shape.serial(f);

						CWaterShape	*wshape = dynamic_cast<CWaterShape *>(shape.getShapePointer());
						if (wshape == NULL)
						{
							NonWaterShapes.insert(shapeName);
							continue;
						}

						CMatrix	matrix;
						ig.getInstanceMatrix(j, matrix);

						CPolygon			wpoly;
						wshape->getShapeInWorldSpace(wpoly);

						for (k=0; k<wpoly.Vertices.size(); ++k)
						{
							if (boxSet)
							{
								igBBox.extend(matrix * wpoly.Vertices[k]);
							}
							else
							{
								igBBox.setCenter(matrix * wpoly.Vertices[k]);
								boxSet = true;
							}
						}
					}
					else
					{
						nlwarning ("Can't load shape %s", shapeNameLookup.c_str());
					}
				}
				else
				{
					NonWaterShapes.insert(shapeName);
				}
			}

			if (boxSet)
			{
				Boxes.push_back(CIGBox(igName, igBBox));
				nlinfo("Bbox: (%.1f,%.1f)-(%.1f,%.1f)", igBBox.getMin().x, igBBox.getMin().y, igBBox.getMax().x, igBBox.getMax().y);
			}
		}

		COFile	output(Output);
		output.serialCont(Boxes);
	}
	catch (Exception &e)
	{
		fprintf (stderr,"main trapped an exception: '%s'\n", e.what ());
	}
#ifndef NL_DEBUG
	catch (...)
	{
		fprintf(stderr,"main trapped an unknown exception\n");
	}
#endif // NL_DEBUG

	return 0;
}
Ejemplo n.º 20
0
// ***************************************************************************
void	makeAnimMeleeImpact(const std::string &animSetFile, const set<CAnimCombatSet> &combatAnimSets)
{
	// look if this animSetFile is in the combat list to patch
	string	shortName= CFile::getFilenameWithoutExtension(animSetFile);
	strlwr(shortName);
	CAnimCombatSet	key;
	key.Name= shortName;
	set<CAnimCombatSet>::const_iterator	it= combatAnimSets.find(key);
	if(it == combatAnimSets.end())
		return;

	const CAnimCombatSet	&currentCombatAnimSet= *it;

	InfoLog->displayRawNL("patching %s", animSetFile.c_str());


	// *** Read the animset file.
	CIFile	iFile;
	iFile.open(animSetFile, true);
	// Read all text
	static vector<string>	animSetText;
	animSetText.clear();
	while(!iFile.eof())
	{
		char	tmp[50000];
		iFile.getline(tmp, 50000);
		animSetText.push_back(tmp);
	}
	iFile.close();


	bool	someChangeDone= false;

	// *** Parse the animSet
	{
		// For each line of the animSet
		sint	structLevel= 0;
		sint	meleeImpactDelayLine= -1;
		string	currentStateName;
		for(uint j=0;j<animSetText.size();j++)
		{
			string	line= animSetText[j];
			string	lineLwr= toLower(line);

			// Find <LOG> TAg? => stop
			if(line.find("<LOG>")!=string::npos)
				break;

			// Find a STRUCT start?
			if(line.find("<STRUCT")!=string::npos)
			{
				// inc struct
				structLevel++;

				// if start a new State block
				if(structLevel==2)
				{
					// reset info for this state
					currentStateName.clear();
					meleeImpactDelayLine= -1;
					
					// try to get the name
					const string	tagStart= "name=\"";
					std::string::size_type	start= lineLwr.find(tagStart);
					if(start!=string::npos)
					{
						start+= tagStart.size();
						std::string::size_type	end= lineLwr.find("\"", start);
						if(end!=string::npos)
							currentStateName= lineLwr.substr(start, end-start);
					}
				}
			}

			// Find a STRUCT end?
			if(line.find("</STRUCT>")!=string::npos)
			{
				// if end a state block, may add or replace MeleeDelayImpact
				if(structLevel==2 && !currentStateName.empty())
				{
					// If the state is not in the combat state, no need to patch anything
					static CAnimCombatState		key;
					// must translate for instance "attack1" to "A1"
					key.StateCode= StateNameToStateCode[currentStateName];
					set<CAnimCombatState>::const_iterator		it= currentCombatAnimSet.States.find(key);
					if(it!=currentCombatAnimSet.States.end())
					{
						// else take the mean anim time
						string	format= "      <ATOM Name=\"MeleeImpactDelay\" Value=\"%.3f\"/>";
						string	newLine= toString(format.c_str(), it->MeanAnimTime * MeleeImpactTimeFactor);

						// melee impact delay doesn't exist?
						if(meleeImpactDelayLine==-1)
						{
							// add just before this line the Melee Impact Atom
							animSetText.insert(animSetText.begin()+j, newLine);
							j++;
							someChangeDone= true;
						}
						// else exist and want to replace?
						else if(ReplaceExistingMeleeImpactDelay)
						{
							animSetText[meleeImpactDelayLine]= newLine;
							someChangeDone= true;
						}
					}
				}

				// dec struct level
				structLevel--;
			}
				
			// if we are in level 2 structure, try to get the line to modify (if exist)
			if(structLevel==2)
			{
				if( line.find("Name=\"MeleeImpactDelay\"")!=string::npos )
					meleeImpactDelayLine= j;
			}
		}
	}

	// *** Write the animset file.
	if(someChangeDone)
	{
		COFile	oFile;
		oFile.open(animSetFile, false, true);
		// Write all text
		for(uint i=0;i<animSetText.size();i++)
		{
			string	str= animSetText[i];
			str+= "\n";
			oFile.serialBuffer((uint8*)str.c_str(), (uint)str.size());
		}
	}
}
//TODO titegus: What's the point in Importing a new border if there is no Pixel Compatibility check ?
void CTile_browser_dlg::on_importBorderPushButton_clicked()
{
	QFileDialog::Options options;
	QString selectedFilter;
	QString fileName = QFileDialog::getOpenFileName(this, tr("Choose Bitmap"), QString(tileBankBrowser.getAbsPath().c_str()) , "Targa Bitmap(*.tga);;All Files (*.*);;", &selectedFilter, options);
	
	if (!fileName.isEmpty())
	{
		fileName = QDir::toNativeSeparators(fileName);
		// Get the border of the bank
		std::vector<NLMISC::CBGRA> array(128*128);

		// The bitmap
		NLMISC::CBitmap bitmap;

		// Read the bitmap
		bool error=false;
		try
		{
			CIFile file;
			if (file.open (fileName.toStdString().c_str()))
			{
				// Export
				bitmap.load (file);
			}
			else
				error=true;
		}
		catch (Exception& e)
		{
			const char *toto=e.what ();
			error=true;
		}

		// Error during import ?
		if (error)
		{
			// Error message
			QString s = tr("Can't read bitmap %1").arg(fileName);
			QMessageBox::information (this, tr("Import border"), s);
		}

		// Get pixel
		CRGBA *pPixel=(CRGBA*)&bitmap.getPixels()[0];

		// Good size
		if ((bitmap.getWidth()==128)&&(bitmap.getHeight()==128))
		{
			// Make a copy
			for (int i=0; i<128*128; i++)
			{
				// Copy the pixel
				array[i].R=pPixel->R;
				array[i].G=pPixel->G;
				array[i].B=pPixel->B;
				array[i].A=pPixel->A;
				pPixel++;
			}
		}
		else
		{
			// Error message
			QString s = tr("The bitmap must have a size of 128x128 (%1)").arg(fileName);
			QMessageBox::information (this, tr("Import border"), s);
		}

		// 256 or 128 ?
		CTileBorder border;
		border.set (128, 128, array);
		tileBankBrowser.getTileSet (tileSetIndex)->setBorder ((CTile::TBitmap) tileTextureButtonGroup->checkedId(), border);

		// Message
		QMessageBox::information (this, tr("Import border"), tr("The border has been changed."));
	}

}