X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=radiant%2Fpoints.cpp;h=6e29109c845b314e6bce182a01a90f39c0055daa;hb=6011367844c51d4805528385f7f91d2eb36299eb;hp=2da929768596ab0574e77e457c8153a373b4a1b5;hpb=5265d3cc1517566910718738ee6fa48e2466d3ea;p=xonotic%2Fnetradiant.git diff --git a/radiant/points.cpp b/radiant/points.cpp index 2da92976..6e29109c 100644 --- a/radiant/points.cpp +++ b/radiant/points.cpp @@ -1,249 +1,414 @@ /* -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" + + +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]; + } -#define MAX_POINTFILE 8192 -static vec3_t s_pointvecs[MAX_POINTFILE]; -static int s_num_points, s_check_point; + bool shown() const + { + return m_displaylist != 0; + } -CPointfile g_pointfile; + 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); + } + + 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); + } + + static void constructStatic() + { + m_renderstate = GlobalShaderCache().capture("$POINTFILE"); + } + + static void destroyStatic() + { + GlobalShaderCache().release("$POINTFILE"); + } +}; -// CPointfile routine used by the standard code --------------------------------- +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; + 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++; - } + if (s_num_points < MAX_POINTFILE) { + 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); - - 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-2) - { - Sys_Status ("End of pointfile", 0); - 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); + 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( radians_to_degrees(atan2(dir[1], dir[0]))); + angles[CAMERA_PITCH] = static_cast( radians_to_degrees(asin(dir[2]))); + Camera_setAngles(camwnd, angles); + } } // advance camera to previous point -void Pointfile_Prev (void) +void Pointfile_Prev(void) { - vec3_t dir; + if (!s_pointfile.shown()) { + return; + } + + if (s_check_point == s_pointfile.begin()) { + globalOutputStream() << "Start of pointfile\n"; + return; + } - if ( s_check_point == 0) - { - Sys_Status ("Start of pointfile", 0); - 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; + CPointfile::const_iterator i = --s_check_point; - Sys_UpdateWindows (W_ALL); + 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( radians_to_degrees(atan2(dir[1], dir[0]))); + angles[CAMERA_PITCH] = static_cast( radians_to_degrees(asin(dir[2]))); + Camera_setAngles(camwnd, angles); + } } -void WINAPI Pointfile_Check (void) +int LoadFile(const char *filename, void **bufferptr) { - char name[1024]; - int size; - char *data; - char *text; - int line = 1; - vec3_t v; + FILE *f; + long len; - strcpy (name, currentmap); - StripExtension (name); - strcat (name, ".lin"); + f = fopen(filename, "rb"); + if (f == 0) { + return -1; + } - size = vfsLoadFullPathFile (name, (void**)&data); - if (size <= 0) - { - Sys_FPrintf (SYS_ERR, "Pointfile %s not found\n", name); - return; - } + fseek(f, 0, SEEK_END); + len = ftell(f); + rewind(f); - // store a pointer - text = data; + *bufferptr = malloc(len + 1); + if (*bufferptr == 0) { + return -1; + } - Sys_Printf ("Reading pointfile %s\n", name); + fread(*bufferptr, 1, len, f); + fclose(f); - g_pointfile.Init(); + // we need to end the buffer with a 0 + ((char *) (*bufferptr))[len] = 0; - while (*data) - { - if (sscanf(data,"%f %f %f", &v[0], &v[1], &v[2]) != 3) - { - Sys_Printf("Corrupt point file, line %d\n",line); - break; + 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; } - while (*data && *data != '\n') - { - if (*(data-1) == ' ' && *(data) == '-' && *(data+1) == ' ') - break; - data++; + // store a pointer + text = data; + + globalOutputStream() << "Reading pointfile " << name.c_str() << "\n"; + + pointfile.Init(); + + while (*data) { + 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) { + globalOutputStream() << "Corrupt point file, line " << line << "\n"; + break; + } + + while (*data && *data != '\n') { + data++; + } + + } + while (*data == '\n') { + data++; // skip the \n + line++; + } + pointfile.PushPoint(v); } - // 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++; + g_free(text); +} - } - while (*data == '\n') - { - data++; // skip the \n - line++; - } - g_pointfile.PushPoint (v); - } +void Pointfile_Clear() +{ + s_pointfile.show(false); +} - g_free(text); - - 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 ) +void Pointfile_Construct() { - qglCallList (g_qeglobals.d_pointfile_display_list); + 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 Pointfile_Clear (void) +void Pointfile_Destroy() { - if (!g_qeglobals.d_pointfile_display_list) - return; + 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 ------------------------------- -void CPointfile::saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs) + +// 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) - { - Init(); - // there's a prefs setting to avoid stopping on leak - if (!g_PrefsDlg.m_bLeakStop) - ctx->stop_depth = 0; - } + if (string_equal(reinterpret_cast( 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) +void CPointfile::saxEndElement(message_info_t *ctx, const xmlChar *name) { - if (strcmp ((char *)name, "polyline")==0) - { - // we are done - GenerateDisplayList(); - ctx->bGeometry = false; - } + if (string_equal(reinterpret_cast( name ), "polyline")) { + // we are done + GenerateDisplayList(); + SceneChangeNotify(); + s_check_point = begin(); + } else if (string_equal(reinterpret_cast( 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) +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( ch ), len); } -char * CPointfile::getName() +const char *CPointfile::getName() { - return "Map is leaked"; + return "Map leaked"; }