]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - plugins/model/remap.cpp
apply misc fixes from Markus Fischer and Rambetter
[xonotic/netradiant.git] / plugins / model / remap.cpp
index dbcef14fe46529e7f325ce71d577338fbfa85e44..7f1cac2d164b245681f31209a52d80557750317d 100644 (file)
-\r
-#include "cpicomodel.h"\r
-#include "qertypes.h"\r
-\r
-#include <map>\r
-#include <vector>\r
-\r
-#define RADIANT_ASSERT(condition, message) if(!(condition)) { Sys_Printf("ASSERTION FAILURE: " message "\n"); } else\r
-\r
-template<class key_type, class value_type>\r
-class cache_element\r
-{\r
-public:\r
-  inline cache_element() : m_count(0), m_value(NULL) {}\r
-  inline ~cache_element()\r
-  {\r
-    RADIANT_ASSERT(m_count == 0 , "destroyed a reference before it was released\n");\r
-    if(m_count > 0)\r
-      destroy();\r
-  }\r
-  inline value_type* capture(const key_type& key)\r
-  {\r
-    if(++m_count == 1)\r
-      construct(key);\r
-    return m_value;\r
-  }\r
-  inline void release()\r
-  {\r
-    RADIANT_ASSERT(!empty(), "failed to release reference - not found in cache\n");\r
-    if(--m_count == 0)\r
-      destroy();\r
-  }\r
-  inline bool empty()\r
-  {\r
-    return m_count == 0;\r
-  }\r
-  inline void refresh(const key_type& key)\r
-  {\r
-    m_value->refresh(key);\r
-  }\r
-private:\r
-  inline void construct(const key_type& key)\r
-  {\r
-    m_value = new value_type(key);\r
-  }\r
-  inline void destroy()\r
-  {\r
-    delete m_value;\r
-  }\r
-\r
-  unsigned int m_count;\r
-  value_type* m_value;\r
-};\r
-\r
-class ModelCache\r
-{\r
-  typedef CPicoModel value_type;\r
-  \r
-public:\r
-  typedef PicoModelKey key_type;\r
-  typedef cache_element<key_type, value_type> elem_type;\r
-  typedef map<key_type, elem_type> cache_type;\r
-  \r
-  value_type* capture(const key_type& key)\r
-  {\r
-    return m_cache[key].capture(key);\r
-  }\r
-  void release(const key_type& key)\r
-  {\r
-    m_cache[key].release();\r
-  }\r
-\r
-private:\r
-  cache_type m_cache;\r
-};\r
-\r
-ModelCache g_model_cache;\r
-\r
-\r
-\r
-typedef struct remap_s {\r
-  char m_remapbuff[64+1024];\r
-  char *original;\r
-  char *remap;\r
-} remap_t;\r
-\r
-class RemapWrapper : public IRender, public ISelect\r
-{\r
-  unsigned int m_refcount;\r
-public:\r
-  RemapWrapper(entity_interfaces_t* model, const char* name)\r
-    : m_refcount(1)\r
-  {\r
-    parse_namestr(name);\r
-\r
-    m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), m_frame));\r
-\r
-    model->pRender = this;\r
-    model->pRender->IncRef();\r
-    model->pEdit = NULL;\r
-    model->pSelect = this;\r
-    model->pSelect->IncRef();\r
-\r
-    construct_shaders();\r
-  }\r
-  virtual ~RemapWrapper()\r
-  {\r
-    g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), m_frame));\r
-\r
-    for(shaders_t::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) {\r
-      (*i)->DecRef();\r
-       }\r
-\r
-    for(remaps_t::iterator j = m_remaps.begin(); j != m_remaps.end(); ++j)\r
-    {\r
-      remap_t *pRemap = (*j);\r
-      delete pRemap;\r
-    }\r
-    m_remaps.clear();\r
-  }\r
-  virtual void IncRef()\r
-  {\r
-    ++m_refcount;\r
-  }\r
-  virtual void DecRef()\r
-  {\r
-    if(--m_refcount == 0)\r
-      delete this;\r
-  }\r
-  virtual void Draw(int state, int rflags) const\r
-  {\r
-    m_model->Draw(state, m_shaders, rflags);\r
-  }\r
-  virtual const aabb_t *GetAABB() const \r
-  {\r
-    return m_model->GetAABB();\r
-  }\r
-  virtual bool TestRay(const ray_t *ray, vec_t *dist) const\r
-  {\r
-    return m_model->TestRay(ray, dist);\r
-  }\r
-private:\r
-  void add_remap(const char *remap)\r
-  {\r
-    const char *ch;\r
-    remap_t *pRemap;\r
-\r
-    ch = remap;\r
-\r
-    while( *ch && *ch != ';' )\r
-      ch++;\r
-\r
-    if( *ch == '\0' ) {\r
-      // bad remap\r
-      Sys_FPrintf( SYS_WRN, "WARNING: Shader _remap key found in a model entity without a ; character\n" );\r
-    } else {\r
-      pRemap = new remap_t;\r
-\r
-      strncpy( pRemap->m_remapbuff, remap, sizeof(pRemap->m_remapbuff) );\r
-\r
-      pRemap->m_remapbuff[ch - remap] = '\0';\r
-\r
-      pRemap->original = pRemap->m_remapbuff;\r
-      pRemap->remap = pRemap->m_remapbuff + ( ch - remap ) + 1;\r
-\r
-      m_remaps.push_back( pRemap );\r
-    }\r
-  }\r
-\r
-  void parse_namestr(const char *name)\r
-  {\r
-    const char *ptr, *s;\r
-    char buf[1024];\r
-    bool hasName, hasFrame;\r
-\r
-    hasName = hasFrame = false;\r
-\r
-    for( s = ptr = name; *ptr; ptr++ ) {\r
-      if( !hasName && *ptr == ':' ) {\r
-        // model name\r
-        hasName = true;\r
-        strncpy( buf, s, ptr - s );\r
-        buf[ptr - s] = '\0';\r
-        m_name = buf;\r
-        s = ptr + 1;\r
-      } else if( *ptr == '?' ) {\r
-        // model frame\r
-        hasFrame = true;\r
-        strncpy( buf, s, ptr - s );\r
-        buf[ptr - s] = '\0';\r
-        m_frame = atoi(buf);\r
-        s = ptr + 1;\r
-      } else if( *ptr == '&' ) {\r
-        // a remap\r
-        strncpy( buf, s, ptr - s );\r
-        buf[ptr - s] = '\0';\r
-        add_remap( buf );\r
-        s = ptr + 1;\r
-      }\r
-    }\r
-\r
-    if( !hasFrame ) {\r
-      // model frame\r
-      strncpy( buf, s, ptr - s );\r
-      buf[ptr - s] = '\0';\r
-      m_frame = atoi(buf);\r
-    } else {\r
-      // a remap\r
-      strncpy( buf, s, ptr - s );\r
-      buf[ptr - s] = '\0';\r
-      add_remap( buf );\r
-    }\r
-  }\r
-\r
-  void construct_shaders()\r
-  {\r
-    IShader* global_shader = shader_for_remap("*");\r
-\r
-    unsigned int numSurfaces = m_model->GetNumSurfaces();\r
-    m_shaders.reserve(numSurfaces);\r
-    // now go through our surface and find our shaders, remap if needed\r
-    for(unsigned int j = 0; j < numSurfaces; j++ )\r
-    {\r
-      const char* surfShaderName = m_model->GetShaderNameForSurface(j);\r
-      IShader* shader = shader_for_remap(surfShaderName);\r
-//      m_shaders.push_back((shader) ? shader : (global_shader) ? global_shader : QERApp_Shader_ForName(surfShaderName));\r
-      if( shader ) {\r
-        m_shaders.push_back(shader);\r
-      } else if( global_shader ) {\r
-        m_shaders.push_back(global_shader);\r
-      } else {\r
-        m_shaders.push_back(QERApp_Shader_ForName(surfShaderName));\r
-      }\r
-    }\r
-  }\r
-  \r
-  inline IShader* shader_for_remap(const char* remap)\r
-  {\r
-    remap_t *pRemap;\r
-    remaps_t::iterator i;\r
-    for(i = m_remaps.begin(); i != m_remaps.end(); ++i)\r
-    {\r
-      pRemap = (*i);\r
-      if( stricmp( remap, pRemap->original ) == 0 )\r
-        break;\r
-    }\r
-    return (i != m_remaps.end()) ? QERApp_Shader_ForName(pRemap->remap) : NULL;\r
-  }\r
-\r
-  Str m_name;\r
-  int m_frame;\r
-  CPicoModel* m_model;\r
-\r
-  typedef vector<remap_t *> remaps_t;\r
-  remaps_t m_remaps;\r
-  typedef vector<IShader*> shaders_t;\r
-  shaders_t m_shaders;\r
-};\r
-\r
-class ModelWrapper : public IRender, public ISelect\r
-{\r
-  unsigned int m_refcount;\r
-public:\r
-  ModelWrapper(entity_interfaces_t* model, const char* name)\r
-    : m_refcount(1), m_name(name)\r
-  {\r
-    m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), 0));\r
-\r
-    model->pRender = this;\r
-    model->pRender->IncRef();\r
-    model->pEdit = NULL;\r
-    model->pSelect = this;\r
-    model->pSelect->IncRef();\r
-  }\r
-  virtual ~ModelWrapper()\r
-  {\r
-    g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), 0));\r
-       }\r
-\r
-  virtual void IncRef()\r
-  {\r
-    ++m_refcount;\r
-  }\r
-  virtual void DecRef()\r
-  {\r
-    if(--m_refcount == 0)\r
-      delete this;\r
-  }\r
-  virtual void Draw(int state, int rflags) const\r
-  {\r
-    m_model->Draw(state, rflags);\r
-  }\r
-  virtual const aabb_t *GetAABB() const \r
-  {\r
-    return m_model->GetAABB();\r
-  }\r
-  virtual bool TestRay(const ray_t *ray, vec_t *dist) const\r
-  {\r
-    return m_model->TestRay(ray, dist);\r
-  }\r
-\r
-  Str m_name;\r
-  CPicoModel* m_model;\r
-};\r
-\r
-void LoadModel(entity_interfaces_t* model, const char* name)\r
-{\r
-  if(strchr(name, ':') != NULL || strchr(name, '?') != NULL || strchr(name, '&') != NULL)\r
-  {\r
-    RemapWrapper* wrapper = new RemapWrapper(model, name);\r
-    wrapper->DecRef();\r
-  }\r
-  else\r
-  {\r
-    ModelWrapper* wrapper = new ModelWrapper(model, name);\r
-    wrapper->DecRef();\r
-  }\r
-}\r
+
+#include "cpicomodel.h"
+#include "qertypes.h"
+
+#include <map>
+#include <vector>
+
+#define RADIANT_ASSERT(condition, message) if(!(condition)) { Sys_Printf("ASSERTION FAILURE: " message "\n"); } else
+
+template<class key_type, class value_type>
+class cache_element
+{
+public:
+  inline cache_element() : m_count(0), m_value(NULL) {}
+  inline ~cache_element()
+  {
+    RADIANT_ASSERT(m_count == 0 , "destroyed a reference before it was released\n");
+    if(m_count > 0)
+      destroy();
+  }
+  inline value_type* capture(const key_type& key)
+  {
+    if(++m_count == 1)
+      construct(key);
+    return m_value;
+  }
+  inline void release()
+  {
+    RADIANT_ASSERT(!empty(), "failed to release reference - not found in cache\n");
+    if(--m_count == 0)
+      destroy();
+  }
+  inline bool empty()
+  {
+    return m_count == 0;
+  }
+  inline void refresh(const key_type& key)
+  {
+    m_value->refresh(key);
+  }
+private:
+  inline void construct(const key_type& key)
+  {
+    m_value = new value_type(key);
+  }
+  inline void destroy()
+  {
+    delete m_value;
+  }
+
+  unsigned int m_count;
+  value_type* m_value;
+};
+
+class ModelCache
+{
+  typedef CPicoModel value_type;
+  
+public:
+  typedef PicoModelKey key_type;
+  typedef cache_element<key_type, value_type> elem_type;
+  typedef map<key_type, elem_type> cache_type;
+  
+  value_type* capture(const key_type& key)
+  {
+    return m_cache[key].capture(key);
+  }
+  void release(const key_type& key)
+  {
+    m_cache[key].release();
+  }
+
+private:
+  cache_type m_cache;
+};
+
+ModelCache g_model_cache;
+
+
+
+typedef struct remap_s {
+  char m_remapbuff[64+1024];
+  char *original;
+  char *remap;
+} remap_t;
+
+class RemapWrapper : public IRender, public ISelect
+{
+  unsigned int m_refcount;
+public:
+  RemapWrapper(entity_interfaces_t* model, const char* name)
+    : m_refcount(1)
+  {
+    parse_namestr(name);
+
+    m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), m_frame));
+
+    model->pRender = this;
+    model->pRender->IncRef();
+    model->pEdit = NULL;
+    model->pSelect = this;
+    model->pSelect->IncRef();
+
+    construct_shaders();
+  }
+  virtual ~RemapWrapper()
+  {
+    g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), m_frame));
+
+    for(shaders_t::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) {
+      (*i)->DecRef();
+       }
+
+    for(remaps_t::iterator j = m_remaps.begin(); j != m_remaps.end(); ++j)
+    {
+      remap_t *pRemap = (*j);
+      delete pRemap;
+    }
+    m_remaps.clear();
+  }
+  virtual void IncRef()
+  {
+    ++m_refcount;
+  }
+  virtual void DecRef()
+  {
+    if(--m_refcount == 0)
+      delete this;
+  }
+  virtual void Draw(int state, int rflags) const
+  {
+    m_model->Draw(state, m_shaders, rflags);
+  }
+  virtual const aabb_t *GetAABB() const 
+  {
+    return m_model->GetAABB();
+  }
+  virtual bool TestRay(const ray_t *ray, vec_t *dist) const
+  {
+    return m_model->TestRay(ray, dist);
+  }
+private:
+  void add_remap(const char *remap)
+  {
+    const char *ch;
+    remap_t *pRemap;
+
+    ch = remap;
+
+    while( *ch && *ch != ';' )
+      ch++;
+
+    if( *ch == '\0' ) {
+      // bad remap
+      Sys_FPrintf( SYS_WRN, "WARNING: Shader _remap key found in a model entity without a ; character\n" );
+    } else {
+      pRemap = new remap_t;
+
+      strncpy( pRemap->m_remapbuff, remap, sizeof(pRemap->m_remapbuff) );
+
+      pRemap->m_remapbuff[ch - remap] = '\0';
+
+      pRemap->original = pRemap->m_remapbuff;
+      pRemap->remap = pRemap->m_remapbuff + ( ch - remap ) + 1;
+
+      m_remaps.push_back( pRemap );
+    }
+  }
+
+  void parse_namestr(const char *name)
+  {
+    const char *ptr, *s;
+    char buf[1024];
+    bool hasName, hasFrame;
+
+    hasName = hasFrame = false;
+
+    for( s = ptr = name; *ptr; ptr++ ) {
+      if( !hasName && *ptr == ':' ) {
+        // model name
+        hasName = true;
+        strncpy( buf, s, ptr - s );
+        buf[ptr - s] = '\0';
+        m_name = buf;
+        s = ptr + 1;
+      } else if( *ptr == '?' ) {
+        // model frame
+        hasFrame = true;
+        strncpy( buf, s, ptr - s );
+        buf[ptr - s] = '\0';
+        m_frame = atoi(buf);
+        s = ptr + 1;
+      } else if( *ptr == '&' ) {
+        // a remap
+        strncpy( buf, s, ptr - s );
+        buf[ptr - s] = '\0';
+        add_remap( buf );
+        s = ptr + 1;
+      }
+    }
+
+    if( !hasFrame ) {
+      // model frame
+      strncpy( buf, s, ptr - s );
+      buf[ptr - s] = '\0';
+      m_frame = atoi(buf);
+    } else {
+      // a remap
+      strncpy( buf, s, ptr - s );
+      buf[ptr - s] = '\0';
+      add_remap( buf );
+    }
+  }
+
+  void construct_shaders()
+  {
+    IShader* global_shader = shader_for_remap("*");
+
+    unsigned int numSurfaces = m_model->GetNumSurfaces();
+    m_shaders.reserve(numSurfaces);
+    // now go through our surface and find our shaders, remap if needed
+    for(unsigned int j = 0; j < numSurfaces; j++ )
+    {
+      const char* surfShaderName = m_model->GetShaderNameForSurface(j);
+      IShader* shader = shader_for_remap(surfShaderName);
+//      m_shaders.push_back((shader) ? shader : (global_shader) ? global_shader : QERApp_Shader_ForName(surfShaderName));
+      // Determine which shader it is going to be
+      if( !shader ) {
+        if( global_shader ) {
+          shader = global_shader;
+        } else {
+          shader = QERApp_Shader_ForName(surfShaderName);
+        }
+      }
+      // Add reference
+      shader->IncRef();
+      // Done, continue
+      m_shaders.push_back( shader );
+    }
+  }
+  
+  inline IShader* shader_for_remap(const char* remap)
+  {
+    remap_t *pRemap;
+    remaps_t::iterator i;
+    for(i = m_remaps.begin(); i != m_remaps.end(); ++i)
+    {
+      pRemap = (*i);
+      if( stricmp( remap, pRemap->original ) == 0 )
+        break;
+    }
+    return (i != m_remaps.end()) ? QERApp_Shader_ForName(pRemap->remap) : NULL;
+  }
+
+  Str m_name;
+  int m_frame;
+  CPicoModel* m_model;
+
+  typedef vector<remap_t *> remaps_t;
+  remaps_t m_remaps;
+  typedef vector<IShader*> shaders_t;
+  shaders_t m_shaders;
+};
+
+class ModelWrapper : public IRender, public ISelect
+{
+  unsigned int m_refcount;
+public:
+  ModelWrapper(entity_interfaces_t* model, const char* name)
+    : m_refcount(1), m_name(name)
+  {
+    m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), 0));
+
+    model->pRender = this;
+    model->pRender->IncRef();
+    model->pEdit = NULL;
+    model->pSelect = this;
+    model->pSelect->IncRef();
+  }
+  virtual ~ModelWrapper()
+  {
+    g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), 0));
+       }
+
+  virtual void IncRef()
+  {
+    ++m_refcount;
+  }
+  virtual void DecRef()
+  {
+    if(--m_refcount == 0)
+      delete this;
+  }
+  virtual void Draw(int state, int rflags) const
+  {
+    m_model->Draw(state, rflags);
+  }
+  virtual const aabb_t *GetAABB() const 
+  {
+    return m_model->GetAABB();
+  }
+  virtual bool TestRay(const ray_t *ray, vec_t *dist) const
+  {
+    return m_model->TestRay(ray, dist);
+  }
+
+  Str m_name;
+  CPicoModel* m_model;
+};
+
+void LoadModel(entity_interfaces_t* model, const char* name)
+{
+  if(strchr(name, ':') != NULL || strchr(name, '?') != NULL || strchr(name, '&') != NULL)
+  {
+    RemapWrapper* wrapper = new RemapWrapper(model, name);
+    wrapper->DecRef();
+  }
+  else
+  {
+    ModelWrapper* wrapper = new ModelWrapper(model, name);
+    wrapper->DecRef();
+  }
+}