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"
54 void Pointfile_Parse(CPointfile &pointfile);
57 class CPointfile : public ISAXHandler, public Renderable, public OpenGLRenderable {
61 Vector3 s_pointvecs[MAX_POINTFILE];
62 std::size_t s_num_points;
64 static Shader *m_renderstate;
65 StringOutputStream m_characters;
77 void PushPoint(const Vector3 &v);
79 void GenerateDisplayList();
84 // blank because not heap-allocated
87 void saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
89 void saxEndElement(message_info_t *ctx, const xmlChar *name);
91 void saxCharacters(message_info_t *ctx, const xmlChar *ch, int len);
93 const char *getName();
95 typedef const Vector3 *const_iterator;
97 const_iterator begin() const
99 return &s_pointvecs[0];
102 const_iterator end() const
104 return &s_pointvecs[s_num_points];
109 return m_displaylist != 0;
114 if (show && !shown()) {
115 Pointfile_Parse(*this);
116 GenerateDisplayList();
118 } else if (!show && shown()) {
119 glDeleteLists(m_displaylist, 1);
125 void render(RenderStateFlags state) const
127 glCallList(m_displaylist);
130 void renderSolid(Renderer &renderer, const VolumeTest &volume) const
133 renderer.SetState(m_renderstate, Renderer::eWireframeOnly);
134 renderer.SetState(m_renderstate, Renderer::eFullMaterials);
135 renderer.addRenderable(*this, g_matrix4_identity);
139 void renderWireframe(Renderer &renderer, const VolumeTest &volume) const
141 renderSolid(renderer, volume);
144 static void constructStatic()
146 m_renderstate = GlobalShaderCache().capture("$POINTFILE");
149 static void destroyStatic()
151 GlobalShaderCache().release("$POINTFILE");
155 Shader *CPointfile::m_renderstate = 0;
158 CPointfile s_pointfile;
161 ISAXHandler &g_pointfile = s_pointfile;
163 static CPointfile::const_iterator s_check_point;
165 void CPointfile::Init()
171 void CPointfile::PushPoint(const Vector3 &v)
173 if (s_num_points < MAX_POINTFILE) {
174 s_pointvecs[s_num_points] = v;
179 // create the display list at the end
180 void CPointfile::GenerateDisplayList()
182 m_displaylist = glGenLists(1);
184 glNewList(m_displaylist, GL_COMPILE);
186 glBegin(GL_LINE_STRIP);
187 for (std::size_t i = 0; i < s_num_points; i++)
188 glVertex3fv(vector3_to_array(s_pointvecs[i]));
195 // old (but still relevant) pointfile code -------------------------------------
197 void Pointfile_Delete(void)
199 const char *mapname = Map_Name(g_map);
200 StringOutputStream name(256);
201 name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".lin";
202 file_remove(name.c_str());
205 // advance camera to next point
206 void Pointfile_Next(void)
208 if (!s_pointfile.shown()) {
212 if (s_check_point + 2 == s_pointfile.end()) {
213 globalOutputStream() << "End of pointfile\n";
217 CPointfile::const_iterator i = ++s_check_point;
220 CamWnd &camwnd = *g_pParentWnd->GetCamWnd();
221 Camera_setOrigin(camwnd, *i);
222 g_pParentWnd->GetXYWnd()->SetOrigin(*i);
224 Vector3 dir(vector3_normalised(vector3_subtracted(*(++i), Camera_getOrigin(camwnd))));
225 Vector3 angles(Camera_getAngles(camwnd));
226 angles[CAMERA_YAW] = static_cast<float>( radians_to_degrees(atan2(dir[1], dir[0])));
227 angles[CAMERA_PITCH] = static_cast<float>( radians_to_degrees(asin(dir[2])));
228 Camera_setAngles(camwnd, angles);
232 // advance camera to previous point
233 void Pointfile_Prev(void)
235 if (!s_pointfile.shown()) {
239 if (s_check_point == s_pointfile.begin()) {
240 globalOutputStream() << "Start of pointfile\n";
244 CPointfile::const_iterator i = --s_check_point;
246 CamWnd &camwnd = *g_pParentWnd->GetCamWnd();
247 Camera_setOrigin(camwnd, *i);
248 g_pParentWnd->GetXYWnd()->SetOrigin(*i);
250 Vector3 dir(vector3_normalised(vector3_subtracted(*(++i), Camera_getOrigin(camwnd))));
251 Vector3 angles(Camera_getAngles(camwnd));
252 angles[CAMERA_YAW] = static_cast<float>( radians_to_degrees(atan2(dir[1], dir[0])));
253 angles[CAMERA_PITCH] = static_cast<float>( radians_to_degrees(asin(dir[2])));
254 Camera_setAngles(camwnd, angles);
258 int LoadFile(const char *filename, void **bufferptr)
263 f = fopen(filename, "rb");
268 fseek(f, 0, SEEK_END);
272 *bufferptr = malloc(len + 1);
273 if (*bufferptr == 0) {
277 fread(*bufferptr, 1, len, f);
280 // we need to end the buffer with a 0
281 ((char *) (*bufferptr))[len] = 0;
286 void Pointfile_Parse(CPointfile &pointfile)
293 const char *mapname = Map_Name(g_map);
294 StringOutputStream name(256);
295 name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".lin";
297 size = LoadFile(name.c_str(), (void **) &data);
299 globalErrorStream() << "Pointfile " << name.c_str() << " not found\n";
306 globalOutputStream() << "Reading pointfile " << name.c_str() << "\n";
312 if (sscanf(data, "%f %f %f", &v[0], &v[1], &v[2]) != 3) {
313 globalOutputStream() << "Corrupt point file, line " << line << "\n";
317 while (*data && *data != '\n') {
318 if (*(data - 1) == ' ' && *(data) == '-' && *(data + 1) == ' ') {
323 // deal with zhlt style point files.
325 if (sscanf(data, "- %f %f %f", &v[0], &v[1], &v[2]) != 3) {
326 globalOutputStream() << "Corrupt point file, line " << line << "\n";
330 while (*data && *data != '\n') {
335 while (*data == '\n') {
336 data++; // skip the \n
339 pointfile.PushPoint(v);
345 void Pointfile_Clear()
347 s_pointfile.show(false);
350 void Pointfile_Toggle()
352 s_pointfile.show(!s_pointfile.shown());
354 s_check_point = s_pointfile.begin();
357 void Pointfile_Construct()
359 CPointfile::constructStatic();
361 GlobalShaderCache().attachRenderable(s_pointfile);
363 GlobalCommands_insert("TogglePointfile", makeCallbackF(Pointfile_Toggle));
364 GlobalCommands_insert("NextLeakSpot", makeCallbackF(Pointfile_Next),
365 Accelerator('K', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK)));
366 GlobalCommands_insert("PrevLeakSpot", makeCallbackF(Pointfile_Prev),
367 Accelerator('L', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK)));
370 void Pointfile_Destroy()
372 GlobalShaderCache().detachRenderable(s_pointfile);
374 CPointfile::destroyStatic();
378 // CPointfile implementation for SAX-specific stuff -------------------------------
379 void CPointfile::saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs)
381 if (string_equal(reinterpret_cast<const char *>( name ), "polyline")) {
383 // there's a prefs setting to avoid stopping on leak
384 if (!g_WatchBSP_LeakStop) {
390 void CPointfile::saxEndElement(message_info_t *ctx, const xmlChar *name)
392 if (string_equal(reinterpret_cast<const char *>( name ), "polyline")) {
394 GenerateDisplayList();
396 s_check_point = begin();
397 } 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()