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