/* 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 "misc.h" #define LINE_BUF 1000 #define 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"); fgets(buf, LINE_BUF, in); fgets(buf, LINE_BUF, in); fgets(buf, LINE_BUF, in); 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); }