]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/points.cpp
Merge branch 'flake' into 'master'
[xonotic/netradiant.git] / radiant / points.cpp
index 2da929768596ab0574e77e457c8153a373b4a1b5..c4a56492ee86ed73f0c2093d7f73ecfb08e91442 100644 (file)
 /*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
+   Copyright (C) 1999-2006 Id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
 
-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 "stdafx.h"
+/*
+   The following source code is licensed by Id Software and subject to the terms of
+   its LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with
+   GtkRadiant. If you did not receive a LIMITED USE SOFTWARE LICENSE AGREEMENT,
+   please contact Id Software immediately at info@idsoftware.com.
+ */
+
+#include "points.h"
+
+#include "debugging/debugging.h"
+
+#include "irender.h"
+#include "igl.h"
+#include "renderable.h"
+
+#include "stream/stringstream.h"
+#include "os/path.h"
+#include "os/file.h"
+#include "cmdlib.h"
+
+#include "map.h"
+#include "qe3.h"
+#include "camwindow.h"
+#include "xywindow.h"
+#include "xmlstuff.h"
+#include "mainframe.h"
+#include "watchbsp.h"
+#include "commands.h"
 
-#define        MAX_POINTFILE   8192
-static vec3_t  s_pointvecs[MAX_POINTFILE];
-static int             s_num_points, s_check_point;
 
-CPointfile g_pointfile;
+class CPointfile;
+void Pointfile_Parse( CPointfile& pointfile );
 
-// CPointfile routine used by the standard code ---------------------------------
 
-void CPointfile::Init()
+class CPointfile : public ISAXHandler, public Renderable, public OpenGLRenderable
 {
-  s_num_points = 0;
+enum
+{
+       MAX_POINTFILE = 8192,
+};
+Vector3 s_pointvecs[MAX_POINTFILE];
+std::size_t s_num_points;
+int m_displaylist;
+static Shader* m_renderstate;
+StringOutputStream m_characters;
+public:
+CPointfile(){
+}
+~CPointfile(){
+}
+void Init();
+void PushPoint( const Vector3& v );
+void GenerateDisplayList();
+// SAX interface
+void Release(){
+       // blank because not heap-allocated
 }
+void saxStartElement( message_info_t *ctx, const xmlChar *name, const xmlChar **attrs );
+void saxEndElement( message_info_t *ctx, const xmlChar *name );
+void saxCharacters( message_info_t *ctx, const xmlChar *ch, int len );
+const char* getName();
 
-void CPointfile::PushPoint (vec3_t v)
-{
-       if (s_num_points < MAX_POINTFILE)
-       {
-               VectorCopy (v, s_pointvecs[s_num_points]);
-               s_num_points++;
+typedef const Vector3* const_iterator;
+
+const_iterator begin() const {
+       return &s_pointvecs[0];
+}
+const_iterator end() const {
+       return &s_pointvecs[s_num_points];
+}
+
+bool shown() const {
+       return m_displaylist != 0;
+}
+void show( bool show ){
+       if ( show && !shown() ) {
+               Pointfile_Parse( *this );
+               GenerateDisplayList();
+               SceneChangeNotify();
+       }
+       else if ( !show && shown() ) {
+               glDeleteLists( m_displaylist, 1 );
+               m_displaylist = 0;
+               SceneChangeNotify();
        }
 }
 
-// create the display list at the end
-void CPointfile::GenerateDisplayList()
-{
-  int i;
-
-       if (!g_qeglobals.d_pointfile_display_list)
-               g_qeglobals.d_pointfile_display_list = qglGenLists(1);
-
-  qglNewList (g_qeglobals.d_pointfile_display_list,  GL_COMPILE);
-  
-       qglColor3f (1, 0, 0);
-       qglDisable(GL_TEXTURE_2D);
-       qglDisable(GL_TEXTURE_1D);
-       qglLineWidth (4);
-       qglBegin(GL_LINE_STRIP);
-       for (i=0;i<s_num_points;i++)
-       {
-         if (s_num_points < MAX_POINTFILE)
-         {
-           qglVertex3fv (s_pointvecs[i]);
-         }
+void render( RenderStateFlags state ) const {
+       glCallList( m_displaylist );
+}
+
+void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
+       if ( shown() ) {
+               renderer.SetState( m_renderstate, Renderer::eWireframeOnly );
+               renderer.SetState( m_renderstate, Renderer::eFullMaterials );
+               renderer.addRenderable( *this, g_matrix4_identity );
        }
-       qglEnd();
-       qglLineWidth (1);
-       
-       qglEndList ();
-       
-       s_check_point = 0;
+}
+void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
+       renderSolid( renderer, volume );
 }
 
-// old (but still relevant) pointfile code -------------------------------------
+static void constructStatic(){
+       m_renderstate = GlobalShaderCache().capture( "$POINTFILE" );
+}
+
+static void destroyStatic(){
+       GlobalShaderCache().release( "$POINTFILE" );
+}
+};
 
-void Pointfile_Delete (void)
+Shader* CPointfile::m_renderstate = 0;
+
+namespace
 {
-       char    name[1024];
+CPointfile s_pointfile;
+}
+
+ISAXHandler& g_pointfile = s_pointfile;
+
+static CPointfile::const_iterator s_check_point;
+
+void CPointfile::Init(){
+       s_num_points = 0;
+       m_displaylist = 0;
+}
+
+void CPointfile::PushPoint( const Vector3& v ){
+       if ( s_num_points < MAX_POINTFILE ) {
+               s_pointvecs[s_num_points] = v;
+               ++s_num_points;
+       }
+}
 
-       strcpy (name, currentmap);
-       StripExtension (name);
-       strcat (name, ".lin");
+// create the display list at the end
+void CPointfile::GenerateDisplayList(){
+       m_displaylist = glGenLists( 1 );
+
+       glNewList( m_displaylist,  GL_COMPILE );
+
+       glBegin( GL_LINE_STRIP );
+       for ( std::size_t i = 0; i < s_num_points; i++ )
+               glVertex3fv( vector3_to_array( s_pointvecs[i] ) );
+       glEnd();
+       glLineWidth( 1 );
+
+       glEndList();
+}
+
+// old (but still relevant) pointfile code -------------------------------------
 
-       remove(name);
+void Pointfile_Delete( void ){
+       const char* mapname = Map_Name( g_map );
+       StringOutputStream name( 256 );
+       name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".lin";
+       file_remove( name.c_str() );
 }
 
 // advance camera to next point
-void Pointfile_Next (void)
-{
-       vec3_t  dir;
+void Pointfile_Next( void ){
+       if ( !s_pointfile.shown() ) {
+               return;
+       }
 
-       if (s_check_point >= s_num_points-2)
-       {
-               Sys_Status ("End of pointfile", 0);
+       if ( s_check_point + 2 == s_pointfile.end() ) {
+               globalOutputStream() << "End of pointfile\n";
                return;
        }
-       s_check_point++;
-       VectorCopy (s_pointvecs[s_check_point], g_pParentWnd->GetCamWnd()->Camera()->origin);
-       VectorCopy (s_pointvecs[s_check_point], g_pParentWnd->GetXYWnd()->GetOrigin());
-       VectorSubtract (s_pointvecs[s_check_point+1], g_pParentWnd->GetCamWnd()->Camera()->origin, dir);
-       VectorNormalize (dir, dir);
-       g_pParentWnd->GetCamWnd()->Camera()->angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
-       g_pParentWnd->GetCamWnd()->Camera()->angles[0] = asin (dir[2])*180/3.14159;
 
-       Sys_UpdateWindows (W_ALL);
+       CPointfile::const_iterator i = ++s_check_point;
+
+
+       CamWnd& camwnd = *g_pParentWnd->GetCamWnd();
+       Camera_setOrigin( camwnd, *i );
+       g_pParentWnd->GetXYWnd()->SetOrigin( *i );
+       {
+               Vector3 dir( vector3_normalised( vector3_subtracted( *( ++i ), Camera_getOrigin( camwnd ) ) ) );
+               Vector3 angles( Camera_getAngles( camwnd ) );
+               angles[CAMERA_YAW] = static_cast<float>( radians_to_degrees( atan2( dir[1], dir[0] ) ) );
+               angles[CAMERA_PITCH] = static_cast<float>( radians_to_degrees( asin( dir[2] ) ) );
+               Camera_setAngles( camwnd, angles );
+       }
 }
 
 // advance camera to previous point
-void Pointfile_Prev (void)
-{
-       vec3_t  dir;
+void Pointfile_Prev( void ){
+       if ( !s_pointfile.shown() ) {
+               return;
+       }
 
-       if ( s_check_point == 0)
-       {
-               Sys_Status ("Start of pointfile", 0);
+       if ( s_check_point == s_pointfile.begin() ) {
+               globalOutputStream() << "Start of pointfile\n";
                return;
        }
-       s_check_point--;
-       VectorCopy (s_pointvecs[s_check_point], g_pParentWnd->GetCamWnd()->Camera()->origin);
-       VectorCopy (s_pointvecs[s_check_point], g_pParentWnd->GetXYWnd()->GetOrigin());
-       VectorSubtract (s_pointvecs[s_check_point+1], g_pParentWnd->GetCamWnd()->Camera()->origin, dir);
-       VectorNormalize (dir, dir);
-       g_pParentWnd->GetCamWnd()->Camera()->angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
-       g_pParentWnd->GetCamWnd()->Camera()->angles[0] = asin (dir[2])*180/3.14159;
 
-       Sys_UpdateWindows (W_ALL);
+       CPointfile::const_iterator i = --s_check_point;
+
+       CamWnd& camwnd = *g_pParentWnd->GetCamWnd();
+       Camera_setOrigin( camwnd, *i );
+       g_pParentWnd->GetXYWnd()->SetOrigin( *i );
+       {
+               Vector3 dir( vector3_normalised( vector3_subtracted( *( ++i ), Camera_getOrigin( camwnd ) ) ) );
+               Vector3 angles( Camera_getAngles( camwnd ) );
+               angles[CAMERA_YAW] = static_cast<float>( radians_to_degrees( atan2( dir[1], dir[0] ) ) );
+               angles[CAMERA_PITCH] = static_cast<float>( radians_to_degrees( asin( dir[2] ) ) );
+               Camera_setAngles( camwnd, angles );
+       }
 }
 
-void WINAPI Pointfile_Check (void)
-{
-       char    name[1024];
-       int             size;
-       char    *data;
-  char  *text;
-  int   line = 1;
-       vec3_t v;
-
-       strcpy (name, currentmap);
-       StripExtension (name);
-       strcat (name, ".lin");
-
-       size = vfsLoadFullPathFile (name, (void**)&data);
-  if (size <= 0)
-  {
-    Sys_FPrintf (SYS_ERR, "Pointfile %s not found\n", name);
+int LoadFile( const char *filename, void **bufferptr ){
+       FILE *f;
+       long len;
+
+       f = fopen( filename, "rb" );
+       if ( f == 0 ) {
+               return -1;
+       }
+
+       fseek( f, 0, SEEK_END );
+       len = ftell( f );
+       rewind( f );
+
+       *bufferptr = malloc( len + 1 );
+       if ( *bufferptr == 0 ) {
+               return -1;
+       }
+
+       fread( *bufferptr, 1, len, f );
+       fclose( f );
+
+       // we need to end the buffer with a 0
+       ( (char*) ( *bufferptr ) )[len] = 0;
+
+       return len;
+}
+
+void Pointfile_Parse( CPointfile& pointfile ){
+       int size;
+       char    *data;
+       char  *text;
+       int line = 1;
+
+       const char* mapname = Map_Name( g_map );
+       StringOutputStream name( 256 );
+       name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".lin";
+
+       size = LoadFile( name.c_str(), (void**)&data );
+       if ( size == -1 ) {
+               globalErrorStream() << "Pointfile " << name.c_str() << " not found\n";
                return;
-  }
+       }
 
-  // store a pointer
-  text = data;
+       // store a pointer
+       text = data;
 
-       Sys_Printf ("Reading pointfile %s\n", name);
+       globalOutputStream() << "Reading pointfile " << name.c_str() << "\n";
 
-  g_pointfile.Init();
+       pointfile.Init();
 
-       while (*data)
+       while ( *data )
        {
-    if (sscanf(data,"%f %f %f", &v[0], &v[1], &v[2]) != 3)
-    {
-      Sys_Printf("Corrupt point file, line %d\n",line);
+               Vector3 v;
+               if ( sscanf( data,"%f %f %f", &v[0], &v[1], &v[2] ) != 3 ) {
+                       globalOutputStream() << "Corrupt point file, line " << line << "\n";
                        break;
-    }
-
-       while (*data && *data != '\n')
-    {
-      if (*(data-1) == ' ' && *(data) == '-' && *(data+1) == ' ')
-        break;
-                 data++;
-    }
-    // deal with zhlt style point files.
-    if (*data == '-')
-    {
-      if (sscanf(data,"- %f %f %f", &v[0], &v[1], &v[2]) != 3)
-      {
-        Sys_Printf("Corrupt point file, line %d\n",line);
-        break;
-      }
-
-      while (*data && *data != '\n')
-                   data++;
-
-    }
-    while (*data == '\n')
-    {
-      data++; // skip the \n
-      line++;
-    }
-               g_pointfile.PushPoint (v);
-       }
-
-  g_free(text);
-       
-       g_pointfile.GenerateDisplayList();
-
-  Sys_UpdateWindows (W_ALL);
-}
-
-void Pointfile_Draw( void )
-{
-  qglCallList (g_qeglobals.d_pointfile_display_list);
+               }
+
+               while ( *data && *data != '\n' )
+               {
+                       if ( *( data - 1 ) == ' ' && *( data ) == '-' && *( data + 1 ) == ' ' ) {
+                               break;
+                       }
+                       data++;
+               }
+               // deal with zhlt style point files.
+               if ( *data == '-' ) {
+                       if ( sscanf( data,"- %f %f %f", &v[0], &v[1], &v[2] ) != 3 ) {
+                               globalOutputStream() << "Corrupt point file, line " << line << "\n";
+                               break;
+                       }
+
+                       while ( *data && *data != '\n' )
+                               data++;
+
+               }
+               while ( *data == '\n' )
+               {
+                       data++; // skip the \n
+                       line++;
+               }
+               pointfile.PushPoint( v );
+       }
+
+       g_free( text );
 }
 
-void Pointfile_Clear (void)
-{
-       if (!g_qeglobals.d_pointfile_display_list)
-               return;
+void Pointfile_Clear(){
+       s_pointfile.show( false );
+}
 
-       qglDeleteLists (g_qeglobals.d_pointfile_display_list, 1);
-       g_qeglobals.d_pointfile_display_list = 0;
-       Sys_UpdateWindows (W_ALL);
+void Pointfile_Toggle(){
+       s_pointfile.show( !s_pointfile.shown() );
+
+       s_check_point = s_pointfile.begin();
 }
 
-// CPointfile implementation for SAX speicific stuff -------------------------------
-void CPointfile::saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs)
-{
-  if (strcmp ((char *)name, "polyline")==0)
-  {
-    Init();
-    // there's a prefs setting to avoid stopping on leak
-    if (!g_PrefsDlg.m_bLeakStop)
-      ctx->stop_depth = 0;
-  }
+void Pointfile_Construct(){
+       CPointfile::constructStatic();
+
+       GlobalShaderCache().attachRenderable( s_pointfile );
+
+       GlobalCommands_insert( "TogglePointfile", makeCallbackF(Pointfile_Toggle) );
+       GlobalCommands_insert( "NextLeakSpot", makeCallbackF(Pointfile_Next), Accelerator( 'K', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
+       GlobalCommands_insert( "PrevLeakSpot", makeCallbackF(Pointfile_Prev), Accelerator( 'L', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
 }
 
-void CPointfile::saxEndElement (message_info_t *ctx, const xmlChar *name)
-{
-  if (strcmp ((char *)name, "polyline")==0)
-  {
-    // we are done
-    GenerateDisplayList();
-    ctx->bGeometry = false;
-  }
+void Pointfile_Destroy(){
+       GlobalShaderCache().detachRenderable( s_pointfile );
+
+       CPointfile::destroyStatic();
+}
+
+
+
+// CPointfile implementation for SAX-specific stuff -------------------------------
+void CPointfile::saxStartElement( message_info_t *ctx, const xmlChar *name, const xmlChar **attrs ){
+       if ( string_equal( reinterpret_cast<const char*>( name ), "polyline" ) ) {
+               Init();
+               // there's a prefs setting to avoid stopping on leak
+               if ( !g_WatchBSP_LeakStop ) {
+                       ctx->stop_depth = 0;
+               }
+       }
+}
+
+void CPointfile::saxEndElement( message_info_t *ctx, const xmlChar *name ){
+       if ( string_equal( reinterpret_cast<const char*>( name ), "polyline" ) ) {
+               // we are done
+               GenerateDisplayList();
+               SceneChangeNotify();
+               s_check_point = begin();
+       }
+       else if ( string_equal( reinterpret_cast<const char*>( name ), "point" ) ) {
+               Vector3 v;
+               sscanf( m_characters.c_str(), "%f %f %f\n", &v[0], &v[1], &v[2] );
+               PushPoint( v );
+               m_characters.clear();
+       }
 }
 
 // only "point" is expected to have characters around here
-void CPointfile::saxCharacters (message_info_t *ctx, const xmlChar *ch, int len)
-{
-  vec3_t v;
-  
-  sscanf ((char *)ch, "%f %f %f\n", &v[0], &v[1], &v[2]);
-  PushPoint (v);
+void CPointfile::saxCharacters( message_info_t *ctx, const xmlChar *ch, int len ){
+       m_characters.write( reinterpret_cast<const char*>( ch ), len );
 }
 
-char * CPointfile::getName()
-{
-  return "Map is leaked";
+const char* CPointfile::getName(){
+       return "Map leaked";
 }