merge branch work back into trunk
[xonotic/netradiant.git] / plugins / model / plugin.cpp
1
2 /*
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6 This file is part of GtkRadiant.
7
8 GtkRadiant is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 GtkRadiant is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GtkRadiant; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 */
22
23 #include "plugin.h"
24
25 // toolbar implementation
26
27 class CFlushReloadSelectedToolbarButton : public IToolbarButton
28 {
29 public:
30   virtual const char* getImage() const
31   {
32     return "model_reload_entity.bmp";
33   }
34   virtual const char* getText() const
35   {
36     return "Reload";
37   }
38   virtual const char* getTooltip() const
39   {
40     return "Flush & Reload Selected Model";
41   }
42   virtual void activate() const
43   {
44     DoFlushReloadSelected();
45   }
46   virtual EType getType() const
47   {
48     return eButton;
49   }
50 };
51
52 CFlushReloadSelectedToolbarButton g_flushreloadselected;
53
54 unsigned int ToolbarButtonCount()
55 {
56   return 1;
57 }
58
59 const IToolbarButton* GetToolbarButton(unsigned int index)
60 {
61   return &g_flushreloadselected;
62 }
63
64 // =============================================================================
65 // Pico utility functions
66
67 #include "picomodel.h"
68
69 void PicoPrintFunc( int level, const char *str )
70 {
71         if( str == NULL )
72                 return;
73         switch( level )
74         {
75                 case PICO_NORMAL:
76                         Sys_Printf( "%s\n", str );
77                         break;
78                 
79                 case PICO_VERBOSE:
80                         Sys_FPrintf( SYS_VRB, "%s\n", str );
81                         break;
82                 
83                 case PICO_WARNING:
84                         Sys_Printf( "WARNING: %s\n", str );
85                         break;
86                 
87                 case PICO_ERROR:
88                         Sys_FPrintf( SYS_VRB, "ERROR: %s\n", str );
89                         break;
90                 
91                 case PICO_FATAL:
92       Sys_Printf( "ERROR: %s\n", str );
93                         break;
94         }
95 }
96
97 void PicoLoadFileFunc( char *name, byte **buffer, int *bufSize )
98 {
99         *bufSize = vfsLoadFile( (const char*) name, (void**) buffer, 0 );
100 }
101
102 void PicoFreeFileFunc( void* file )
103 {
104         vfsFreeFile(file);
105 }
106
107 static void initialise()
108 {
109         PicoInit();
110         PicoSetMallocFunc( malloc );
111         PicoSetFreeFunc( free );
112         PicoSetPrintFunc( PicoPrintFunc );
113         PicoSetLoadFileFunc( PicoLoadFileFunc );
114         PicoSetFreeFileFunc( PicoFreeFileFunc );
115 }
116
117 static void add_model_apis(CSynapseClient& client)
118 {
119   const picoModule_t** modules = PicoModuleList( NULL );
120   while(*modules != NULL)
121   {
122     const picoModule_t* module = *modules++;
123     if(module->canload && module->load)
124       for(unsigned int j = 0; module->defaultExts[j] != NULL; j++)
125         client.AddAPI(MODEL_MAJOR, module->defaultExts[j], sizeof(_QERPlugModelTable));
126   }   
127 }
128
129 static bool model_is_supported(const char* extension)
130 {
131   const picoModule_t** modules = PicoModuleList( NULL );
132   while(*modules != NULL)
133   {
134     const picoModule_t* module = *modules++;
135     if(module->canload && module->load)
136       for(unsigned int j = 0; module->defaultExts[j] != NULL; j++)
137         if(strcmp(extension, module->defaultExts[j]) == 0)
138           return true;
139   }
140   return false;
141 }
142
143 void init_filetypes()
144 {
145   const picoModule_t **modules = PicoModuleList(NULL);
146   while(*modules != NULL)
147   {
148     const picoModule_t* module = *modules++;
149     if(module->canload && module->load)
150     {
151       for(char*const* ext = module->defaultExts; *ext != NULL; ++ext)
152       {
153         char buf[16];
154         buf[0] = '*';
155         buf[1] = '.';
156         strcpy(buf+2, *ext);
157         GetFileTypeRegistry()->addType(MODEL_MAJOR, filetype_t(module->displayName, buf));
158       }
159     }
160   }
161 }
162
163 // plugin implementation
164
165 static const char *PLUGIN_NAME = "Model loading module";
166 static const char *PLUGIN_COMMANDS = "About;-;Flush & Reload Models;Flush & Reload Selected";
167 static const char *PLUGIN_ABOUT = "Model Module v1.0 for GtkRadiant\nby Arnout van Meer (rr2do2@splashdamage.com)\n\nBased on the MD3Model Module by SPoG\nPicoModel Library Copyright (c) 2002, Randy Reddig & seaw0lf\n\nSupported models:\n";
168
169 extern "C" const char* QERPlug_Init (void *hApp, void* pMainWidget)
170 {
171   init_filetypes();
172   return (char *) PLUGIN_NAME;
173 }
174
175 extern "C" const char* QERPlug_GetName ()
176 {
177   return (char *) PLUGIN_NAME;
178 }
179
180 extern "C" const char* QERPlug_GetCommandList ()
181 {
182   return (char *) PLUGIN_COMMANDS;
183 }
184
185 extern "C" void QERPlug_Dispatch (const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush)
186 {
187   if( !strcmp( p, "Flush & Reload Selected" ) )
188     DoFlushReloadSelected();
189   else if( !strcmp( p, "Flush & Reload Models" ) )
190     DoFlushReloadAll();
191   else if( !strcmp( p, "About" ) ) {
192     const picoModule_t** modules = PicoModuleList( NULL );
193     char about_buf[1024];
194     strncpy(about_buf, PLUGIN_ABOUT, sizeof(about_buf) - 1);
195     while(*modules != NULL) {
196       const picoModule_t* module = *modules++;
197       strncat(about_buf, module->displayName, sizeof(about_buf) - 1);
198       strncat(about_buf, " (", sizeof(about_buf) - 1);
199       strncat(about_buf, module->defaultExts[0], sizeof(about_buf) - 1);
200       strncat(about_buf, ")\n\t", sizeof(about_buf) - 1);
201       strncat(about_buf, module->copyright, sizeof(about_buf) - 1);
202       strncat(about_buf, "\n", sizeof(about_buf) - 1);
203     }
204     g_FuncTable.m_pfnMessageBox(NULL, about_buf, "About", MB_OK, NULL);
205   }
206 }
207
208
209 void DoFlushReloadSelected() {
210 }
211
212 void DoFlushReloadAll() {
213   GetModelCache()->RefreshAll();
214 }
215
216 // =============================================================================
217
218 // function tables
219 _QERFuncTable_1 g_FuncTable;
220 _QERQglTable g_QglTable;
221 _QERShadersTable g_ShadersTable;
222 _QERFileSystemTable g_FileSystemTable;
223
224 // =============================================================================
225 // SYNAPSE
226
227 CSynapseServer* g_pSynapseServer = NULL;
228 CSynapseClientModel g_SynapseClient;
229
230 static const XMLConfigEntry_t entries[] = 
231   { { SHADERS_MAJOR, SYN_REQUIRE, sizeof(g_ShadersTable), &g_ShadersTable }, 
232     { VFS_MAJOR, SYN_REQUIRE, sizeof(g_FileSystemTable), &g_FileSystemTable },
233     { NULL, SYN_UNKNOWN, 0, NULL } };
234
235 #if __GNUC__ >= 4
236 #pragma GCC visibility push(default)
237 #endif
238 extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ) {
239 #if __GNUC__ >= 4
240 #pragma GCC visibility pop
241 #endif
242   if (strcmp(version, SYNAPSE_VERSION))
243   {
244     Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version);
245     return NULL;
246   }
247   g_pSynapseServer = pServer;
248   g_pSynapseServer->IncRef();
249   Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() );
250
251   initialise();
252   
253   add_model_apis(g_SynapseClient);
254   g_SynapseClient.AddAPI(TOOLBAR_MAJOR, "model", sizeof(_QERPlugToolbarTable));
255   g_SynapseClient.AddAPI(PLUGIN_MAJOR, "model", sizeof(_QERPluginTable));
256
257   g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable);
258   g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(g_QglTable), SYN_REQUIRE, &g_QglTable);
259
260   if ( !g_SynapseClient.ConfigXML( pServer, NULL, entries ) ) {
261     return NULL;
262   }
263   
264   return &g_SynapseClient;
265 }
266
267 bool CSynapseClientModel::RequestAPI(APIDescriptor_t *pAPI)
268 {
269   if (!strcmp(pAPI->major_name, MODEL_MAJOR))
270   {
271     _QERPlugModelTable* pTable= static_cast<_QERPlugModelTable*>(pAPI->mpTable);
272
273     if (model_is_supported(pAPI->minor_name))
274     {
275       pTable->m_pfnLoadModel = &LoadModel;
276       return true;
277     }
278   }
279   else if (!strcmp(pAPI->major_name, TOOLBAR_MAJOR))
280   {
281     _QERPlugToolbarTable* pTable= static_cast<_QERPlugToolbarTable*>(pAPI->mpTable);
282
283     pTable->m_pfnToolbarButtonCount = &ToolbarButtonCount;
284     pTable->m_pfnGetToolbarButton = &GetToolbarButton;
285     return true;
286   }
287   else if (!strcmp(pAPI->major_name, PLUGIN_MAJOR))
288   {
289     _QERPluginTable* pTable= static_cast<_QERPluginTable*>(pAPI->mpTable);
290
291     pTable->m_pfnQERPlug_Init = QERPlug_Init;
292     pTable->m_pfnQERPlug_GetName = QERPlug_GetName;
293     pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList;
294     pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch;
295     return true;
296   }
297
298   Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());
299   return false;
300 }
301
302 #include "version.h"
303
304 const char* CSynapseClientModel::GetInfo()
305 {
306   return "picomodel loader module built " __DATE__ " " RADIANT_VERSION;
307 }
308
309 const char* CSynapseClientModel::GetName()
310 {
311   return "model";
312 }