2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 The following source code is licensed by Id Software and subject to the terms of
24 its LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with
25 GtkRadiant. If you did not receive a LIMITED USE SOFTWARE LICENSE AGREEMENT,
26 please contact Id Software immediately at info@idsoftware.com.
31 #include "debugging/debugging.h"
35 #include "renderable.h"
37 #include "stream/stringstream.h"
44 #include "camwindow.h"
47 #include "mainframe.h"
53 void Pointfile_Parse(CPointfile& pointfile);
56 class CPointfile : public ISAXHandler, public Renderable, public OpenGLRenderable
62 Vector3 s_pointvecs[MAX_POINTFILE];
63 std::size_t s_num_points;
65 static Shader* m_renderstate;
66 StringOutputStream m_characters;
75 void PushPoint (const Vector3& v);
76 void GenerateDisplayList();
80 // blank because not heap-allocated
82 void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
83 void saxEndElement (message_info_t *ctx, const xmlChar *name);
84 void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
85 const char* getName();
87 typedef const Vector3* const_iterator;
89 const_iterator begin() const
91 return &s_pointvecs[0];
93 const_iterator end() const
95 return &s_pointvecs[s_num_points];
100 return m_displaylist != 0;
106 Pointfile_Parse(*this);
107 GenerateDisplayList();
110 else if(!show && shown())
112 glDeleteLists (m_displaylist, 1);
118 void render(RenderStateFlags state) const
120 glCallList(m_displaylist);
123 void renderSolid(Renderer& renderer, const VolumeTest& volume) const
127 renderer.SetState(m_renderstate, Renderer::eWireframeOnly);
128 renderer.SetState(m_renderstate, Renderer::eFullMaterials);
129 renderer.addRenderable(*this, g_matrix4_identity);
132 void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
134 renderSolid(renderer, volume);
137 static void constructStatic()
139 m_renderstate = GlobalShaderCache().capture("$POINTFILE");
142 static void destroyStatic()
144 GlobalShaderCache().release("$POINTFILE");
148 Shader* CPointfile::m_renderstate = 0;
152 CPointfile s_pointfile;
155 ISAXHandler& g_pointfile = s_pointfile;
157 static CPointfile::const_iterator s_check_point;
159 void CPointfile::Init()
165 void CPointfile::PushPoint(const Vector3& v)
167 if (s_num_points < MAX_POINTFILE)
169 s_pointvecs[s_num_points] = v;
174 // create the display list at the end
175 void CPointfile::GenerateDisplayList()
177 m_displaylist = glGenLists(1);
179 glNewList (m_displaylist, GL_COMPILE);
181 glBegin(GL_LINE_STRIP);
182 for(std::size_t i=0;i<s_num_points;i++)
183 glVertex3fv (vector3_to_array(s_pointvecs[i]));
190 // old (but still relevant) pointfile code -------------------------------------
192 void Pointfile_Delete (void)
194 const char* mapname = Map_Name(g_map);
195 StringOutputStream name(256);
196 name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".lin";
197 file_remove(name.c_str());
200 // advance camera to next point
201 void Pointfile_Next (void)
203 if(!s_pointfile.shown())
206 if (s_check_point+2 == s_pointfile.end())
208 globalOutputStream() << "End of pointfile\n";
212 CPointfile::const_iterator i = ++s_check_point;
215 CamWnd& camwnd = *g_pParentWnd->GetCamWnd();
216 Camera_setOrigin(camwnd, *i);
217 g_pParentWnd->GetXYWnd()->SetOrigin(*i);
219 Vector3 dir(vector3_normalised(vector3_subtracted(*(++i), Camera_getOrigin(camwnd))));
220 Vector3 angles(Camera_getAngles(camwnd));
221 angles[CAMERA_YAW] = static_cast<float>(radians_to_degrees(atan2(dir[1], dir[0])));
222 angles[CAMERA_PITCH] = static_cast<float>(radians_to_degrees(asin(dir[2])));
223 Camera_setAngles(camwnd, angles);
227 // advance camera to previous point
228 void Pointfile_Prev (void)
230 if(!s_pointfile.shown())
233 if (s_check_point == s_pointfile.begin())
235 globalOutputStream() << "Start of pointfile\n";
239 CPointfile::const_iterator i = --s_check_point;
241 CamWnd& camwnd = *g_pParentWnd->GetCamWnd();
242 Camera_setOrigin(camwnd, *i);
243 g_pParentWnd->GetXYWnd()->SetOrigin(*i);
245 Vector3 dir(vector3_normalised(vector3_subtracted(*(++i), Camera_getOrigin(camwnd))));
246 Vector3 angles(Camera_getAngles(camwnd));
247 angles[CAMERA_YAW] = static_cast<float>(radians_to_degrees(atan2(dir[1], dir[0])));
248 angles[CAMERA_PITCH] = static_cast<float>(radians_to_degrees(asin(dir[2])));
249 Camera_setAngles(camwnd, angles);
253 int LoadFile (const char *filename, void **bufferptr)
258 f = fopen (filename, "rb");
262 fseek (f, 0, SEEK_END);
266 *bufferptr = malloc (len+1);
270 fread (*bufferptr, 1, len, f);
273 // we need to end the buffer with a 0
274 ((char*) (*bufferptr))[len] = 0;
279 void Pointfile_Parse(CPointfile& pointfile)
286 const char* mapname = Map_Name(g_map);
287 StringOutputStream name(256);
288 name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".lin";
290 size = LoadFile (name.c_str(), (void**)&data);
293 globalErrorStream() << "Pointfile " << name.c_str() << " not found\n";
300 globalOutputStream() << "Reading pointfile " << name.c_str() << "\n";
307 if (sscanf(data,"%f %f %f", &v[0], &v[1], &v[2]) != 3)
309 globalOutputStream() << "Corrupt point file, line " << line << "\n";
313 while (*data && *data != '\n')
315 if (*(data-1) == ' ' && *(data) == '-' && *(data+1) == ' ')
319 // deal with zhlt style point files.
322 if (sscanf(data,"- %f %f %f", &v[0], &v[1], &v[2]) != 3)
324 globalOutputStream() << "Corrupt point file, line " << line << "\n";
328 while (*data && *data != '\n')
332 while (*data == '\n')
334 data++; // skip the \n
337 pointfile.PushPoint (v);
343 void Pointfile_Clear()
345 s_pointfile.show(false);
348 void Pointfile_Toggle()
350 s_pointfile.show(!s_pointfile.shown());
352 s_check_point = s_pointfile.begin();
355 void Pointfile_Construct()
357 CPointfile::constructStatic();
359 GlobalShaderCache().attachRenderable(s_pointfile);
361 GlobalCommands_insert("TogglePointfile", FreeCaller<Pointfile_Toggle>());
362 GlobalCommands_insert("NextLeakSpot", FreeCaller<Pointfile_Next>(), Accelerator('K', (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
363 GlobalCommands_insert("PrevLeakSpot", FreeCaller<Pointfile_Prev>(), Accelerator('L', (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
366 void Pointfile_Destroy()
368 GlobalShaderCache().detachRenderable(s_pointfile);
370 CPointfile::destroyStatic();
375 // CPointfile implementation for SAX-specific stuff -------------------------------
376 void CPointfile::saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs)
378 if(string_equal(reinterpret_cast<const char*>(name), "polyline"))
381 // there's a prefs setting to avoid stopping on leak
382 if (!g_WatchBSP_LeakStop)
387 void CPointfile::saxEndElement (message_info_t *ctx, const xmlChar *name)
389 if(string_equal(reinterpret_cast<const char*>(name), "polyline"))
392 GenerateDisplayList();
394 s_check_point = begin();
396 else if(string_equal(reinterpret_cast<const char*>(name), "point"))
399 sscanf(m_characters.c_str(), "%f %f %f\n", &v[0], &v[1], &v[2]);
401 m_characters.clear();
405 // only "point" is expected to have characters around here
406 void CPointfile::saxCharacters (message_info_t *ctx, const xmlChar *ch, int len)
408 m_characters.write(reinterpret_cast<const char*>(ch), len);
411 const char* CPointfile::getName()