]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - plugins/model/remap.cpp
uncrustify! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / plugins / model / remap.cpp
index dbcef14fe46529e7f325ce71d577338fbfa85e44..4ffc342a5482e5c0f132ac55a51332bb91cc4377 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 );
+               // 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();
+       }
+}