fix "ExpandPath called without qdir set" as qdir is never set in Xonotic/Nexuiz/any...
[divverent/netradiant.git] / plugins / model / plugin.cpp
1 /*
2 Copyright (C) 2001-2006, William Joseph.
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 "plugin.h"
23
24 #include <stdio.h>
25 #include "picomodel.h"
26 typedef unsigned char byte;
27 #include <stdlib.h>
28 #include <algorithm>
29 #include <list>
30
31 #include "iscenegraph.h"
32 #include "irender.h"
33 #include "iselection.h"
34 #include "iimage.h"
35 #include "imodel.h"
36 #include "igl.h"
37 #include "ifilesystem.h"
38 #include "iundo.h"
39 #include "ifiletypes.h"
40
41 #include "modulesystem/singletonmodule.h"
42 #include "stream/textstream.h"
43 #include "string/string.h"
44 #include "stream/stringstream.h"
45 #include "typesystem.h"
46
47 #include "model.h"
48
49 void PicoPrintFunc( int level, const char *str )
50 {
51         if( str == 0 )
52                 return;
53         switch( level )
54         {
55                 case PICO_NORMAL:
56                         globalOutputStream() << str << "\n";
57                         break;
58                 
59                 case PICO_VERBOSE:
60                         //globalOutputStream() << "PICO_VERBOSE: " << str << "\n";
61                         break;
62                 
63                 case PICO_WARNING:
64                         globalErrorStream() << "PICO_WARNING: " << str << "\n";
65                         break;
66                 
67                 case PICO_ERROR:
68                         globalErrorStream() << "PICO_ERROR: " << str << "\n";
69                         break;
70                 
71                 case PICO_FATAL:
72                         globalErrorStream() << "PICO_FATAL: " << str << "\n";
73                         break;
74         }
75 }
76
77 void PicoLoadFileFunc( const char *name, byte **buffer, int *bufSize )
78 {
79         *bufSize = vfsLoadFile( name, (void**) buffer);
80 }
81
82 void PicoFreeFileFunc( void* file )
83 {
84         vfsFreeFile(file);
85 }
86
87 void pico_initialise()
88 {
89         PicoInit();
90         PicoSetMallocFunc( malloc );
91         PicoSetFreeFunc( free );
92         PicoSetPrintFunc( PicoPrintFunc );
93         PicoSetLoadFileFunc( PicoLoadFileFunc );
94         PicoSetFreeFileFunc( PicoFreeFileFunc );
95 }
96
97
98 class PicoModelLoader : public ModelLoader
99 {
100   const picoModule_t* m_module;
101 public:
102   PicoModelLoader(const picoModule_t* module) : m_module(module)
103   {
104   }
105   scene::Node& loadModel(ArchiveFile& file)
106   {
107     return loadPicoModel(m_module, file);
108   }
109 };
110
111 class ModelPicoDependencies :
112   public GlobalFileSystemModuleRef,
113   public GlobalOpenGLModuleRef,
114   public GlobalUndoModuleRef,
115   public GlobalSceneGraphModuleRef,
116   public GlobalShaderCacheModuleRef,
117   public GlobalSelectionModuleRef,
118   public GlobalFiletypesModuleRef
119 {
120 };
121
122 class ModelPicoAPI : public TypeSystemRef
123 {
124   PicoModelLoader m_modelLoader;
125 public:
126   typedef ModelLoader Type;
127
128   ModelPicoAPI(const char* extension, const picoModule_t* module) :
129     m_modelLoader(module)
130   {
131     StringOutputStream filter(128);
132     filter << "*." << extension;
133     GlobalFiletypesModule::getTable().addType(Type::Name(), extension, filetype_t(module->displayName, filter.c_str()));
134   }
135   ModelLoader* getTable()
136   {
137     return &m_modelLoader;
138   }
139 };
140
141 class PicoModelAPIConstructor
142 {
143   CopiedString m_extension;
144   const picoModule_t* m_module;
145 public:
146   PicoModelAPIConstructor(const char* extension, const picoModule_t* module) :
147     m_extension(extension), m_module(module)
148   {
149   }
150   const char* getName()
151   {
152     return m_extension.c_str();
153   }
154   ModelPicoAPI* constructAPI(ModelPicoDependencies& dependencies)
155   {
156     return new ModelPicoAPI(m_extension.c_str(), m_module);
157   }
158   void destroyAPI(ModelPicoAPI* api)
159   {
160     delete api;
161   }
162 };
163
164
165 typedef SingletonModule<ModelPicoAPI, ModelPicoDependencies, PicoModelAPIConstructor> PicoModelModule;
166 typedef std::list<PicoModelModule> PicoModelModules;
167 PicoModelModules g_PicoModelModules;
168
169
170 extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
171 {
172   initialiseModule(server);
173
174   pico_initialise();
175
176   const picoModule_t** modules = PicoModuleList( 0 );
177   while(*modules != 0)
178   {
179     const picoModule_t* module = *modules++;
180     if(module->canload && module->load)
181     {
182       for(char*const* ext = module->defaultExts; *ext != 0; ++ext)
183       {
184         g_PicoModelModules.push_back(PicoModelModule(PicoModelAPIConstructor(*ext, module)));
185         g_PicoModelModules.back().selfRegister();
186       }
187     }
188   }
189 }