]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/shaderplug/shaderplug.cpp
Merge branch 'fix-fast' into 'master'
[xonotic/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 public:
52     ShaderPlugPluginDependencies() :
53             GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders"))
54     {
55     }
56 };
57
58 namespace Shaderplug {
59     ui::Window g_window{ui::null};
60
61     std::vector<const char *> archives;
62     std::set<std::string> shaders;
63     std::set<std::string> textures;
64
65     XmlTagBuilder TagBuilder;
66
67     void CreateTagFile();
68
69     const char *init(void *hApp, void *pMainWidget)
70     {
71         g_window = ui::Window::from(pMainWidget);
72         return "";
73     }
74
75     const char *getName()
76     {
77         return "ShaderPlug";
78     }
79
80     const char *getCommandList()
81     {
82         return "About;Create tag file";
83     }
84
85     const char *getCommandTitleList()
86     {
87         return "";
88     }
89
90     void dispatch(const char *command, float *vMin, float *vMax, bool bSingleBrush)
91     {
92         if (string_equal(command, "About")) {
93             GlobalRadiant().m_pfnMessageBox(g_window, "Shaderplug (1.0)\n\n"
94                                                     "by Shaderman (shaderman@gmx.net)",
95                                             "About",
96                                             eMB_OK,
97                                             eMB_ICONDEFAULT);
98         }
99         if (string_equal(command, "Create tag file")) {
100             CreateTagFile();
101         }
102     }
103
104     void loadArchiveFile(const char *filename)
105     {
106         archives.push_back(filename);
107     }
108
109     void LoadTextureFile(const char *filename)
110     {
111         std::string s_filename = filename;
112
113         char buffer[256];
114         strcpy(buffer, "textures/");
115
116         // append filename without trailing file extension (.tga or .jpg for example)
117         strncat(buffer, filename, s_filename.length() - 4);
118
119         std::set<std::string>::iterator iter;
120         iter = shaders.find(buffer);
121
122         // a shader with this name already exists
123         if (iter == shaders.end()) {
124             textures.insert(buffer);
125         }
126     }
127
128     void GetTextures(const char *extension)
129     {
130         GlobalFileSystem().forEachFile("textures/", extension, makeCallbackF(LoadTextureFile), 0);
131     }
132
133     void LoadShaderList(const char *filename)
134     {
135         if (string_equal_prefix(filename, "textures/")) {
136             shaders.insert(filename);
137         }
138     }
139
140     void GetAllShaders()
141     {
142         GlobalShaderSystem().foreachShaderName(makeCallbackF(LoadShaderList));
143     }
144
145     void GetArchiveList()
146     {
147         GlobalFileSystem().forEachArchive(makeCallbackF(loadArchiveFile));
148         globalOutputStream() << "Shaderplug: " << (const Unsigned) Shaderplug::archives.size() << " archives found.\n";
149     }
150
151     void CreateTagFile()
152     {
153         const char *shader_type = GlobalRadiant().getGameDescriptionKeyValue("shaders");
154
155         GetAllShaders();
156         globalOutputStream() << "Shaderplug: " << (const Unsigned) shaders.size() << " shaders found.\n";
157
158         if (string_equal(shader_type, "quake3")) {
159             GetTextures("jpg");
160             GetTextures("tga");
161             GetTextures("png");
162
163             globalOutputStream() << "Shaderplug: " << (const Unsigned) textures.size() << " textures found.\n";
164         }
165
166         if (shaders.size() || textures.size() != 0) {
167             globalOutputStream() << "Shaderplug: Creating XML tag file.\n";
168
169             TagBuilder.CreateXmlDocument();
170
171             std::set<std::string>::reverse_iterator r_iter;
172
173             for (r_iter = textures.rbegin(); r_iter != textures.rend(); ++r_iter) {
174                 TagBuilder.AddShaderNode(const_cast<char *>((*r_iter).c_str()), STOCK, TEXTURE);
175             }
176
177             for (r_iter = shaders.rbegin(); r_iter != shaders.rend(); ++r_iter) {
178                 TagBuilder.AddShaderNode(const_cast<char *>((*r_iter).c_str()), STOCK, SHADER);
179             }
180
181             // Get the tag file
182             StringOutputStream tagFileStream(256);
183             tagFileStream << GlobalRadiant().getLocalRcPath() << SHADERTAG_FILE;
184             char *tagFile = tagFileStream.c_str();
185
186             char message[256];
187             strcpy(message, "Tag file saved to\n");
188             strcat(message, tagFile);
189             strcat(message, "\nPlease restart Radiant now.\n");
190
191             if (file_exists(tagFile)) {
192                 EMessageBoxReturn result = GlobalRadiant().m_pfnMessageBox(g_window,
193                                                                            "WARNING! A tag file already exists! Overwrite it?",
194                                                                            "Overwrite tag file?",
195                                                                            eMB_NOYES,
196                                                                            eMB_ICONWARNING);
197
198                 if (result == eIDYES) {
199                     TagBuilder.SaveXmlDoc(tagFile);
200                     GlobalRadiant().m_pfnMessageBox(g_window, message, "INFO", eMB_OK, eMB_ICONASTERISK);
201                 }
202             } else {
203                 TagBuilder.SaveXmlDoc(tagFile);
204                 GlobalRadiant().m_pfnMessageBox(g_window, message, "INFO", eMB_OK, eMB_ICONASTERISK);
205             }
206         } else {
207             GlobalRadiant().m_pfnMessageBox(g_window,
208                                             "No shaders or textures found. No XML tag file created!\n"
209                                                     "",
210                                             "ERROR",
211                                             eMB_OK,
212                                             eMB_ICONERROR);
213         }
214     }
215 } // namespace
216
217 class ShaderPluginModule {
218     _QERPluginTable m_plugin;
219 public:
220     typedef _QERPluginTable Type;
221
222     STRING_CONSTANT(Name, "ShaderPlug");
223
224     ShaderPluginModule()
225     {
226         m_plugin.m_pfnQERPlug_Init = &Shaderplug::init;
227         m_plugin.m_pfnQERPlug_GetName = &Shaderplug::getName;
228         m_plugin.m_pfnQERPlug_GetCommandList = &Shaderplug::getCommandList;
229         m_plugin.m_pfnQERPlug_GetCommandTitleList = &Shaderplug::getCommandTitleList;
230         m_plugin.m_pfnQERPlug_Dispatch = &Shaderplug::dispatch;
231     }
232
233     _QERPluginTable *getTable()
234     {
235         return &m_plugin;
236     }
237 };
238
239 typedef SingletonModule<ShaderPluginModule, ShaderPlugPluginDependencies> SingletonShaderPluginModule;
240
241 SingletonShaderPluginModule g_ShaderPluginModule;
242
243 extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server)
244 {
245     initialiseModule(server);
246
247     g_ShaderPluginModule.selfRegister();
248 }