]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - plugins/model/plugin.cpp
Merge branch 'master' into divVerent/farplanedist-sky-fix
[xonotic/netradiant.git] / plugins / model / plugin.cpp
index d47c25011992956c7b43673db1e17b42ca696a0f..61e77628530ff65e8118ff2d1836b868d2d64914 100644 (file)
-
 /*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
+   Copyright (C) 2001-2006, William Joseph.
+   All Rights Reserved.
 
-This file is part of GtkRadiant.
+   This file is part of GtkRadiant.
 
-GtkRadiant is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-GtkRadiant is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
 
 #include "plugin.h"
 
-#if 0 // stop using windowing systems in plugins - put the text in SynapseClient::GetInfo
-// =============================================================================
-// Utility functions
-static void dialog_button_callback (GtkWidget *widget, gpointer data)
-{
-       GtkWidget *parent;
-       int *loop, *ret;
-       parent = gtk_widget_get_toplevel (widget);
-       loop = (int*)g_object_get_data (G_OBJECT (parent), "loop");
-       ret = (int*)g_object_get_data (G_OBJECT (parent), "ret");
-       *loop = 0;
-       *ret = (int)data;
-}
-
-static gint dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data)
-{
-       int *loop;
-       gtk_widget_hide (widget);
-       loop = (int*)g_object_get_data (G_OBJECT (widget), "loop");
-       *loop = 0;
-
-       return TRUE;
-}
-
-int DoAboutBox( GtkWidget *parent )
-{
-       GtkWidget *window, *w, *text, *vbox, *hbox, *hbox2, *frame;
-       GdkPixmap *pixmap;
-       GdkBitmap *mask;
-       GtkStyle *style;
-       int ret, loop = 1;
-       char buf[2048];
-  const picoModule_t **modules, *pm;
-       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-       gtk_signal_connect (GTK_OBJECT (window), "delete_event",
-                      GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
-       gtk_signal_connect (GTK_OBJECT (window), "destroy",
-                      GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
-       gtk_window_set_title (GTK_WINDOW (window), "About...");
-       gtk_container_border_width (GTK_CONTAINER (window), 10);
-       g_object_set_data (G_OBJECT (window), "loop", &loop);
-       g_object_set_data (G_OBJECT (window), "ret", &ret);
-       gtk_widget_realize (window);
-
-       if (parent != NULL)
-               gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (parent));
-
-  vbox = gtk_vbox_new (FALSE, 10);
-  gtk_container_add (GTK_CONTAINER (window), vbox);
-       gtk_widget_show (vbox);
-
-       style = gtk_widget_get_style(window);
-
-  hbox2 = gtk_hbox_new (FALSE, 10);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 2);
-       gtk_widget_show (hbox2);
-
-  frame = gtk_frame_new (NULL);
-  gtk_box_pack_start (GTK_BOX (hbox2), frame, FALSE, FALSE, 2);
-  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-  gtk_widget_show (frame);
-
-       if( g_FuncTable.m_pfnLoadBitmap( "picomodel.bmp", (void **)&pixmap, (void **)&mask ) ) {
-               w = gtk_pixmap_new (pixmap, mask);
-    gtk_container_add (GTK_CONTAINER (frame), w);
-               gtk_widget_show (w);
+#include <stdio.h>
+#include "picomodel.h"
+typedef unsigned char byte;
+#include <stdlib.h>
+#include <algorithm>
+#include <list>
+
+#include "iscenegraph.h"
+#include "irender.h"
+#include "iselection.h"
+#include "iimage.h"
+#include "imodel.h"
+#include "igl.h"
+#include "ifilesystem.h"
+#include "iundo.h"
+#include "ifiletypes.h"
+
+#include "modulesystem/singletonmodule.h"
+#include "stream/textstream.h"
+#include "string/string.h"
+#include "stream/stringstream.h"
+#include "typesystem.h"
+
+#include "model.h"
+
+void PicoPrintFunc( int level, const char *str ){
+       if ( str == 0 ) {
+               return;
        }
+       switch ( level )
+       {
+       case PICO_NORMAL:
+               globalOutputStream() << str << "\n";
+               break;
 
-       w = gtk_label_new ("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" );
-       gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);
-       gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_LEFT);
-       gtk_widget_show (w);
-
-  w = gtk_scrolled_window_new(NULL, NULL);
-  gtk_box_pack_start(GTK_BOX(vbox), w, TRUE, TRUE, 2);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-  gtk_widget_show(w);
-
-  text = gtk_text_new(NULL, NULL);
-  gtk_text_set_editable(GTK_TEXT(text), FALSE);
-  gtk_container_add(GTK_CONTAINER(w), text);
-
-  strcpy( buf, "#Supported Model Formats:\n" );
-  gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, buf, -1);
-
-  for( modules = PicoModuleList( NULL ); *modules != NULL; modules++ )
-  {
-    pm = *modules;
-
-    if( pm == NULL)
-                       break;
-
-    sprintf( buf, "\n%s, version %s, (c) %s", pm->displayName, pm->version, pm->copyright );
-    gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, buf, -1);
-  }
-
-  gtk_text_set_word_wrap(GTK_TEXT(text), FALSE);
-  gtk_widget_show(text);
-
-  gtk_text_set_point(GTK_TEXT(text), 0);
-  gtk_text_forward_delete(GTK_TEXT(text), 1);
-
-       w = gtk_hseparator_new ();
-       gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);
-       gtk_widget_show (w);
-       hbox = gtk_hbox_new (FALSE, 10);
-       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2);
-       gtk_widget_show (hbox);
-       w = gtk_button_new_with_label ("Ok");
-       gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
-       gtk_signal_connect (GTK_OBJECT (w), "clicked",
-                        GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
-       GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
-       gtk_widget_grab_default (w);
-       gtk_widget_show (w);
-       ret = IDOK;
-       gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
-       gtk_widget_show (window);
-       gtk_grab_add (window);
-       while (loop)
-               gtk_main_iteration ();
-       gtk_grab_remove (window);
-       gtk_widget_destroy (window);
-       return ret;
-}
-#endif
-
-// toolbar implementation
-
-class CFlushReloadSelectedToolbarButton : public IToolbarButton
-{
-public:
-  virtual const char* getImage() const
-  {
-    return "model_reload_entity.bmp";
-  }
-  virtual const char* getText() const
-  {
-    return "Reload";
-  }
-  virtual const char* getTooltip() const
-  {
-    return "Flush & Reload Selected Model";
-  }
-  virtual void activate() const
-  {
-    DoFlushReloadSelected();
-  }
-  virtual EType getType() const
-  {
-    return eButton;
-  }
-};
-
-CFlushReloadSelectedToolbarButton g_flushreloadselected;
-
-unsigned int ToolbarButtonCount()
-{
-  return 1;
-}
-
-const IToolbarButton* GetToolbarButton(unsigned int index)
-{
-  return &g_flushreloadselected;
-}
+       case PICO_VERBOSE:
+               //globalOutputStream() << "PICO_VERBOSE: " << str << "\n";
+               break;
 
-// =============================================================================
-// Pico utility functions
+       case PICO_WARNING:
+               globalErrorStream() << "PICO_WARNING: " << str << "\n";
+               break;
 
-#include "picomodel.h"
+       case PICO_ERROR:
+               globalErrorStream() << "PICO_ERROR: " << str << "\n";
+               break;
 
-void PicoPrintFunc( int level, const char *str )
-{
-       if( str == NULL )
-               return;
-       switch( level )
-       {
-               case PICO_NORMAL:
-                       Sys_Printf( "%s\n", str );
-                       break;
-               
-               case PICO_VERBOSE:
-                       Sys_FPrintf( SYS_VRB, "%s\n", str );
-                       break;
-               
-               case PICO_WARNING:
-                       Sys_Printf( "WARNING: %s\n", str );
-                       break;
-               
-               case PICO_ERROR:
-                       Sys_FPrintf( SYS_VRB, "ERROR: %s\n", str );
-                       break;
-               
-               case PICO_FATAL:
-      Sys_Printf( "ERROR: %s\n", str );
-                       break;
+       case PICO_FATAL:
+               globalErrorStream() << "PICO_FATAL: " << str << "\n";
+               break;
        }
 }
 
-void PicoLoadFileFunc( char *name, byte **buffer, int *bufSize )
-{
-       *bufSize = vfsLoadFile( (const char*) name, (void**) buffer, 0 );
+void PicoLoadFileFunc( const char *name, byte **buffer, int *bufSize ){
+       *bufSize = vfsLoadFile( name, (void**) buffer );
 }
 
-void PicoFreeFileFunc( void* file )
-{
-       vfsFreeFile(file);
+void PicoFreeFileFunc( void* file ){
+       vfsFreeFile( file );
 }
 
-static void initialise()
-{
+void pico_initialise(){
        PicoInit();
        PicoSetMallocFunc( malloc );
        PicoSetFreeFunc( free );
@@ -251,179 +91,86 @@ static void initialise()
        PicoSetFreeFileFunc( PicoFreeFileFunc );
 }
 
-static void add_model_apis(CSynapseClient& client)
-{
-  const picoModule_t** modules = PicoModuleList( NULL );
-  while(*modules != NULL)
-  {
-    const picoModule_t* module = *modules++;
-    if(module->canload && module->load)
-      for(unsigned int j = 0; module->defaultExts[j] != NULL; j++)
-        client.AddAPI(MODEL_MAJOR, module->defaultExts[j], sizeof(_QERPlugModelTable));
-  }   
-}
 
-static bool model_is_supported(const char* extension)
+class PicoModelLoader : public ModelLoader
 {
-  const picoModule_t** modules = PicoModuleList( NULL );
-  while(*modules != NULL)
-  {
-    const picoModule_t* module = *modules++;
-    if(module->canload && module->load)
-      for(unsigned int j = 0; module->defaultExts[j] != NULL; j++)
-        if(strcmp(extension, module->defaultExts[j]) == 0)
-          return true;
-  }
-  return false;
+const picoModule_t* m_module;
+public:
+PicoModelLoader( const picoModule_t* module ) : m_module( module ){
 }
-
-void init_filetypes()
-{
-  const picoModule_t **modules = PicoModuleList(NULL);
-  while(*modules != NULL)
-  {
-    const picoModule_t* module = *modules++;
-    if(module->canload && module->load)
-    {
-      for(char*const* ext = module->defaultExts; *ext != NULL; ++ext)
-      {
-        char buf[16];
-        buf[0] = '*';
-        buf[1] = '.';
-        strcpy(buf+2, *ext);
-        GetFileTypeRegistry()->addType(MODEL_MAJOR, filetype_t(module->displayName, buf));
-      }
-    }
-  }
+scene::Node& loadModel( ArchiveFile& file ){
+       return loadPicoModel( m_module, file );
 }
+};
 
-// plugin implementation
-
-static const char *PLUGIN_NAME = "Model loading module";
-static const char *PLUGIN_COMMANDS = "Flush & Reload Models,Flush & Reload Selected";
-static const char *PLUGIN_ABOUT = "Model loading module";
-
-extern "C" const char* QERPlug_Init (void *hApp, void* pMainWidget)
+class ModelPicoDependencies :
+       public GlobalFileSystemModuleRef,
+       public GlobalOpenGLModuleRef,
+       public GlobalUndoModuleRef,
+       public GlobalSceneGraphModuleRef,
+       public GlobalShaderCacheModuleRef,
+       public GlobalSelectionModuleRef,
+       public GlobalFiletypesModuleRef
 {
-  init_filetypes();
-  return (char *) PLUGIN_NAME;
-}
+};
 
-extern "C" const char* QERPlug_GetName ()
+class ModelPicoAPI : public TypeSystemRef
 {
-  return (char *) PLUGIN_NAME;
-}
+PicoModelLoader m_modelLoader;
+public:
+typedef ModelLoader Type;
 
-extern "C" const char* QERPlug_GetCommandList ()
-{
-  return (char *) PLUGIN_COMMANDS;
+ModelPicoAPI( const char* extension, const picoModule_t* module ) :
+       m_modelLoader( module ){
+       StringOutputStream filter( 128 );
+       filter << "*." << extension;
+       GlobalFiletypesModule::getTable().addType( Type::Name(), extension, filetype_t( module->displayName, filter.c_str() ) );
 }
+ModelLoader* getTable(){
+       return &m_modelLoader;
+}
+};
 
-extern "C" void QERPlug_Dispatch (const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush)
+class PicoModelAPIConstructor
 {
-  if( !strcmp( p, "Flush & Reload Selected" ) )
-    DoFlushReloadSelected();
-  else if( !strcmp( p, "Flush & Reload Models" ) )
-    DoFlushReloadAll();
+CopiedString m_extension;
+const picoModule_t* m_module;
+public:
+PicoModelAPIConstructor( const char* extension, const picoModule_t* module ) :
+       m_extension( extension ), m_module( module ){
 }
-
-
-void DoFlushReloadSelected() {
+const char* getName(){
+       return m_extension.c_str();
 }
-
-void DoFlushReloadAll() {
-  GetModelCache()->RefreshAll();
+ModelPicoAPI* constructAPI( ModelPicoDependencies& dependencies ){
+       return new ModelPicoAPI( m_extension.c_str(), m_module );
 }
-
-// =============================================================================
-
-// function tables
-_QERFuncTable_1 g_FuncTable;
-_QERQglTable g_QglTable;
-_QERShadersTable g_ShadersTable;
-_QERFileSystemTable g_FileSystemTable;
-
-// =============================================================================
-// SYNAPSE
-
-CSynapseServer* g_pSynapseServer = NULL;
-CSynapseClientModel g_SynapseClient;
-
-static const XMLConfigEntry_t entries[] = 
-  { { SHADERS_MAJOR, SYN_REQUIRE, sizeof(g_ShadersTable), &g_ShadersTable }, 
-    { VFS_MAJOR, SYN_REQUIRE, sizeof(g_FileSystemTable), &g_FileSystemTable },
-    { NULL, SYN_UNKNOWN, 0, NULL } };
-
-extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces (const char *version, CSynapseServer *pServer)
-{
-  if (strcmp(version, SYNAPSE_VERSION))
-  {
-    Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version);
-    return NULL;
-  }
-  g_pSynapseServer = pServer;
-  g_pSynapseServer->IncRef();
-  Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() );
-
-  initialise();
-  
-  add_model_apis(g_SynapseClient);
-  g_SynapseClient.AddAPI(TOOLBAR_MAJOR, "model", sizeof(_QERPlugToolbarTable));
-  g_SynapseClient.AddAPI(PLUGIN_MAJOR, "model", sizeof(_QERPluginTable));
-
-  g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable);
-  g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(g_QglTable), SYN_REQUIRE, &g_QglTable);
-
-  if ( !g_SynapseClient.ConfigXML( pServer, NULL, entries ) ) {
-    return NULL;
-  }
-  
-  return &g_SynapseClient;
+void destroyAPI( ModelPicoAPI* api ){
+       delete api;
 }
+};
 
-bool CSynapseClientModel::RequestAPI(APIDescriptor_t *pAPI)
-{
-  if (!strcmp(pAPI->major_name, MODEL_MAJOR))
-  {
-    _QERPlugModelTable* pTable= static_cast<_QERPlugModelTable*>(pAPI->mpTable);
-
-    if (model_is_supported(pAPI->minor_name))
-    {
-      pTable->m_pfnLoadModel = &LoadModel;
-      return true;
-    }
-  }
-  else if (!strcmp(pAPI->major_name, TOOLBAR_MAJOR))
-  {
-    _QERPlugToolbarTable* pTable= static_cast<_QERPlugToolbarTable*>(pAPI->mpTable);
-
-    pTable->m_pfnToolbarButtonCount = &ToolbarButtonCount;
-    pTable->m_pfnGetToolbarButton = &GetToolbarButton;
-    return true;
-  }
-  else if (!strcmp(pAPI->major_name, PLUGIN_MAJOR))
-  {
-    _QERPluginTable* pTable= static_cast<_QERPluginTable*>(pAPI->mpTable);
 
-    pTable->m_pfnQERPlug_Init = QERPlug_Init;
-    pTable->m_pfnQERPlug_GetName = QERPlug_GetName;
-    pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList;
-    pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch;
-    return true;
-  }
+typedef SingletonModule<ModelPicoAPI, ModelPicoDependencies, PicoModelAPIConstructor> PicoModelModule;
+typedef std::list<PicoModelModule> PicoModelModules;
+PicoModelModules g_PicoModelModules;
 
-  Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());
-  return false;
-}
 
-#include "version.h"
+extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){
+       initialiseModule( server );
 
-const char* CSynapseClientModel::GetInfo()
-{
-  return "picomodel loader module built " __DATE__ " " RADIANT_VERSION;
-}
+       pico_initialise();
 
-const char* CSynapseClientModel::GetName()
-{
-  return "model";
+       const picoModule_t** modules = PicoModuleList( 0 );
+       while ( *modules != 0 )
+       {
+               const picoModule_t* module = *modules++;
+               if ( module->canload && module->load ) {
+                       for ( char*const* ext = module->defaultExts; *ext != 0; ++ext )
+                       {
+                               g_PicoModelModules.push_back( PicoModelModule( PicoModelAPIConstructor( *ext, module ) ) );
+                               g_PicoModelModules.back().selfRegister();
+                       }
+               }
+       }
 }