/*
- Copyright (C) 1999-2007 id Software, Inc. and contributors.
+ 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.
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"
+
+
+class CPointfile;
+void Pointfile_Parse( CPointfile& pointfile );
+
+
+class CPointfile : public ISAXHandler, public Renderable, public OpenGLRenderable
+{
+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();
+
+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();
+ }
+}
+
+void render( RenderStateFlags state ) const {
+ glCallList( m_displaylist );
+}
-#define MAX_POINTFILE 8192
-static vec3_t s_pointvecs[MAX_POINTFILE];
-static int s_num_points, s_check_point;
+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 );
+ }
+}
+void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
+ renderSolid( renderer, volume );
+}
-CPointfile g_pointfile;
+static void constructStatic(){
+ m_renderstate = GlobalShaderCache().capture( "$POINTFILE" );
+}
-// CPointfile routine used by the standard code ---------------------------------
+static void destroyStatic(){
+ GlobalShaderCache().release( "$POINTFILE" );
+}
+};
+
+Shader* CPointfile::m_renderstate = 0;
+
+namespace
+{
+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( vec3_t v ){
+void CPointfile::PushPoint( const Vector3& v ){
if ( s_num_points < MAX_POINTFILE ) {
- VectorCopy( v, s_pointvecs[s_num_points] );
- s_num_points++;
+ s_pointvecs[s_num_points] = v;
+ ++s_num_points;
}
}
// 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 );
- }
+ m_displaylist = glGenLists( 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] );
- }
- }
- qglEnd();
- qglLineWidth( 1 );
+ glNewList( m_displaylist, GL_COMPILE );
- qglEndList();
+ 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 );
- s_check_point = 0;
+ glEndList();
}
// old (but still relevant) pointfile code -------------------------------------
void Pointfile_Delete( void ){
- char name[1024];
-
- strcpy( name, currentmap );
- StripExtension( name );
- strcat( name, ".lin" );
-
- remove( name );
+ 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;
+ 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;
+ 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 );
+ }
+}
+
+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 WINAPI Pointfile_Check( void ){
- char name[1024];
+void Pointfile_Parse( CPointfile& pointfile ){
int size;
char *data;
char *text;
int line = 1;
- vec3_t v;
- strcpy( name, currentmap );
- StripExtension( name );
- strcat( name, ".lin" );
+ const char* mapname = Map_Name( g_map );
+ StringOutputStream name( 256 );
+ name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".lin";
- size = vfsLoadFullPathFile( name, (void**)&data );
- if ( size <= 0 ) {
- Sys_FPrintf( SYS_ERR, "Pointfile %s not found\n", name );
+ size = LoadFile( name.c_str(), (void**)&data );
+ if ( size == -1 ) {
+ globalErrorStream() << "Pointfile " << name.c_str() << " not found\n";
return;
}
// 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 )
{
+ Vector3 v;
if ( sscanf( data,"%f %f %f", &v[0], &v[1], &v[2] ) != 3 ) {
- Sys_Printf( "Corrupt point file, line %d\n",line );
+ globalOutputStream() << "Corrupt point file, line " << line << "\n";
break;
}
// 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 );
+ globalOutputStream() << "Corrupt point file, line " << line << "\n";
break;
}
data++; // skip the \n
line++;
}
- g_pointfile.PushPoint( v );
+ pointfile.PushPoint( v );
}
g_free( text );
+}
+
+void Pointfile_Clear(){
+ s_pointfile.show( false );
+}
- g_pointfile.GenerateDisplayList();
+void Pointfile_Toggle(){
+ s_pointfile.show( !s_pointfile.shown() );
- Sys_UpdateWindows( W_ALL );
+ s_check_point = s_pointfile.begin();
}
-void Pointfile_Draw( void ){
- qglCallList( g_qeglobals.d_pointfile_display_list );
+void Pointfile_Construct(){
+ CPointfile::constructStatic();
+
+ GlobalShaderCache().attachRenderable( s_pointfile );
+
+ GlobalCommands_insert( "TogglePointfile", FreeCaller<Pointfile_Toggle>() );
+ GlobalCommands_insert( "NextLeakSpot", FreeCaller<Pointfile_Next>(), Accelerator( 'K', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
+ GlobalCommands_insert( "PrevLeakSpot", FreeCaller<Pointfile_Prev>(), Accelerator( 'L', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
}
-void Pointfile_Clear( void ){
- if ( !g_qeglobals.d_pointfile_display_list ) {
- return;
- }
+void Pointfile_Destroy(){
+ GlobalShaderCache().detachRenderable( s_pointfile );
- qglDeleteLists( g_qeglobals.d_pointfile_display_list, 1 );
- g_qeglobals.d_pointfile_display_list = 0;
- Sys_UpdateWindows( W_ALL );
+ CPointfile::destroyStatic();
}
-// CPointfile implementation for SAX speicific stuff -------------------------------
+
+
+// CPointfile implementation for SAX-specific stuff -------------------------------
void CPointfile::saxStartElement( message_info_t *ctx, const xmlChar *name, const xmlChar **attrs ){
- if ( strcmp( (char *)name, "polyline" ) == 0 ) {
+ if ( string_equal( reinterpret_cast<const char*>( name ), "polyline" ) ) {
Init();
// there's a prefs setting to avoid stopping on leak
- if ( !g_PrefsDlg.m_bLeakStop ) {
+ if ( !g_WatchBSP_LeakStop ) {
ctx->stop_depth = 0;
}
}
}
void CPointfile::saxEndElement( message_info_t *ctx, const xmlChar *name ){
- if ( strcmp( (char *)name, "polyline" ) == 0 ) {
+ if ( string_equal( reinterpret_cast<const char*>( name ), "polyline" ) ) {
// we are done
GenerateDisplayList();
- ctx->bGeometry = false;
+ 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 );
+ m_characters.write( reinterpret_cast<const char*>( ch ), len );
}
-char * CPointfile::getName(){
- return "Map is leaked";
+const char* CPointfile::getName(){
+ return "Map leaked";
}