- Added LocalLcPath to plugin interface
[xonotic/netradiant.git] / contrib / shaderplug / shaderplug.cpp
1 /*\r
2 Copyright (C) 2006, Stefan Greven.\r
3 All Rights Reserved.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 #include "shaderplug.h"\r
23 \r
24 #include "debugging/debugging.h"\r
25 \r
26 #include <string>\r
27 #include <vector>\r
28 #include "string/string.h"\r
29 #include "modulesystem/singletonmodule.h"\r
30 #include "stream/stringstream.h"\r
31 #include "os/file.h"\r
32 \r
33 #include <gtk/gtk.h>\r
34 \r
35 #include "iplugin.h"\r
36 #include "qerplugin.h"\r
37 #include "ifilesystem.h"\r
38 #include "iarchive.h"\r
39 #include "ishaders.h"\r
40 #include "iscriplib.h"\r
41 \r
42 #include "generic/callback.h"\r
43 \r
44 namespace {\r
45 const char SHADERTAG_FILE[] = "shadertags.xml";\r
46 }\r
47 \r
48 class ShaderPlugPluginDependencies : public GlobalRadiantModuleRef,\r
49                                      public GlobalFileSystemModuleRef,\r
50                                      public GlobalShadersModuleRef\r
51 {\r
52 public:\r
53   ShaderPlugPluginDependencies() :\r
54       GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders"))\r
55   {\r
56   }\r
57 };\r
58 \r
59 namespace Shaderplug\r
60 {\r
61   GtkWindow* g_window;\r
62 \r
63   std::vector<const char*> archives;\r
64   std::set<std::string> shaders;\r
65   std::set<std::string> textures;\r
66 \r
67   XmlTagBuilder TagBuilder;\r
68   void CreateTagFile();\r
69 \r
70   const char* init(void* hApp, void* pMainWidget)\r
71   {\r
72     g_window = GTK_WINDOW(pMainWidget);\r
73     return "";\r
74   }\r
75   const char* getName()\r
76   {\r
77     return "ShaderPlug";\r
78   }\r
79   const char* getCommandList()\r
80   {\r
81     return "About;Create tag file";\r
82   }\r
83   const char* getCommandTitleList()\r
84   {\r
85     return "";\r
86   }\r
87   void dispatch(const char* command, float* vMin, float* vMax, bool bSingleBrush)\r
88   {\r
89     if(string_equal(command, "About"))\r
90     {\r
91       GlobalRadiant().m_pfnMessageBox(GTK_WIDGET(g_window), "Shaderplug (1.0)\n\n"\r
92                                         "by Shaderman (shaderman@gmx.net)",\r
93                                         "About",\r
94                                         eMB_OK,\r
95                                         eMB_ICONDEFAULT);\r
96     }\r
97     if(string_equal(command, "Create tag file"))\r
98     {\r
99       CreateTagFile();\r
100     }\r
101   }\r
102 \r
103   void loadArchiveFile(const char* filename)\r
104   {\r
105     archives.push_back(filename);\r
106   }\r
107 \r
108   typedef FreeCaller1<const char*, loadArchiveFile> LoadArchiveFileCaller;\r
109 \r
110   void LoadTextureFile(const char* filename)\r
111   {\r
112     std::string s_filename = filename;\r
113 \r
114     char buffer[256];\r
115     strcpy(buffer, "textures/");\r
116 \r
117     // append filename without trailing file extension (.tga or .jpg for example)\r
118     strncat(buffer, filename, s_filename.length() - 4);\r
119 \r
120     std::set<std::string>::iterator iter;\r
121     iter = shaders.find(buffer);\r
122 \r
123     // a shader with this name already exists\r
124     if(iter == shaders.end())\r
125     {\r
126       textures.insert(buffer);\r
127     }\r
128   }\r
129 \r
130   typedef FreeCaller1<const char*, LoadTextureFile> LoadTextureFileCaller;\r
131 \r
132   void GetTextures(char* extension)\r
133   {\r
134     GlobalFileSystem().forEachFile("textures/", extension, LoadTextureFileCaller(), 0);\r
135   }\r
136 \r
137   void LoadShaderList(const char* filename)\r
138   {\r
139     if(string_equal_prefix(filename, "textures/"))\r
140     {\r
141       shaders.insert(filename);\r
142     }\r
143   }\r
144 \r
145   typedef FreeCaller1<const char*, LoadShaderList> LoadShaderListCaller;\r
146 \r
147   void GetAllShaders()\r
148   {\r
149     GlobalShaderSystem().foreachShaderName(LoadShaderListCaller());\r
150   }\r
151 \r
152   void GetArchiveList()\r
153   {\r
154     GlobalFileSystem().forEachArchive(LoadArchiveFileCaller());\r
155     globalOutputStream() << "Shaderplug: " << (const Unsigned)Shaderplug::archives.size() << " archives found.\n";\r
156   }\r
157 \r
158   void CreateTagFile()\r
159   {\r
160     const char* shader_type = GlobalRadiant().getGameDescriptionKeyValue("shaders");\r
161 \r
162     GetAllShaders();\r
163     globalOutputStream() << "Shaderplug: " << (const Unsigned)shaders.size() << " shaders found.\n";\r
164 \r
165     if(string_equal(shader_type, "quake3"))\r
166     {\r
167       GetTextures("jpg");\r
168       GetTextures("tga");\r
169       GetTextures("png");\r
170 \r
171       globalOutputStream() << "Shaderplug: " << (const Unsigned)textures.size() << " textures found.\n";\r
172     }\r
173 \r
174     if(shaders.size() || textures.size() != 0)\r
175     {\r
176       globalOutputStream() << "Shaderplug: Creating XML tag file.\n";\r
177 \r
178       TagBuilder.CreateXmlDocument();\r
179 \r
180       std::set<std::string>::reverse_iterator r_iter;\r
181 \r
182       for(r_iter = textures.rbegin(); r_iter != textures.rend(); ++r_iter)\r
183       {\r
184         TagBuilder.AddShaderNode(const_cast<char*>((*r_iter).c_str()), STOCK, TEXTURE);\r
185       }\r
186 \r
187       for(r_iter = shaders.rbegin(); r_iter != shaders.rend(); ++r_iter)\r
188       {\r
189         TagBuilder.AddShaderNode(const_cast<char*>((*r_iter).c_str()), STOCK, SHADER);\r
190       }\r
191 \r
192       // Get the tag file         \r
193       StringOutputStream tagFileStream(256);\r
194           tagFileStream << GlobalRadiant().getLocalRcPath() << SHADERTAG_FILE;\r
195       char* tagFile = tagFileStream.c_str();\r
196 \r
197       char message[256];\r
198       strcpy(message, "Tag file saved to\n");\r
199       strcat(message, tagFile);\r
200       strcat(message, "\nPlease restart Radiant now.\n");\r
201 \r
202       if(file_exists(tagFile))\r
203       {\r
204         EMessageBoxReturn result = GlobalRadiant().m_pfnMessageBox(GTK_WIDGET(g_window),\r
205             "WARNING! A tag file already exists! Overwrite it?", "Overwrite tag file?",\r
206             eMB_NOYES,\r
207             eMB_ICONWARNING);\r
208 \r
209         if(result == eIDYES)\r
210         {\r
211           TagBuilder.SaveXmlDoc(tagFile);\r
212           GlobalRadiant().m_pfnMessageBox(GTK_WIDGET(g_window), message, "INFO", eMB_OK, eMB_ICONASTERISK);\r
213         }\r
214       } else {\r
215         TagBuilder.SaveXmlDoc(tagFile);\r
216         GlobalRadiant().m_pfnMessageBox(GTK_WIDGET(g_window), message, "INFO", eMB_OK, eMB_ICONASTERISK);\r
217       }\r
218     } else {\r
219       GlobalRadiant().m_pfnMessageBox(GTK_WIDGET(g_window),\r
220           "No shaders or textures found. No XML tag file created!\n"\r
221           "",\r
222           "ERROR",\r
223           eMB_OK,\r
224           eMB_ICONERROR);\r
225     }\r
226   }\r
227 } // namespace\r
228 \r
229 class ShaderPluginModule\r
230 {\r
231   _QERPluginTable m_plugin;\r
232 public:\r
233   typedef _QERPluginTable Type;\r
234   STRING_CONSTANT(Name, "ShaderPlug");\r
235 \r
236   ShaderPluginModule()\r
237   {\r
238     m_plugin.m_pfnQERPlug_Init = &Shaderplug::init;\r
239     m_plugin.m_pfnQERPlug_GetName = &Shaderplug::getName;\r
240     m_plugin.m_pfnQERPlug_GetCommandList = &Shaderplug::getCommandList;\r
241     m_plugin.m_pfnQERPlug_GetCommandTitleList = &Shaderplug::getCommandTitleList;\r
242     m_plugin.m_pfnQERPlug_Dispatch = &Shaderplug::dispatch;\r
243   }\r
244   _QERPluginTable* getTable()\r
245   {\r
246     return &m_plugin;\r
247   }\r
248 };\r
249 \r
250 typedef SingletonModule<ShaderPluginModule, ShaderPlugPluginDependencies> SingletonShaderPluginModule;\r
251 \r
252 SingletonShaderPluginModule g_ShaderPluginModule;\r
253 \r
254 extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)\r
255 {\r
256   initialiseModule(server);\r
257 \r
258   g_ShaderPluginModule.selfRegister();\r
259 }\r
260 \r
261 \r
262 \r
263 \r