1 #include "Terrain.h"
2 #include "radiant_i18n.h"
3 #include "iradiant.h"
4 #include "iselection.h"
5 #include "gtkutil/dialog.h"
6 #include "../../ui/scripteditor/UFOScriptEditor.h"
7 #include "../../brush/BrushVisit.h"
8 #include "../../brush/Face.h"
9 #include "../../brush/FaceInstance.h"
10 
11 #include <string>
12 #include <map>
13 
14 namespace scripts
15 {
Terrain()16 	Terrain::Terrain () :
17 		parser("terrain")
18 	{
19 		_blocks = parser.getEntries();
20 	}
21 
~Terrain()22 	Terrain::~Terrain ()
23 	{
24 	}
25 
26 	namespace
27 	{
28 		static const std::string& TEXTURES = "textures/";
29 		static const std::size_t TEXTURES_LENGTH = TEXTURES.length();
30 
31 		// Functor to add terrain definition to a string stream that is later
32 		// saved to the terrain.ufo script file
33 		class GenerateTerrainForFaces
34 		{
35 			private:
36 
37 				std::stringstream& _os;
38 				Terrain* _terrain;
39 
40 			private:
41 
42 				/**
43 				 * @param terrainID The id that is used in the scripts. In general
44 				 * this is the texture path relative to textures/
45 				 * @return @c true if the terrain definition was already defined
46 				 * in this run, or it is a special texture that is not shown in
47 				 * the game and thus needs no terrain definition.
48 				 */
skipTexture(const std::string & terrainID) const49 				bool skipTexture (const std::string& terrainID) const
50 				{
51 					if (_os.str().find(terrainID) != std::string::npos)
52 						return true;
53 
54 					if (terrainID.find("tex_common/") != std::string::npos)
55 						return true;
56 
57 					return false;
58 				}
59 
60 			public:
GenerateTerrainForFaces(std::stringstream & os,Terrain * terrain)61 				GenerateTerrainForFaces (std::stringstream& os, Terrain* terrain) :
62 					_os(os), _terrain(terrain)
63 				{
64 				}
65 
operator ()(Face & face) const66 				void operator() (Face& face) const
67 				{
68 					const std::string texture = face.GetShader();
69 					std::string terrainID = texture.substr(TEXTURES_LENGTH);
70 					if (skipTexture(terrainID))
71 						return;
72 
73 					const DataBlock* dataBlock = _terrain->getTerrainDefitionForTexture(texture);
74 					if (!dataBlock) {
75 						_os << "terrain " << terrainID << std::endl;
76 						_os << "{" << std::endl;
77 						_os << "//\tfootstepsound\t\"footsteps/grass2\"" << std::endl;
78 						_os << "//\tbouncefraction\t1.0" << std::endl;
79 						_os << "}" << std::endl;
80 					}
81 				}
82 		};
83 	}
84 
generateTerrainDefinitionsForTextures()85 	void Terrain::generateTerrainDefinitionsForTextures ()
86 	{
87 		if (!GlobalSelectionSystem().areFacesSelected()) {
88 			gtkutil::infoDialog(_("No faces selected"));
89 			return;
90 		}
91 
92 		std::stringstream os;
93 		Scene_ForEachSelectedBrushFace(GenerateTerrainForFaces(os, this));
94 		const std::string& newTerrainDefinitions = os.str();
95 		if (newTerrainDefinitions.empty()) {
96 			showTerrainDefinitionForTexture();
97 		} else {
98 			ui::UFOScriptEditor editor("ufos/terrain.ufo", newTerrainDefinitions);
99 			editor.show();
100 		}
101 	}
102 
getTerrainDefitionForTexture(const std::string & texture)103 	const DataBlock* Terrain::getTerrainDefitionForTexture (const std::string& texture)
104 	{
105 		for (Parser::EntriesIterator i = _blocks.begin(); i != _blocks.end(); ++i) {
106 			const DataBlock* blockData = (*i);
107 			const std::string terrainID = TEXTURES + blockData->getID();
108 			if (terrainID == texture)
109 				return blockData;
110 		}
111 		return (DataBlock*) 0;
112 	}
113 
showTerrainDefinitionForTexture()114 	void Terrain::showTerrainDefinitionForTexture ()
115 	{
116 		if (!GlobalSelectionSystem().areFacesSelected()) {
117 			gtkutil::infoDialog(_("No faces selected"));
118 			return;
119 		}
120 
121 		const Face &face = g_SelectedFaceInstances.last().getFace();
122 		const std::string shader = face.GetShader();
123 
124 		const DataBlock* blockData = getTerrainDefitionForTexture(shader);
125 		if (blockData) {
126 			// found it, now show it
127 			ui::UFOScriptEditor editor("ufos/" + blockData->getFilename());
128 			editor.goToLine(blockData->getLineNumber());
129 			editor.show();
130 			return;
131 		}
132 
133 		gtkutil::infoDialog(_("Could not find any associated terrain definition"));
134 	}
135 }
136