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