/* BobToolz plugin for GtkRadiant Copyright (C) 2001 Gordon Biggans This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "CPortals.h" #include #include #include #include "misc.h" const int LINE_BUF = 1000; const char *MSG_PREFIX = "bobToolz plugin: "; // these classes are far less of a mess than my code was, // thanq to G.DeWan 4 the prtview source on which it was based CBspPortal::CBspPortal() { memset(this, 0, sizeof(CBspPortal)); } CBspPortal::~CBspPortal() { delete[] point; } void ClampFloat(float *p) { double i; double frac = modf(*p, &i); if (!frac) { return; } if (fabs(*p - ceil(*p)) < MAX_ROUND_ERROR) { *p = static_cast( ceil(*p)); } if (fabs(*p - floor(*p)) < MAX_ROUND_ERROR) { *p = static_cast( floor(*p)); } } bool CBspPortal::Build(char *def, unsigned int pointCnt, bool bInverse) { char *c = def; unsigned int n; point_count = pointCnt; if (point_count < 3) { return false; } point = new CBspPoint[point_count]; for (n = 0; n < point_count; n++) { for (; *c != 0 && *c != '('; c++) {} if (*c == 0) { return false; } c++; int x; if (bInverse) { x = point_count - n - 1; } else { x = n; } sscanf(c, "%f %f %f", &point[x].p[0], &point[x].p[1], &point[x].p[2]); ClampFloat(&point[x].p[0]); ClampFloat(&point[x].p[1]); ClampFloat(&point[x].p[2]); } return true; } CPortals::CPortals() { memset(this, 0, sizeof(CPortals)); } CPortals::~CPortals() { Purge(); } void CPortals::Purge() { if (node) { delete[] node; } node = NULL; node_count = 0; } void CPortals::Load() { char buf[LINE_BUF + 1]; memset(buf, 0, LINE_BUF + 1); Purge(); globalOutputStream() << MSG_PREFIX << "Loading portal file " << fn << ".\n"; FILE *in; in = fopen(fn, "rt"); if (in == NULL) { globalOutputStream() << " ERROR - could not open file.\n"; return; } if (!fgets(buf, LINE_BUF, in)) { fclose(in); globalOutputStream() << " ERROR - File ended prematurely.\n"; return; } if (strncmp("PRT1", buf, 4) != 0) { fclose(in); globalOutputStream() << " ERROR - File header indicates wrong file type (should be \"PRT1\").\n"; return; } if (!fgets(buf, LINE_BUF, in)) { fclose(in); globalOutputStream() << " ERROR - File ended prematurely.\n"; return; } sscanf(buf, "%u", &node_count); if (node_count > 0xFFFF) { fclose(in); node_count = 0; globalOutputStream() << " ERROR - Extreme number of nodes, aborting.\n"; return; } if (!fgets(buf, LINE_BUF, in)) { fclose(in); node_count = 0; globalOutputStream() << " ERROR - File ended prematurely.\n"; return; } unsigned int p_count; sscanf(buf, "%u", &p_count); if (!fgets(buf, LINE_BUF, in)) { fclose(in); node_count = 0; globalOutputStream() << " ERROR - File ended prematurely.\n"; return; } unsigned int p_count2; sscanf(buf, "%u", &p_count2); node = new CBspNode[node_count]; unsigned int i; for (i = 0; i < p_count; i++) { if (!fgets(buf, LINE_BUF, in)) { fclose(in); node_count = 0; globalOutputStream() << " ERROR - File ended prematurely.\n"; return; } unsigned int dummy, node1, node2; sscanf(buf, "%u %u %u", &dummy, &node1, &node2); node[node1].portal_count++; node[node2].portal_count++; } for (i = 0; i < p_count2; i++) { if (!fgets(buf, LINE_BUF, in)) { fclose(in); node_count = 0; globalOutputStream() << " ERROR - File ended prematurely.\n"; return; } unsigned int dummy, node1; sscanf(buf, "%u %u", &dummy, &node1); node[node1].portal_count++; } for (i = 0; i < node_count; i++) { node[i].portal = new CBspPortal[node[i].portal_count]; } fclose(in); in = fopen(fn, "rt"); assert(fgets(buf, LINE_BUF, in)); assert(fgets(buf, LINE_BUF, in)); assert(fgets(buf, LINE_BUF, in)); assert(fgets(buf, LINE_BUF, in)); unsigned int n; for (n = 0; n < p_count; n++) { if (!fgets(buf, LINE_BUF, in)) { fclose(in); Purge(); globalOutputStream() << " ERROR - Could not find information for portal number " << n + 1 << " of " << p_count << ".\n"; return; } unsigned int pCount, node1, node2; sscanf(buf, "%u %u %u", &pCount, &node1, &node2); if (!node[node1].AddPortal(buf, pCount, false)) { fclose(in); Purge(); globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n"; return; } if (!node[node2].AddPortal(buf, pCount, true)) { fclose(in); Purge(); globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n"; return; } } for (n = 0; n < p_count2; n++) { if (!fgets(buf, LINE_BUF, in)) { fclose(in); Purge(); globalOutputStream() << " ERROR - Could not find information for portal number " << n + 1 << " of " << p_count << ".\n"; return; } unsigned int pCount, node1; sscanf(buf, "%u %u", &pCount, &node1); if (!node[node1].AddPortal(buf, pCount, false)) { fclose(in); Purge(); globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n"; return; } } fclose(in); } CBspNode::CBspNode() { portal = NULL; portal_count = 0; portal_next = 0; } CBspNode::~CBspNode() { if (portal != NULL) { delete[] portal; } } bool CBspNode::AddPortal(char *def, unsigned int pointCnt, bool bInverse) { return portal[portal_next++].Build(def, pointCnt, bInverse); }