goat3d

changeset 73:9862541fdcf5

- build qt goatview on linux - fixed line endings in a bunch of files
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 06 May 2014 03:57:11 +0300
parents 36e39632db75
children ab66cdabf6f2
files exporters/maxgoat/resource.h exporters/maxgoat/src/config.h exporters/maxgoat/src/logger.cc exporters/maxgoat/src/logger.h exporters/maxgoat/src/maxgoat.cc exporters/maxgoat_stub/src/stub.cc goatview/Makefile goatview/src/goatview.cc goatview/src/goatview.h goatview/src/main.cc libs/tinyxml2/tinyxml2.h
diffstat 11 files changed, 3382 insertions(+), 3373 deletions(-) [+]
line diff
     1.1 Binary file exporters/maxgoat/resource.h has changed
     2.1 --- a/exporters/maxgoat/src/config.h	Tue May 06 03:31:35 2014 +0300
     2.2 +++ b/exporters/maxgoat/src/config.h	Tue May 06 03:57:11 2014 +0300
     2.3 @@ -1,7 +1,7 @@
     2.4 -#ifndef CONFIG_H_
     2.5 -#define CONFIG_H_
     2.6 -
     2.7 -#define VER_MAJOR	0
     2.8 -#define VER_MINOR	1
     2.9 -
    2.10 -#endif	/* CONFIG_H_ */
    2.11 \ No newline at end of file
    2.12 +#ifndef CONFIG_H_
    2.13 +#define CONFIG_H_
    2.14 +
    2.15 +#define VER_MAJOR	0
    2.16 +#define VER_MINOR	1
    2.17 +
    2.18 +#endif	/* CONFIG_H_ */
     3.1 --- a/exporters/maxgoat/src/logger.cc	Tue May 06 03:31:35 2014 +0300
     3.2 +++ b/exporters/maxgoat/src/logger.cc	Tue May 06 03:57:11 2014 +0300
     3.3 @@ -1,31 +1,31 @@
     3.4 -#include <stdio.h>
     3.5 -#include <stdarg.h>
     3.6 -#include "logger.h"
     3.7 -
     3.8 -static FILE *logfile;
     3.9 -
    3.10 -bool maxlog_open(const char *fname)
    3.11 -{
    3.12 -	if(!(logfile = fopen(fname, "wb"))) {
    3.13 -		return false;
    3.14 -	}
    3.15 -	setvbuf(logfile, 0, _IONBF, 0);
    3.16 -	return true;
    3.17 -}
    3.18 -
    3.19 -void maxlog_close()
    3.20 -{
    3.21 -	if(logfile) {
    3.22 -		fclose(logfile);
    3.23 -	}
    3.24 -}
    3.25 -
    3.26 -void maxlog(const char *fmt, ...)
    3.27 -{
    3.28 -	if(!logfile) return;
    3.29 -
    3.30 -	va_list ap;
    3.31 -	va_start(ap, fmt);
    3.32 -	vfprintf(logfile, fmt, ap);
    3.33 -	va_end(ap);
    3.34 -}
    3.35 \ No newline at end of file
    3.36 +#include <stdio.h>
    3.37 +#include <stdarg.h>
    3.38 +#include "logger.h"
    3.39 +
    3.40 +static FILE *logfile;
    3.41 +
    3.42 +bool maxlog_open(const char *fname)
    3.43 +{
    3.44 +	if(!(logfile = fopen(fname, "wb"))) {
    3.45 +		return false;
    3.46 +	}
    3.47 +	setvbuf(logfile, 0, _IONBF, 0);
    3.48 +	return true;
    3.49 +}
    3.50 +
    3.51 +void maxlog_close()
    3.52 +{
    3.53 +	if(logfile) {
    3.54 +		fclose(logfile);
    3.55 +	}
    3.56 +}
    3.57 +
    3.58 +void maxlog(const char *fmt, ...)
    3.59 +{
    3.60 +	if(!logfile) return;
    3.61 +
    3.62 +	va_list ap;
    3.63 +	va_start(ap, fmt);
    3.64 +	vfprintf(logfile, fmt, ap);
    3.65 +	va_end(ap);
    3.66 +}
     4.1 --- a/exporters/maxgoat/src/logger.h	Tue May 06 03:31:35 2014 +0300
     4.2 +++ b/exporters/maxgoat/src/logger.h	Tue May 06 03:57:11 2014 +0300
     4.3 @@ -1,8 +1,8 @@
     4.4 -#ifndef MAXLOGGER_H_
     4.5 -#define MAXLOGGER_H_
     4.6 -
     4.7 -bool maxlog_open(const char *fname);
     4.8 -void maxlog_close();
     4.9 -void maxlog(const char *fmt, ...);
    4.10 -
    4.11 -#endif	/* MAXLOGGER_H_ */
    4.12 \ No newline at end of file
    4.13 +#ifndef MAXLOGGER_H_
    4.14 +#define MAXLOGGER_H_
    4.15 +
    4.16 +bool maxlog_open(const char *fname);
    4.17 +void maxlog_close();
    4.18 +void maxlog(const char *fmt, ...);
    4.19 +
    4.20 +#endif	/* MAXLOGGER_H_ */
     5.1 --- a/exporters/maxgoat/src/maxgoat.cc	Tue May 06 03:31:35 2014 +0300
     5.2 +++ b/exporters/maxgoat/src/maxgoat.cc	Tue May 06 03:57:11 2014 +0300
     5.3 @@ -1,892 +1,892 @@
     5.4 -#include <stdio.h>
     5.5 -#include <string.h>
     5.6 -#include <stdlib.h>
     5.7 -#include <ctype.h>
     5.8 -#include <errno.h>
     5.9 -#include <map>
    5.10 -#include <vector>
    5.11 -#include <windows.h>
    5.12 -#include <shlobj.h>
    5.13 -#include "max.h"
    5.14 -#include "impexp.h"		// SceneExport
    5.15 -#include "iparamb2.h"	// ClassDesc2
    5.16 -#include "plugapi.h"
    5.17 -#include "IGame.h"
    5.18 -#include "IGameExport.h"
    5.19 -#include "IGameControl.h"
    5.20 -#include "IConversionmanager.h"
    5.21 -#include "goat3d.h"
    5.22 -#include "config.h"
    5.23 -#include "logger.h"
    5.24 -#include "resource.h"
    5.25 -
    5.26 -
    5.27 -#pragma comment (lib, "core.lib")
    5.28 -#pragma comment (lib, "geom.lib")
    5.29 -#pragma comment (lib, "gfx.lib")
    5.30 -#pragma comment (lib, "mesh.lib")
    5.31 -#pragma comment (lib, "maxutil.lib")
    5.32 -#pragma comment (lib, "maxscrpt.lib")
    5.33 -#pragma comment (lib, "paramblk2.lib")
    5.34 -#pragma comment (lib, "msxml2.lib")
    5.35 -#pragma comment (lib, "igame.lib")
    5.36 -#pragma comment (lib, "comctl32.lib")
    5.37 -
    5.38 -
    5.39 -#define COPYRIGHT	\
    5.40 -	L"Copyright 2014 (C) John Tsiombikas - GNU General Public License v3, see COPYING for details."
    5.41 -#define VERSION(major, minor) \
    5.42 -	((major) * 100 + ((minor) < 10 ? (minor) * 10 : (minor)))
    5.43 -
    5.44 -static INT_PTR CALLBACK scene_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
    5.45 -static INT_PTR CALLBACK anim_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
    5.46 -static void get_position_keys(IGameControl *ctrl, goat3d_node *node);
    5.47 -static void get_xyz_position_keys(IGameControl *ctrl, goat3d_node *node);
    5.48 -static void get_rotation_keys(IGameControl *ctrl, goat3d_node *node);
    5.49 -static void get_euler_keys(IGameControl *ctrl, goat3d_node *node);
    5.50 -static void get_scaling_keys(IGameControl *ctrl, goat3d_node *node);
    5.51 -static const char *max_string(const MCHAR *wstr);
    5.52 -
    5.53 -HINSTANCE hinst;
    5.54 -
    5.55 -class GoatExporter : public SceneExport {
    5.56 -private:
    5.57 -	std::map<IGameMaterial*, goat3d_material*> mtlmap;
    5.58 -	std::map<IGameNode*, goat3d_node*> nodemap;
    5.59 -
    5.60 -public:
    5.61 -	IGameScene *igame;
    5.62 -
    5.63 -	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
    5.64 -
    5.65 -	void process_materials(goat3d *goat);
    5.66 -
    5.67 -	void process_node(goat3d *goat, goat3d_node *parent, IGameNode *maxnode);
    5.68 -
    5.69 -	void process_mesh(goat3d *goat, goat3d_mesh *mesh, IGameObject *maxobj);
    5.70 -	void process_light(goat3d *goat, goat3d_light *light, IGameObject *maxobj);
    5.71 -	void process_camera(goat3d *goat, goat3d_camera *cam, IGameObject *maxobj);
    5.72 -
    5.73 -
    5.74 -	int ExtCount() { return 1; }
    5.75 -	const TCHAR *Ext(int n) { return L"goatsce"; }
    5.76 -	const TCHAR *LongDesc() { return L"Goat3D scene file"; }
    5.77 -	const TCHAR *ShortDesc() { return L"Goat3D"; }
    5.78 -	const TCHAR *AuthorName() { return L"John Tsiombikas"; }
    5.79 -	const TCHAR *CopyrightMessage() { return COPYRIGHT; }
    5.80 -	const TCHAR *OtherMessage1() { return L"other1"; }
    5.81 -	const TCHAR *OtherMessage2() { return L"other2"; }
    5.82 -	unsigned int Version() { return VERSION(VER_MAJOR, VER_MINOR); }
    5.83 -	void ShowAbout(HWND win) { MessageBoxA(win, "Goat3D exporter plugin", "About this plugin", 0); }
    5.84 -};
    5.85 -
    5.86 -class GoatAnimExporter : public GoatExporter {
    5.87 -private:
    5.88 -public:
    5.89 -	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
    5.90 -
    5.91 -	const TCHAR *Ext(int n) { return L"goatanm"; }
    5.92 -	const TCHAR *LongDesc() { return L"Goat3D animation file"; }
    5.93 -};
    5.94 -
    5.95 -
    5.96 -// ---- GoatExporter implementation ----
    5.97 -
    5.98 -int GoatExporter::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
    5.99 -		BOOL non_interactive, DWORD opt)
   5.100 -{
   5.101 -	if(!DialogBox(hinst, MAKEINTRESOURCE(IDD_GOAT_SCE), 0, scene_gui_handler)) {
   5.102 -		return IMPEXP_CANCEL;
   5.103 -	}
   5.104 -
   5.105 -	mtlmap.clear();
   5.106 -	nodemap.clear();
   5.107 -
   5.108 -	char fname[512];
   5.109 -	wcstombs(fname, name, sizeof fname - 1);
   5.110 -	for(int i=0; fname[i]; i++) {
   5.111 -		fname[i] = tolower(fname[i]);
   5.112 -	}
   5.113 -	char *basename = (char*)alloca(strlen(fname) + 1);
   5.114 -	strcpy(basename, fname);
   5.115 -	char *suffix = strrchr(basename, '.');
   5.116 -	if(suffix) *suffix = 0;
   5.117 -
   5.118 -	maxlog("Exporting Goat3D Scene (text) file: %s\n", fname);
   5.119 -	if(!(igame = GetIGameInterface())) {
   5.120 -		maxlog("failed to get the igame interface\n");
   5.121 -		return IMPEXP_FAIL;
   5.122 -	}
   5.123 -	IGameConversionManager *cm = GetConversionManager();
   5.124 -	cm->SetCoordSystem(IGameConversionManager::IGAME_OGL);
   5.125 -	igame->InitialiseIGame();
   5.126 -
   5.127 -	goat3d *goat = goat3d_create();
   5.128 -	goat3d_set_name(goat, basename);
   5.129 -
   5.130 -	process_materials(goat);
   5.131 -
   5.132 -	// process all nodes
   5.133 -	for(int i=0; i<igame->GetTopLevelNodeCount(); i++) {
   5.134 -		IGameNode *node = igame->GetTopLevelNode(i);
   5.135 -		process_node(goat, 0, node);
   5.136 -	}
   5.137 -
   5.138 -	if(goat3d_save(goat, fname) == -1) {
   5.139 -		goat3d_free(goat);
   5.140 -		return IMPEXP_FAIL;
   5.141 -	}
   5.142 -
   5.143 -	goat3d_free(goat);
   5.144 -	return IMPEXP_SUCCESS;
   5.145 -}
   5.146 -
   5.147 -void GoatExporter::process_materials(goat3d *goat)
   5.148 -{
   5.149 -	IGameProperty *prop;
   5.150 -
   5.151 -	int num_mtl = igame->GetRootMaterialCount();
   5.152 -	for(int i=0; i<num_mtl; i++) {
   5.153 -		IGameMaterial *maxmtl = igame->GetRootMaterial(i);
   5.154 -		if(maxmtl) {
   5.155 -			goat3d_material *mtl = goat3d_create_mtl();
   5.156 -
   5.157 -			const char *name = max_string(maxmtl->GetMaterialName());
   5.158 -			if(name) {
   5.159 -				goat3d_set_mtl_name(mtl, name);
   5.160 -			}
   5.161 -
   5.162 -			// diffuse
   5.163 -			if((prop = maxmtl->GetDiffuseData())) {
   5.164 -				Point3 diffuse(1, 1, 1);
   5.165 -				prop->GetPropertyValue(diffuse);
   5.166 -				goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_DIFFUSE, diffuse[0],
   5.167 -					diffuse[1], diffuse[2]);
   5.168 -			}
   5.169 -			// specular
   5.170 -			if((prop = maxmtl->GetSpecularData())) {
   5.171 -				Point3 specular(0, 0, 0);
   5.172 -				prop->GetPropertyValue(specular);
   5.173 -
   5.174 -				float sstr = 1.0;
   5.175 -				if((prop = maxmtl->GetSpecularLevelData())) {
   5.176 -					prop->GetPropertyValue(sstr);
   5.177 -				}
   5.178 -				goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_SPECULAR, specular[0] * sstr,
   5.179 -					specular[1] * sstr, specular[2] * sstr);
   5.180 -			}
   5.181 -			// shininess
   5.182 -			if((prop = maxmtl->GetGlossinessData())) {
   5.183 -				float shin;
   5.184 -				prop->GetPropertyValue(shin);
   5.185 -				goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_SHININESS, shin * 100.0);
   5.186 -			}
   5.187 -
   5.188 -			// textures
   5.189 -			for(int j=0; j<maxmtl->GetNumberOfTextureMaps(); j++) {
   5.190 -				IGameTextureMap *tex = maxmtl->GetIGameTextureMap(j);
   5.191 -
   5.192 -				const char *fname = max_string(tex->GetBitmapFileName());
   5.193 -				if(!fname) {
   5.194 -					continue;
   5.195 -				}
   5.196 -
   5.197 -				int slot = tex->GetStdMapSlot();
   5.198 -				switch(slot) {
   5.199 -				case ID_DI:	// diffuse
   5.200 -					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_DIFFUSE, fname);
   5.201 -					break;
   5.202 -
   5.203 -				case ID_SP:
   5.204 -				case ID_SS:
   5.205 -					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SPECULAR, fname);
   5.206 -					break;
   5.207 -
   5.208 -				case ID_SH:
   5.209 -					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SHININESS, fname);
   5.210 -					break;
   5.211 -
   5.212 -				case ID_BU:
   5.213 -					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_NORMAL, fname);
   5.214 -					break;
   5.215 -
   5.216 -				case ID_RL:
   5.217 -					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_REFLECTION, fname);
   5.218 -					break;
   5.219 -
   5.220 -				case ID_RR:
   5.221 -					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_TRANSMISSION, fname);
   5.222 -					break;
   5.223 -
   5.224 -				default:
   5.225 -					break;
   5.226 -				}
   5.227 -			}
   5.228 -
   5.229 -			goat3d_add_mtl(goat, mtl);
   5.230 -			mtlmap[maxmtl] = mtl;
   5.231 -		}
   5.232 -	}
   5.233 -}
   5.234 -
   5.235 -void GoatExporter::process_node(goat3d *goat, goat3d_node *parent, IGameNode *maxnode)
   5.236 -{
   5.237 -	goat3d_node *node = goat3d_create_node();
   5.238 -	goat3d_add_node(goat, node);
   5.239 -
   5.240 -	if(parent) {
   5.241 -		goat3d_add_node_child(parent, node);
   5.242 -	}
   5.243 -
   5.244 -	const char *name = max_string(maxnode->GetName());
   5.245 -	if(name) {
   5.246 -		goat3d_set_node_name(node, name);
   5.247 -	}
   5.248 -
   5.249 -	IGameObject *maxobj = maxnode->GetIGameObject();
   5.250 -	IGameObject::ObjectTypes type = maxobj->GetIGameType();
   5.251 -
   5.252 -	switch(type) {
   5.253 -	case IGameObject::IGAME_MESH:
   5.254 -		{
   5.255 -			goat3d_mesh *mesh = goat3d_create_mesh();
   5.256 -			if(name) goat3d_set_mesh_name(mesh, name);
   5.257 -			goat3d_set_node_object(node, GOAT3D_NODE_MESH, mesh);
   5.258 -
   5.259 -			// get the node material and assign it to the mesh
   5.260 -			IGameMaterial *maxmtl = maxnode->GetNodeMaterial();
   5.261 -			goat3d_material *mtl = mtlmap[maxmtl];
   5.262 -			if(mtl) {
   5.263 -				goat3d_set_mesh_mtl(mesh, mtl);
   5.264 -			}
   5.265 -
   5.266 -			process_mesh(goat, mesh, maxobj);
   5.267 -			goat3d_add_mesh(goat, mesh);
   5.268 -		}
   5.269 -		break;
   5.270 -
   5.271 -	case IGameObject::IGAME_LIGHT:
   5.272 -		{
   5.273 -			goat3d_light *light = goat3d_create_light();
   5.274 -			//if(name) goat3d_set_light_name(light, name);
   5.275 -			goat3d_set_node_object(node, GOAT3D_NODE_LIGHT, light);
   5.276 -
   5.277 -			process_light(goat, light, maxobj);
   5.278 -			goat3d_add_light(goat, light);
   5.279 -		}
   5.280 -		break;
   5.281 -
   5.282 -	case IGameObject::IGAME_CAMERA:
   5.283 -		{
   5.284 -			goat3d_camera *cam = goat3d_create_camera();
   5.285 -			//if(name) goat3d_set_camera_name(camera, name);
   5.286 -			goat3d_set_node_object(node, GOAT3D_NODE_CAMERA, cam);
   5.287 -
   5.288 -			process_camera(goat, cam, maxobj);
   5.289 -			goat3d_add_camera(goat, cam);
   5.290 -		}
   5.291 -		break;
   5.292 -
   5.293 -	default:
   5.294 -		// otherwise don't assign an object, essentially treating it as a null node
   5.295 -		break;
   5.296 -	}
   5.297 -
   5.298 -	// grab the animation data
   5.299 -	if(!dynamic_cast<GoatAnimExporter*>(this)) {
   5.300 -		// no animation, just get the static PRS
   5.301 -		GMatrix maxmatrix = maxnode->GetObjectTM();
   5.302 -		Point3 trans = maxmatrix.Translation();
   5.303 -		Quat rot = maxmatrix.Rotation();
   5.304 -		Point3 scale = maxmatrix.Scaling();
   5.305 -
   5.306 -		goat3d_set_node_position(node, trans.x, trans.y, trans.z, 0);
   5.307 -		goat3d_set_node_rotation(node, rot.x, rot.y, rot.z, rot.w, 0);
   5.308 -		goat3d_set_node_scaling(node, scale.x, scale.y, scale.z, 0);
   5.309 -
   5.310 -	} else {
   5.311 -		// exporting animations (if available)
   5.312 -		// TODO sample keys if requested
   5.313 -		IGameControl *ctrl = maxnode->GetIGameControl();
   5.314 -		if(ctrl) {
   5.315 -			if(ctrl->IsAnimated(IGAME_POS) || ctrl->IsAnimated(IGAME_POS_X) ||
   5.316 -					ctrl->IsAnimated(IGAME_POS_Y) || ctrl->IsAnimated(IGAME_POS_Z)) {
   5.317 -				get_position_keys(ctrl, node);
   5.318 -			}
   5.319 -			if(ctrl->IsAnimated(IGAME_ROT) || ctrl->IsAnimated(IGAME_EULER_X) ||
   5.320 -					ctrl->IsAnimated(IGAME_EULER_Y) || ctrl->IsAnimated(IGAME_EULER_Z)) {
   5.321 -				get_rotation_keys(ctrl, node);
   5.322 -			}
   5.323 -			if(ctrl->IsAnimated(IGAME_SCALE)) {
   5.324 -				get_scaling_keys(ctrl, node);
   5.325 -			}
   5.326 -		} else {
   5.327 -			maxlog("%s: failed to get IGameControl for node: %s\n", __FUNCTION__, name);
   5.328 -		}
   5.329 -	}
   5.330 -
   5.331 -	for(int i=0; i<maxnode->GetChildCount(); i++) {
   5.332 -		process_node(goat, node, maxnode->GetNodeChild(i));
   5.333 -	}
   5.334 -}
   5.335 -
   5.336 -#define KEY_TIME(key)	((long)(TicksToSec(key.t) * 1000.0))
   5.337 -
   5.338 -static void get_position_keys(IGameControl *ctrl, goat3d_node *node)
   5.339 -{
   5.340 -	const char *nodename = goat3d_get_node_name(node);
   5.341 -	IGameKeyTab keys;
   5.342 -
   5.343 -	if(ctrl->GetLinearKeys(keys, IGAME_POS)) {
   5.344 -		maxlog("node %s: getting %d linear position keys\n", nodename, keys.Count());
   5.345 -		for(int i=0; i<keys.Count(); i++) {
   5.346 -			Point3 p = keys[i].linearKey.pval;
   5.347 -			goat3d_set_node_position(node, p.x, p.y, p.z, KEY_TIME(keys[i]));
   5.348 -		}
   5.349 -	} else if(ctrl->GetBezierKeys(keys, IGAME_POS)) {
   5.350 -		maxlog("node %s: getting %d bezier position keys\n", nodename, keys.Count());
   5.351 -		for(int i=0; i<keys.Count(); i++) {
   5.352 -			Point3 p = keys[i].bezierKey.pval;
   5.353 -			goat3d_set_node_position(node, p.x, p.y, p.z, KEY_TIME(keys[i]));
   5.354 -		}
   5.355 -	} else if(ctrl->GetTCBKeys(keys, IGAME_POS)) {
   5.356 -		maxlog("node %s: getting %d tcb position keys\n", nodename, keys.Count());
   5.357 -		for(int i=0; i<keys.Count(); i++) {
   5.358 -			Point3 p = keys[i].tcbKey.pval;
   5.359 -			goat3d_set_node_position(node, p.x, p.y, p.z, KEY_TIME(keys[i]));
   5.360 -		}
   5.361 -	} else {
   5.362 -		get_xyz_position_keys(ctrl, node);
   5.363 -	}
   5.364 -}
   5.365 -
   5.366 -static void get_xyz_position_keys(IGameControl *ctrl, goat3d_node *node)
   5.367 -{
   5.368 -	const char *nodename = goat3d_get_node_name(node);
   5.369 -	IGameKeyTab keys;
   5.370 -	IGameControlType postype[] = {IGAME_POS_X, IGAME_POS_Y, IGAME_POS_Z};
   5.371 -	std::map<long, Point3> pos;
   5.372 -
   5.373 -	for(int i=0; i<3; i++) {
   5.374 -		if(ctrl->GetLinearKeys(keys, postype[i])) {
   5.375 -			maxlog("node %s: getting %d linear position %c keys\n", nodename, keys.Count(), "xyz"[i]);
   5.376 -			for(int j=0; j<keys.Count(); j++) {
   5.377 -				long tm = KEY_TIME(keys[j]);
   5.378 -				Point3 v = pos[tm];
   5.379 -				v[i] = keys[j].linearKey.fval;
   5.380 -				pos[tm] = v;
   5.381 -			}
   5.382 -		} else if(ctrl->GetBezierKeys(keys, postype[i])) {
   5.383 -			maxlog("node %s: getting %d bezier position %c keys\n", nodename, keys.Count(), "xyz"[i]);
   5.384 -			for(int j=0; j<keys.Count(); j++) {
   5.385 -				long tm = KEY_TIME(keys[j]);
   5.386 -				Point3 v = pos[tm];
   5.387 -				v[i] = keys[j].bezierKey.fval;
   5.388 -				pos[tm] = v;
   5.389 -			}
   5.390 -		} else if(ctrl->GetTCBKeys(keys, postype[i])) {
   5.391 -			maxlog("node %s: getting %d tcb position %c keys\n", nodename, keys.Count(), "xyz"[i]);
   5.392 -			for(int j=0; j<keys.Count(); j++) {
   5.393 -				long tm = KEY_TIME(keys[j]);
   5.394 -				Point3 v = pos[tm];
   5.395 -				v[i] = keys[j].tcbKey.fval;
   5.396 -				pos[tm] = v;
   5.397 -			}
   5.398 -		}
   5.399 -	}
   5.400 -
   5.401 -	std::map<long, Point3>::iterator it = pos.begin();
   5.402 -	while(it != pos.end()) {
   5.403 -		Point3 p = it->second;
   5.404 -		goat3d_set_node_position(node, p.x, p.y, p.z, it->first);
   5.405 -		++it;
   5.406 -	}
   5.407 -}
   5.408 -
   5.409 -static void get_rotation_keys(IGameControl *ctrl, goat3d_node *node)
   5.410 -{
   5.411 -	const char *nodename = goat3d_get_node_name(node);
   5.412 -	IGameKeyTab rkeys;
   5.413 -
   5.414 -	if(ctrl->GetLinearKeys(rkeys, IGAME_ROT)) {
   5.415 -		maxlog("node %s: getting %d linear rotation keys\n", nodename, rkeys.Count());
   5.416 -		for(int i=0; i<rkeys.Count(); i++) {
   5.417 -			Quat q = rkeys[i].linearKey.qval;
   5.418 -			goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, KEY_TIME(rkeys[i]));
   5.419 -		}
   5.420 -	} else if(ctrl->GetBezierKeys(rkeys, IGAME_ROT)) {
   5.421 -		maxlog("node %s: getting %d bezier rotation keys\n", nodename, rkeys.Count());
   5.422 -		for(int i=0; i<rkeys.Count(); i++) {
   5.423 -			Quat q = rkeys[i].bezierKey.qval;
   5.424 -			goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, KEY_TIME(rkeys[i]));
   5.425 -		}
   5.426 -	} else if(ctrl->GetTCBKeys(rkeys, IGAME_ROT)) {
   5.427 -		maxlog("node %s: getting %d TCB rotation keys\n", nodename, rkeys.Count());
   5.428 -		for(int i=0; i<rkeys.Count(); i++) {
   5.429 -			Quat q(rkeys[i].tcbKey.aval);
   5.430 -			goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, KEY_TIME(rkeys[i]));
   5.431 -		}
   5.432 -	} else {
   5.433 -		get_euler_keys(ctrl, node);
   5.434 -	}
   5.435 -}
   5.436 -
   5.437 -static void get_euler_keys(IGameControl *ctrl, goat3d_node *node)
   5.438 -{
   5.439 -	const char *nodename = goat3d_get_node_name(node);
   5.440 -	IGameKeyTab keys;
   5.441 -	IGameControlType eulertype[] = {IGAME_EULER_X, IGAME_EULER_Y, IGAME_EULER_Z};
   5.442 -	std::map<long, Point3> euler;
   5.443 -
   5.444 -	for(int i=0; i<3; i++) {
   5.445 -		if(ctrl->GetLinearKeys(keys, eulertype[i])) {
   5.446 -			maxlog("node %s: getting %d linear euler %c keys\n", nodename, keys.Count(), "xyz"[i]);
   5.447 -			for(int j=0; j<keys.Count(); j++) {
   5.448 -				long tm = KEY_TIME(keys[j]);
   5.449 -				Point3 v = euler[tm];
   5.450 -				v[i] = keys[j].linearKey.fval;
   5.451 -				euler[tm] = v;
   5.452 -			}
   5.453 -		} else if(ctrl->GetBezierKeys(keys, eulertype[i])) {
   5.454 -			maxlog("node %s: getting %d bezier euler %c keys\n", nodename, keys.Count(), "xyz"[i]);
   5.455 -			for(int j=0; j<keys.Count(); j++) {
   5.456 -				long tm = KEY_TIME(keys[j]);
   5.457 -				Point3 v = euler[tm];
   5.458 -				v[i] = keys[j].bezierKey.fval;
   5.459 -				euler[tm] = v;
   5.460 -			}
   5.461 -		} else if(ctrl->GetTCBKeys(keys, eulertype[i])) {
   5.462 -			maxlog("node %s: getting %d tcb euler %c keys\n", nodename, keys.Count(), "xyz"[i]);
   5.463 -			for(int j=0; j<keys.Count(); j++) {
   5.464 -				long tm = KEY_TIME(keys[j]);
   5.465 -				Point3 v = euler[tm];
   5.466 -				v[i] = keys[j].tcbKey.fval;
   5.467 -				euler[tm] = v;
   5.468 -			}
   5.469 -		}
   5.470 -	}
   5.471 -
   5.472 -	int order = ctrl->GetEulerOrder();
   5.473 -	std::map<long, Point3>::iterator it = euler.begin();
   5.474 -	while(it != euler.end()) {
   5.475 -		Quat q;
   5.476 -		EulerToQuat(it->second, q, order);
   5.477 -		goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, it->first);
   5.478 -		++it;
   5.479 -	}
   5.480 -}
   5.481 -
   5.482 -static void get_scaling_keys(IGameControl *ctrl, goat3d_node *node)
   5.483 -{
   5.484 -	const char *nodename = goat3d_get_node_name(node);
   5.485 -	IGameKeyTab keys;
   5.486 -
   5.487 -	// XXX the way I'm using the ScaleValue is wrong, but fuck it...
   5.488 -
   5.489 -	if(ctrl->GetLinearKeys(keys, IGAME_SCALE)) {
   5.490 -		maxlog("node %s: getting %d linear scaling keys\n", nodename, keys.Count());
   5.491 -		for(int i=0; i<keys.Count(); i++) {
   5.492 -			ScaleValue s = keys[i].linearKey.sval;
   5.493 -			goat3d_set_node_scaling(node, s.s.x, s.s.y, s.s.z, KEY_TIME(keys[i]));
   5.494 -		}
   5.495 -	} else if(ctrl->GetBezierKeys(keys, IGAME_SCALE)) {
   5.496 -		maxlog("node %s: getting %d bezier scaling keys\n", nodename, keys.Count());
   5.497 -		for(int i=0; i<keys.Count(); i++) {
   5.498 -			ScaleValue s = keys[i].bezierKey.sval;
   5.499 -			goat3d_set_node_scaling(node, s.s.x, s.s.y, s.s.z, KEY_TIME(keys[i]));
   5.500 -		}
   5.501 -	} else if(ctrl->GetTCBKeys(keys, IGAME_SCALE)) {
   5.502 -		maxlog("node %s: getting %d tcb scaling keys\n", nodename, keys.Count());
   5.503 -		for(int i=0; i<keys.Count(); i++) {
   5.504 -			ScaleValue s = keys[i].tcbKey.sval;
   5.505 -			goat3d_set_node_scaling(node, s.s.x, s.s.y, s.s.z, KEY_TIME(keys[i]));
   5.506 -		}
   5.507 -	}
   5.508 -}
   5.509 -
   5.510 -static bool get_anim_bounds(IGameNode *node, long *tstart, long *tend);
   5.511 -static bool get_node_anim_bounds(IGameNode *node, long *tstart, long *tend);
   5.512 -
   5.513 -static bool get_anim_bounds(IGameScene *igame, long *tstart, long *tend)
   5.514 -{
   5.515 -	long tmin = LONG_MAX;
   5.516 -	long tmax = LONG_MIN;
   5.517 -
   5.518 -	int num_nodes = igame->GetTopLevelNodeCount();
   5.519 -	for(int i=0; i<num_nodes; i++) {
   5.520 -		long t0, t1;
   5.521 -		if(get_anim_bounds(igame->GetTopLevelNode(i), &t0, &t1)) {
   5.522 -			if(t0 < tmin) tmin = t0;
   5.523 -			if(t1 > tmax) tmax = t1;
   5.524 -		}
   5.525 -	}
   5.526 -
   5.527 -	if(tmin != LONG_MAX) {
   5.528 -		*tstart = tmin;
   5.529 -		*tend = tmax;
   5.530 -		return true;
   5.531 -	}
   5.532 -	return false;
   5.533 -}
   5.534 -
   5.535 -static bool get_anim_bounds(IGameNode *node, long *tstart, long *tend)
   5.536 -{
   5.537 -	long tmin = LONG_MAX;
   5.538 -	long tmax = LONG_MIN;
   5.539 -
   5.540 -	get_node_anim_bounds(node, &tmin, &tmax);
   5.541 -
   5.542 -	int num_children = node->GetChildCount();
   5.543 -	for(int i=0; i<num_children; i++) {
   5.544 -		long t0, t1;
   5.545 -		if(get_anim_bounds(node->GetNodeChild(i), &t0, &t1)) {
   5.546 -			if(t0 < tmin) tmin = t0;
   5.547 -			if(t1 > tmax) tmax = t1;
   5.548 -		}
   5.549 -	}
   5.550 -
   5.551 -	if(tmin != LONG_MAX) {
   5.552 -		*tstart = tmin;
   5.553 -		*tend = tmax;
   5.554 -		return true;
   5.555 -	}
   5.556 -	return false;
   5.557 -}
   5.558 -
   5.559 -static bool get_node_anim_bounds(IGameNode *node, long *tstart, long *tend)
   5.560 -{
   5.561 -	static const IGameControlType ctypes[] = {
   5.562 -		IGAME_POS, IGAME_POS_X, IGAME_POS_Y, IGAME_POS_Z,
   5.563 -		IGAME_ROT, IGAME_EULER_X, IGAME_EULER_Y, IGAME_EULER_Z,
   5.564 -		IGAME_SCALE
   5.565 -	};
   5.566 -
   5.567 -	// NOTE: apparently if I don't call GetIGameObject, then GetIGameControl always returns null...
   5.568 -	node->GetIGameObject();
   5.569 -	IGameControl *ctrl = node->GetIGameControl();
   5.570 -	if(!ctrl) {
   5.571 -		maxlog("%s: failed to get IGameControl for node: %s\n", __FUNCTION__, max_string(node->GetName()));
   5.572 -		return false;
   5.573 -	}
   5.574 -
   5.575 -	IGameKeyTab keys;
   5.576 -	long t0, t1;
   5.577 -	long tmin = LONG_MAX;
   5.578 -	long tmax = LONG_MIN;
   5.579 -
   5.580 -	for(int i=0; i<sizeof ctypes / sizeof *ctypes; i++) {
   5.581 -		if(ctrl->GetBezierKeys(keys, ctypes[i]) && keys.Count()) {
   5.582 -			t0 = KEY_TIME(keys[0]);
   5.583 -			t1 = KEY_TIME(keys[keys.Count() - 1]);
   5.584 -			if(t0 < tmin) tmin = t0;
   5.585 -			if(t1 > tmax) tmax = t1;
   5.586 -		}
   5.587 -		if(ctrl->GetLinearKeys(keys, ctypes[i]) && keys.Count()) {
   5.588 -			t0 = KEY_TIME(keys[0]);
   5.589 -			t1 = KEY_TIME(keys[keys.Count() - 1]);
   5.590 -			if(t0 < tmin) tmin = t0;
   5.591 -			if(t1 > tmax) tmax = t1;
   5.592 -		}
   5.593 -		if(ctrl->GetTCBKeys(keys, ctypes[i]) && keys.Count()) {
   5.594 -			t0 = KEY_TIME(keys[0]);
   5.595 -			t1 = KEY_TIME(keys[keys.Count() - 1]);
   5.596 -			if(t0 < tmin) tmin = t0;
   5.597 -			if(t1 > tmax) tmax = t1;
   5.598 -		}
   5.599 -	}
   5.600 -
   5.601 -	if(tmin != LONG_MAX) {
   5.602 -		*tstart = tmin;
   5.603 -		*tend = tmax;
   5.604 -		return true;
   5.605 -	}
   5.606 -	return false;
   5.607 -}
   5.608 -
   5.609 -void GoatExporter::process_mesh(goat3d *goat, goat3d_mesh *mesh, IGameObject *maxobj)
   5.610 -{
   5.611 -	IGameMesh *maxmesh = (IGameMesh*)maxobj;
   5.612 -
   5.613 -	maxmesh->SetCreateOptimizedNormalList();	// not needed any more according to docs
   5.614 -	maxobj->InitializeData();
   5.615 -
   5.616 -	int num_verts = maxmesh->GetNumberOfVerts();
   5.617 -	int num_faces = maxmesh->GetNumberOfFaces();
   5.618 -	//assert(maxmesh->GetNumberOfTexVerts() == num_verts);
   5.619 -
   5.620 -	float *vertices = new float[num_verts * 3];
   5.621 -	float *normals = new float[num_verts * 3];
   5.622 -	//float *texcoords = new float[num_verts * 2];
   5.623 -	int *indices = new int[num_faces * 3];
   5.624 -
   5.625 -	for(int i=0; i<num_verts; i++) {
   5.626 -		Point3 v = maxmesh->GetVertex(i, true);
   5.627 -		vertices[i * 3] = v.x;
   5.628 -		vertices[i * 3 + 1] = v.y;
   5.629 -		vertices[i * 3 + 2] = v.z;
   5.630 -	}
   5.631 -
   5.632 -	for(int i=0; i<maxmesh->GetNumberOfNormals(); i++) {
   5.633 -		Point3 norm = maxmesh->GetNormal(i);
   5.634 -
   5.635 -		int vidx = maxmesh->GetNormalVertexIndex(i);
   5.636 -		normals[vidx * 3] = norm.x;
   5.637 -		normals[vidx * 3 + 1] = norm.y;
   5.638 -		normals[vidx * 3 + 2] = norm.z;
   5.639 -	}
   5.640 -
   5.641 -	/*for(int i=0; i<maxmesh->GetNumberOfTexVerts(); i++) {
   5.642 -		Point3 tex = maxmesh->GetTexVertex(i);
   5.643 -
   5.644 -		texcoords[i * 2] = tex.x;
   5.645 -		texcoords[i * 2 + 1] = tex.y;
   5.646 -	}*/
   5.647 -
   5.648 -	// get the faces
   5.649 -	for(int i=0; i<num_faces; i++) {
   5.650 -		FaceEx *face = maxmesh->GetFace(i);
   5.651 -		indices[i * 3] = face->vert[0];
   5.652 -		indices[i * 3 + 1] = face->vert[1];
   5.653 -		indices[i * 3 + 2] = face->vert[2];
   5.654 -		// TODO at some point I'll have to split based on normal/texcoord indices
   5.655 -	}
   5.656 -
   5.657 -	goat3d_set_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX, vertices, num_verts);
   5.658 -	goat3d_set_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL, normals, num_verts);
   5.659 -	//goat3d_set_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD, texcoords, num_verts);
   5.660 -	goat3d_set_mesh_faces(mesh, indices, num_faces);
   5.661 -
   5.662 -	delete [] vertices;
   5.663 -	delete [] normals;
   5.664 -	//delete [] texcoords;
   5.665 -	delete [] indices;
   5.666 -}
   5.667 -
   5.668 -void GoatExporter::process_light(goat3d *goat, goat3d_light *light, IGameObject *maxobj)
   5.669 -{
   5.670 -	// TODO
   5.671 -}
   5.672 -
   5.673 -void GoatExporter::process_camera(goat3d *goat, goat3d_camera *cam, IGameObject *maxobj)
   5.674 -{
   5.675 -	// TODO
   5.676 -}
   5.677 -
   5.678 -static INT_PTR CALLBACK scene_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
   5.679 -{
   5.680 -	switch(msg) {
   5.681 -	case WM_INITDIALOG:
   5.682 -		CheckDlgButton(win, IDC_GOAT_NODES, 1);
   5.683 -		CheckDlgButton(win, IDC_GOAT_MESHES, 1);
   5.684 -		CheckDlgButton(win, IDC_GOAT_LIGHTS, 1);
   5.685 -		CheckDlgButton(win, IDC_GOAT_CAMERAS, 1);
   5.686 -		break;
   5.687 -
   5.688 -	case WM_COMMAND:
   5.689 -		switch(LOWORD(wparam)) {
   5.690 -		case IDOK:
   5.691 -			EndDialog(win, 1);
   5.692 -			break;
   5.693 -
   5.694 -		case IDCANCEL:
   5.695 -			EndDialog(win, 0);
   5.696 -			break;
   5.697 -
   5.698 -		default:
   5.699 -			return 0;
   5.700 -		}
   5.701 -		break;
   5.702 -
   5.703 -	default:
   5.704 -		return 0;
   5.705 -	}
   5.706 -
   5.707 -	return 1;
   5.708 -}
   5.709 -
   5.710 -
   5.711 -
   5.712 -// ---- GoatAnimExporter implementation ----
   5.713 -static long tstart, tend;
   5.714 -
   5.715 -int GoatAnimExporter::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent, DWORD opt)
   5.716 -{
   5.717 -	if(!(igame = GetIGameInterface())) {
   5.718 -		maxlog("failed to get the igame interface\n");
   5.719 -		return IMPEXP_FAIL;
   5.720 -	}
   5.721 -	IGameConversionManager *cm = GetConversionManager();
   5.722 -	cm->SetCoordSystem(IGameConversionManager::IGAME_OGL);
   5.723 -	igame->InitialiseIGame();
   5.724 -	igame->SetStaticFrame(0);
   5.725 -
   5.726 -	tstart = tend = 0;
   5.727 -	get_anim_bounds(igame, &tstart, &tend);
   5.728 -
   5.729 -	if(!DialogBox(hinst, MAKEINTRESOURCE(IDD_GOAT_ANM), 0, anim_gui_handler)) {
   5.730 -		igame->ReleaseIGame();
   5.731 -		return IMPEXP_CANCEL;
   5.732 -	}
   5.733 -
   5.734 -	char fname[512];
   5.735 -	wcstombs(fname, name, sizeof fname - 1);
   5.736 -	for(int i=0; fname[i]; i++) {
   5.737 -		fname[i] = tolower(fname[i]);
   5.738 -	}
   5.739 -
   5.740 -	maxlog("Exporting Goat3D Animation (text) file: %s\n", fname);
   5.741 -
   5.742 -	goat3d *goat = goat3d_create();
   5.743 -
   5.744 -	// process all nodes
   5.745 -	for(int i=0; i<igame->GetTopLevelNodeCount(); i++) {
   5.746 -		IGameNode *node = igame->GetTopLevelNode(i);
   5.747 -		process_node(goat, 0, node);
   5.748 -	}
   5.749 -
   5.750 -	if(goat3d_save_anim(goat, fname) == -1) {
   5.751 -		goat3d_free(goat);
   5.752 -		igame->ReleaseIGame();
   5.753 -		return IMPEXP_FAIL;
   5.754 -	}
   5.755 -
   5.756 -	goat3d_free(goat);
   5.757 -	igame->ReleaseIGame();
   5.758 -	return IMPEXP_SUCCESS;
   5.759 -}
   5.760 -
   5.761 -static INT_PTR CALLBACK anim_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
   5.762 -{
   5.763 -	switch(msg) {
   5.764 -	case WM_INITDIALOG:
   5.765 -		{
   5.766 -			wchar_t buf[128];
   5.767 -			CheckDlgButton(win, IDC_GOAT_ANM_FULL, BST_CHECKED);
   5.768 -			CheckDlgButton(win, IDC_RAD_KEYS_ORIG, BST_CHECKED);
   5.769 -			wsprintf(buf, L"%ld", tstart);
   5.770 -			SetDlgItemText(win, IDC_EDIT_TSTART, buf);
   5.771 -			wsprintf(buf, L"%ld", tend);
   5.772 -			SetDlgItemText(win, IDC_EDIT_TEND, buf);
   5.773 -		}
   5.774 -		break;
   5.775 -
   5.776 -	case WM_COMMAND:
   5.777 -		switch(LOWORD(wparam)) {
   5.778 -		case IDOK:
   5.779 -			EndDialog(win, 1);
   5.780 -			break;
   5.781 -
   5.782 -		case IDCANCEL:
   5.783 -			EndDialog(win, 0);
   5.784 -			break;
   5.785 -
   5.786 -		default:
   5.787 -			return 0;
   5.788 -		}
   5.789 -		break;
   5.790 -
   5.791 -	default:
   5.792 -		return 0;
   5.793 -	}
   5.794 -
   5.795 -	return 1;
   5.796 -}
   5.797 -
   5.798 -// ------------------------------------------
   5.799 -
   5.800 -class GoatClassDesc : public ClassDesc2 {
   5.801 -public:
   5.802 -	int IsPublic() { return TRUE; }
   5.803 -	void *Create(BOOL loading = FALSE) { return new GoatExporter; }
   5.804 -	const TCHAR *ClassName() { return L"GoatExporter"; }
   5.805 -	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
   5.806 -	Class_ID ClassID() { return Class_ID(0x77050f0d, 0x7d4c5ab5); }
   5.807 -	const TCHAR *Category() { return L"Mutant Stargoat"; }
   5.808 -
   5.809 -	const TCHAR *InternalName() { return L"GoatExporter"; }
   5.810 -	HINSTANCE HInstance() { return hinst; }
   5.811 -};
   5.812 -
   5.813 -class GoatAnimClassDesc : public ClassDesc2 {
   5.814 -public:
   5.815 -	int IsPublic() { return TRUE; }
   5.816 -	void *Create(BOOL loading = FALSE) { return new GoatAnimExporter; }
   5.817 -	const TCHAR *ClassName() { return L"GoatAnimExporter"; }
   5.818 -	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
   5.819 -	Class_ID ClassID() { return Class_ID(0x51b94924, 0x2e0332f3); }
   5.820 -	const TCHAR *Category() { return L"Mutant Stargoat"; }
   5.821 -
   5.822 -	const TCHAR *InternalName() { return L"GoatAnimExporter"; }
   5.823 -	HINSTANCE HInstance() { return hinst; }
   5.824 -};
   5.825 -
   5.826 -// TODO: make 2 class descriptors, one for goat3d, one for goat3danim
   5.827 -static GoatClassDesc class_desc;
   5.828 -static GoatAnimClassDesc anim_class_desc;
   5.829 -
   5.830 -BOOL WINAPI DllMain(HINSTANCE inst_handle, ULONG reason, void *reserved)
   5.831 -{
   5.832 -	if(reason == DLL_PROCESS_ATTACH) {
   5.833 -		hinst = inst_handle;
   5.834 -		DisableThreadLibraryCalls(hinst);
   5.835 -	}
   5.836 -	return TRUE;
   5.837 -}
   5.838 -
   5.839 -extern "C" {
   5.840 -
   5.841 -__declspec(dllexport) const TCHAR *LibDescription()
   5.842 -{
   5.843 -	return L"test exporter";
   5.844 -}
   5.845 -
   5.846 -__declspec(dllexport) int LibNumberClasses()
   5.847 -{
   5.848 -	return 1;
   5.849 -}
   5.850 -
   5.851 -__declspec(dllexport) ClassDesc *LibClassDesc(int i)
   5.852 -{
   5.853 -	switch(i) {
   5.854 -	case 0:
   5.855 -		return &class_desc;
   5.856 -	case 1:
   5.857 -		return &anim_class_desc;
   5.858 -	default:
   5.859 -		break;
   5.860 -	}
   5.861 -	return 0;
   5.862 -}
   5.863 -
   5.864 -__declspec(dllexport) ULONG LibVersion()
   5.865 -{
   5.866 -	return Get3DSMAXVersion();
   5.867 -}
   5.868 -
   5.869 -__declspec(dllexport) int LibInitialize()
   5.870 -{
   5.871 -	static char path[1024];
   5.872 -
   5.873 -	SHGetFolderPathA(0, CSIDL_PERSONAL, 0, 0, path);
   5.874 -	strcat(path, "/testexp.log");
   5.875 -
   5.876 -	maxlog_open(path);
   5.877 -	return TRUE;
   5.878 -}
   5.879 -
   5.880 -__declspec(dllexport) int LibShutdown()
   5.881 -{
   5.882 -	maxlog_close();
   5.883 -	return TRUE;
   5.884 -}
   5.885 -
   5.886 -}	// extern "C"
   5.887 -
   5.888 -
   5.889 -static const char *max_string(const MCHAR *wstr)
   5.890 -{
   5.891 -	if(!wstr) return 0;
   5.892 -	static char str[512];
   5.893 -	wcstombs(str, wstr, sizeof str - 1);
   5.894 -	return str;
   5.895 -}
   5.896 \ No newline at end of file
   5.897 +#include <stdio.h>
   5.898 +#include <string.h>
   5.899 +#include <stdlib.h>
   5.900 +#include <ctype.h>
   5.901 +#include <errno.h>
   5.902 +#include <map>
   5.903 +#include <vector>
   5.904 +#include <windows.h>
   5.905 +#include <shlobj.h>
   5.906 +#include "max.h"
   5.907 +#include "impexp.h"		// SceneExport
   5.908 +#include "iparamb2.h"	// ClassDesc2
   5.909 +#include "plugapi.h"
   5.910 +#include "IGame.h"
   5.911 +#include "IGameExport.h"
   5.912 +#include "IGameControl.h"
   5.913 +#include "IConversionmanager.h"
   5.914 +#include "goat3d.h"
   5.915 +#include "config.h"
   5.916 +#include "logger.h"
   5.917 +#include "resource.h"
   5.918 +
   5.919 +
   5.920 +#pragma comment (lib, "core.lib")
   5.921 +#pragma comment (lib, "geom.lib")
   5.922 +#pragma comment (lib, "gfx.lib")
   5.923 +#pragma comment (lib, "mesh.lib")
   5.924 +#pragma comment (lib, "maxutil.lib")
   5.925 +#pragma comment (lib, "maxscrpt.lib")
   5.926 +#pragma comment (lib, "paramblk2.lib")
   5.927 +#pragma comment (lib, "msxml2.lib")
   5.928 +#pragma comment (lib, "igame.lib")
   5.929 +#pragma comment (lib, "comctl32.lib")
   5.930 +
   5.931 +
   5.932 +#define COPYRIGHT	\
   5.933 +	L"Copyright 2014 (C) John Tsiombikas - GNU General Public License v3, see COPYING for details."
   5.934 +#define VERSION(major, minor) \
   5.935 +	((major) * 100 + ((minor) < 10 ? (minor) * 10 : (minor)))
   5.936 +
   5.937 +static INT_PTR CALLBACK scene_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
   5.938 +static INT_PTR CALLBACK anim_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
   5.939 +static void get_position_keys(IGameControl *ctrl, goat3d_node *node);
   5.940 +static void get_xyz_position_keys(IGameControl *ctrl, goat3d_node *node);
   5.941 +static void get_rotation_keys(IGameControl *ctrl, goat3d_node *node);
   5.942 +static void get_euler_keys(IGameControl *ctrl, goat3d_node *node);
   5.943 +static void get_scaling_keys(IGameControl *ctrl, goat3d_node *node);
   5.944 +static const char *max_string(const MCHAR *wstr);
   5.945 +
   5.946 +HINSTANCE hinst;
   5.947 +
   5.948 +class GoatExporter : public SceneExport {
   5.949 +private:
   5.950 +	std::map<IGameMaterial*, goat3d_material*> mtlmap;
   5.951 +	std::map<IGameNode*, goat3d_node*> nodemap;
   5.952 +
   5.953 +public:
   5.954 +	IGameScene *igame;
   5.955 +
   5.956 +	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
   5.957 +
   5.958 +	void process_materials(goat3d *goat);
   5.959 +
   5.960 +	void process_node(goat3d *goat, goat3d_node *parent, IGameNode *maxnode);
   5.961 +
   5.962 +	void process_mesh(goat3d *goat, goat3d_mesh *mesh, IGameObject *maxobj);
   5.963 +	void process_light(goat3d *goat, goat3d_light *light, IGameObject *maxobj);
   5.964 +	void process_camera(goat3d *goat, goat3d_camera *cam, IGameObject *maxobj);
   5.965 +
   5.966 +
   5.967 +	int ExtCount() { return 1; }
   5.968 +	const TCHAR *Ext(int n) { return L"goatsce"; }
   5.969 +	const TCHAR *LongDesc() { return L"Goat3D scene file"; }
   5.970 +	const TCHAR *ShortDesc() { return L"Goat3D"; }
   5.971 +	const TCHAR *AuthorName() { return L"John Tsiombikas"; }
   5.972 +	const TCHAR *CopyrightMessage() { return COPYRIGHT; }
   5.973 +	const TCHAR *OtherMessage1() { return L"other1"; }
   5.974 +	const TCHAR *OtherMessage2() { return L"other2"; }
   5.975 +	unsigned int Version() { return VERSION(VER_MAJOR, VER_MINOR); }
   5.976 +	void ShowAbout(HWND win) { MessageBoxA(win, "Goat3D exporter plugin", "About this plugin", 0); }
   5.977 +};
   5.978 +
   5.979 +class GoatAnimExporter : public GoatExporter {
   5.980 +private:
   5.981 +public:
   5.982 +	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
   5.983 +
   5.984 +	const TCHAR *Ext(int n) { return L"goatanm"; }
   5.985 +	const TCHAR *LongDesc() { return L"Goat3D animation file"; }
   5.986 +};
   5.987 +
   5.988 +
   5.989 +// ---- GoatExporter implementation ----
   5.990 +
   5.991 +int GoatExporter::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
   5.992 +		BOOL non_interactive, DWORD opt)
   5.993 +{
   5.994 +	if(!DialogBox(hinst, MAKEINTRESOURCE(IDD_GOAT_SCE), 0, scene_gui_handler)) {
   5.995 +		return IMPEXP_CANCEL;
   5.996 +	}
   5.997 +
   5.998 +	mtlmap.clear();
   5.999 +	nodemap.clear();
  5.1000 +
  5.1001 +	char fname[512];
  5.1002 +	wcstombs(fname, name, sizeof fname - 1);
  5.1003 +	for(int i=0; fname[i]; i++) {
  5.1004 +		fname[i] = tolower(fname[i]);
  5.1005 +	}
  5.1006 +	char *basename = (char*)alloca(strlen(fname) + 1);
  5.1007 +	strcpy(basename, fname);
  5.1008 +	char *suffix = strrchr(basename, '.');
  5.1009 +	if(suffix) *suffix = 0;
  5.1010 +
  5.1011 +	maxlog("Exporting Goat3D Scene (text) file: %s\n", fname);
  5.1012 +	if(!(igame = GetIGameInterface())) {
  5.1013 +		maxlog("failed to get the igame interface\n");
  5.1014 +		return IMPEXP_FAIL;
  5.1015 +	}
  5.1016 +	IGameConversionManager *cm = GetConversionManager();
  5.1017 +	cm->SetCoordSystem(IGameConversionManager::IGAME_OGL);
  5.1018 +	igame->InitialiseIGame();
  5.1019 +
  5.1020 +	goat3d *goat = goat3d_create();
  5.1021 +	goat3d_set_name(goat, basename);
  5.1022 +
  5.1023 +	process_materials(goat);
  5.1024 +
  5.1025 +	// process all nodes
  5.1026 +	for(int i=0; i<igame->GetTopLevelNodeCount(); i++) {
  5.1027 +		IGameNode *node = igame->GetTopLevelNode(i);
  5.1028 +		process_node(goat, 0, node);
  5.1029 +	}
  5.1030 +
  5.1031 +	if(goat3d_save(goat, fname) == -1) {
  5.1032 +		goat3d_free(goat);
  5.1033 +		return IMPEXP_FAIL;
  5.1034 +	}
  5.1035 +
  5.1036 +	goat3d_free(goat);
  5.1037 +	return IMPEXP_SUCCESS;
  5.1038 +}
  5.1039 +
  5.1040 +void GoatExporter::process_materials(goat3d *goat)
  5.1041 +{
  5.1042 +	IGameProperty *prop;
  5.1043 +
  5.1044 +	int num_mtl = igame->GetRootMaterialCount();
  5.1045 +	for(int i=0; i<num_mtl; i++) {
  5.1046 +		IGameMaterial *maxmtl = igame->GetRootMaterial(i);
  5.1047 +		if(maxmtl) {
  5.1048 +			goat3d_material *mtl = goat3d_create_mtl();
  5.1049 +
  5.1050 +			const char *name = max_string(maxmtl->GetMaterialName());
  5.1051 +			if(name) {
  5.1052 +				goat3d_set_mtl_name(mtl, name);
  5.1053 +			}
  5.1054 +
  5.1055 +			// diffuse
  5.1056 +			if((prop = maxmtl->GetDiffuseData())) {
  5.1057 +				Point3 diffuse(1, 1, 1);
  5.1058 +				prop->GetPropertyValue(diffuse);
  5.1059 +				goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_DIFFUSE, diffuse[0],
  5.1060 +					diffuse[1], diffuse[2]);
  5.1061 +			}
  5.1062 +			// specular
  5.1063 +			if((prop = maxmtl->GetSpecularData())) {
  5.1064 +				Point3 specular(0, 0, 0);
  5.1065 +				prop->GetPropertyValue(specular);
  5.1066 +
  5.1067 +				float sstr = 1.0;
  5.1068 +				if((prop = maxmtl->GetSpecularLevelData())) {
  5.1069 +					prop->GetPropertyValue(sstr);
  5.1070 +				}
  5.1071 +				goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_SPECULAR, specular[0] * sstr,
  5.1072 +					specular[1] * sstr, specular[2] * sstr);
  5.1073 +			}
  5.1074 +			// shininess
  5.1075 +			if((prop = maxmtl->GetGlossinessData())) {
  5.1076 +				float shin;
  5.1077 +				prop->GetPropertyValue(shin);
  5.1078 +				goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_SHININESS, shin * 100.0);
  5.1079 +			}
  5.1080 +
  5.1081 +			// textures
  5.1082 +			for(int j=0; j<maxmtl->GetNumberOfTextureMaps(); j++) {
  5.1083 +				IGameTextureMap *tex = maxmtl->GetIGameTextureMap(j);
  5.1084 +
  5.1085 +				const char *fname = max_string(tex->GetBitmapFileName());
  5.1086 +				if(!fname) {
  5.1087 +					continue;
  5.1088 +				}
  5.1089 +
  5.1090 +				int slot = tex->GetStdMapSlot();
  5.1091 +				switch(slot) {
  5.1092 +				case ID_DI:	// diffuse
  5.1093 +					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_DIFFUSE, fname);
  5.1094 +					break;
  5.1095 +
  5.1096 +				case ID_SP:
  5.1097 +				case ID_SS:
  5.1098 +					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SPECULAR, fname);
  5.1099 +					break;
  5.1100 +
  5.1101 +				case ID_SH:
  5.1102 +					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SHININESS, fname);
  5.1103 +					break;
  5.1104 +
  5.1105 +				case ID_BU:
  5.1106 +					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_NORMAL, fname);
  5.1107 +					break;
  5.1108 +
  5.1109 +				case ID_RL:
  5.1110 +					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_REFLECTION, fname);
  5.1111 +					break;
  5.1112 +
  5.1113 +				case ID_RR:
  5.1114 +					goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_TRANSMISSION, fname);
  5.1115 +					break;
  5.1116 +
  5.1117 +				default:
  5.1118 +					break;
  5.1119 +				}
  5.1120 +			}
  5.1121 +
  5.1122 +			goat3d_add_mtl(goat, mtl);
  5.1123 +			mtlmap[maxmtl] = mtl;
  5.1124 +		}
  5.1125 +	}
  5.1126 +}
  5.1127 +
  5.1128 +void GoatExporter::process_node(goat3d *goat, goat3d_node *parent, IGameNode *maxnode)
  5.1129 +{
  5.1130 +	goat3d_node *node = goat3d_create_node();
  5.1131 +	goat3d_add_node(goat, node);
  5.1132 +
  5.1133 +	if(parent) {
  5.1134 +		goat3d_add_node_child(parent, node);
  5.1135 +	}
  5.1136 +
  5.1137 +	const char *name = max_string(maxnode->GetName());
  5.1138 +	if(name) {
  5.1139 +		goat3d_set_node_name(node, name);
  5.1140 +	}
  5.1141 +
  5.1142 +	IGameObject *maxobj = maxnode->GetIGameObject();
  5.1143 +	IGameObject::ObjectTypes type = maxobj->GetIGameType();
  5.1144 +
  5.1145 +	switch(type) {
  5.1146 +	case IGameObject::IGAME_MESH:
  5.1147 +		{
  5.1148 +			goat3d_mesh *mesh = goat3d_create_mesh();
  5.1149 +			if(name) goat3d_set_mesh_name(mesh, name);
  5.1150 +			goat3d_set_node_object(node, GOAT3D_NODE_MESH, mesh);
  5.1151 +
  5.1152 +			// get the node material and assign it to the mesh
  5.1153 +			IGameMaterial *maxmtl = maxnode->GetNodeMaterial();
  5.1154 +			goat3d_material *mtl = mtlmap[maxmtl];
  5.1155 +			if(mtl) {
  5.1156 +				goat3d_set_mesh_mtl(mesh, mtl);
  5.1157 +			}
  5.1158 +
  5.1159 +			process_mesh(goat, mesh, maxobj);
  5.1160 +			goat3d_add_mesh(goat, mesh);
  5.1161 +		}
  5.1162 +		break;
  5.1163 +
  5.1164 +	case IGameObject::IGAME_LIGHT:
  5.1165 +		{
  5.1166 +			goat3d_light *light = goat3d_create_light();
  5.1167 +			//if(name) goat3d_set_light_name(light, name);
  5.1168 +			goat3d_set_node_object(node, GOAT3D_NODE_LIGHT, light);
  5.1169 +
  5.1170 +			process_light(goat, light, maxobj);
  5.1171 +			goat3d_add_light(goat, light);
  5.1172 +		}
  5.1173 +		break;
  5.1174 +
  5.1175 +	case IGameObject::IGAME_CAMERA:
  5.1176 +		{
  5.1177 +			goat3d_camera *cam = goat3d_create_camera();
  5.1178 +			//if(name) goat3d_set_camera_name(camera, name);
  5.1179 +			goat3d_set_node_object(node, GOAT3D_NODE_CAMERA, cam);
  5.1180 +
  5.1181 +			process_camera(goat, cam, maxobj);
  5.1182 +			goat3d_add_camera(goat, cam);
  5.1183 +		}
  5.1184 +		break;
  5.1185 +
  5.1186 +	default:
  5.1187 +		// otherwise don't assign an object, essentially treating it as a null node
  5.1188 +		break;
  5.1189 +	}
  5.1190 +
  5.1191 +	// grab the animation data
  5.1192 +	if(!dynamic_cast<GoatAnimExporter*>(this)) {
  5.1193 +		// no animation, just get the static PRS
  5.1194 +		GMatrix maxmatrix = maxnode->GetObjectTM();
  5.1195 +		Point3 trans = maxmatrix.Translation();
  5.1196 +		Quat rot = maxmatrix.Rotation();
  5.1197 +		Point3 scale = maxmatrix.Scaling();
  5.1198 +
  5.1199 +		goat3d_set_node_position(node, trans.x, trans.y, trans.z, 0);
  5.1200 +		goat3d_set_node_rotation(node, rot.x, rot.y, rot.z, rot.w, 0);
  5.1201 +		goat3d_set_node_scaling(node, scale.x, scale.y, scale.z, 0);
  5.1202 +
  5.1203 +	} else {
  5.1204 +		// exporting animations (if available)
  5.1205 +		// TODO sample keys if requested
  5.1206 +		IGameControl *ctrl = maxnode->GetIGameControl();
  5.1207 +		if(ctrl) {
  5.1208 +			if(ctrl->IsAnimated(IGAME_POS) || ctrl->IsAnimated(IGAME_POS_X) ||
  5.1209 +					ctrl->IsAnimated(IGAME_POS_Y) || ctrl->IsAnimated(IGAME_POS_Z)) {
  5.1210 +				get_position_keys(ctrl, node);
  5.1211 +			}
  5.1212 +			if(ctrl->IsAnimated(IGAME_ROT) || ctrl->IsAnimated(IGAME_EULER_X) ||
  5.1213 +					ctrl->IsAnimated(IGAME_EULER_Y) || ctrl->IsAnimated(IGAME_EULER_Z)) {
  5.1214 +				get_rotation_keys(ctrl, node);
  5.1215 +			}
  5.1216 +			if(ctrl->IsAnimated(IGAME_SCALE)) {
  5.1217 +				get_scaling_keys(ctrl, node);
  5.1218 +			}
  5.1219 +		} else {
  5.1220 +			maxlog("%s: failed to get IGameControl for node: %s\n", __FUNCTION__, name);
  5.1221 +		}
  5.1222 +	}
  5.1223 +
  5.1224 +	for(int i=0; i<maxnode->GetChildCount(); i++) {
  5.1225 +		process_node(goat, node, maxnode->GetNodeChild(i));
  5.1226 +	}
  5.1227 +}
  5.1228 +
  5.1229 +#define KEY_TIME(key)	((long)(TicksToSec(key.t) * 1000.0))
  5.1230 +
  5.1231 +static void get_position_keys(IGameControl *ctrl, goat3d_node *node)
  5.1232 +{
  5.1233 +	const char *nodename = goat3d_get_node_name(node);
  5.1234 +	IGameKeyTab keys;
  5.1235 +
  5.1236 +	if(ctrl->GetLinearKeys(keys, IGAME_POS)) {
  5.1237 +		maxlog("node %s: getting %d linear position keys\n", nodename, keys.Count());
  5.1238 +		for(int i=0; i<keys.Count(); i++) {
  5.1239 +			Point3 p = keys[i].linearKey.pval;
  5.1240 +			goat3d_set_node_position(node, p.x, p.y, p.z, KEY_TIME(keys[i]));
  5.1241 +		}
  5.1242 +	} else if(ctrl->GetBezierKeys(keys, IGAME_POS)) {
  5.1243 +		maxlog("node %s: getting %d bezier position keys\n", nodename, keys.Count());
  5.1244 +		for(int i=0; i<keys.Count(); i++) {
  5.1245 +			Point3 p = keys[i].bezierKey.pval;
  5.1246 +			goat3d_set_node_position(node, p.x, p.y, p.z, KEY_TIME(keys[i]));
  5.1247 +		}
  5.1248 +	} else if(ctrl->GetTCBKeys(keys, IGAME_POS)) {
  5.1249 +		maxlog("node %s: getting %d tcb position keys\n", nodename, keys.Count());
  5.1250 +		for(int i=0; i<keys.Count(); i++) {
  5.1251 +			Point3 p = keys[i].tcbKey.pval;
  5.1252 +			goat3d_set_node_position(node, p.x, p.y, p.z, KEY_TIME(keys[i]));
  5.1253 +		}
  5.1254 +	} else {
  5.1255 +		get_xyz_position_keys(ctrl, node);
  5.1256 +	}
  5.1257 +}
  5.1258 +
  5.1259 +static void get_xyz_position_keys(IGameControl *ctrl, goat3d_node *node)
  5.1260 +{
  5.1261 +	const char *nodename = goat3d_get_node_name(node);
  5.1262 +	IGameKeyTab keys;
  5.1263 +	IGameControlType postype[] = {IGAME_POS_X, IGAME_POS_Y, IGAME_POS_Z};
  5.1264 +	std::map<long, Point3> pos;
  5.1265 +
  5.1266 +	for(int i=0; i<3; i++) {
  5.1267 +		if(ctrl->GetLinearKeys(keys, postype[i])) {
  5.1268 +			maxlog("node %s: getting %d linear position %c keys\n", nodename, keys.Count(), "xyz"[i]);
  5.1269 +			for(int j=0; j<keys.Count(); j++) {
  5.1270 +				long tm = KEY_TIME(keys[j]);
  5.1271 +				Point3 v = pos[tm];
  5.1272 +				v[i] = keys[j].linearKey.fval;
  5.1273 +				pos[tm] = v;
  5.1274 +			}
  5.1275 +		} else if(ctrl->GetBezierKeys(keys, postype[i])) {
  5.1276 +			maxlog("node %s: getting %d bezier position %c keys\n", nodename, keys.Count(), "xyz"[i]);
  5.1277 +			for(int j=0; j<keys.Count(); j++) {
  5.1278 +				long tm = KEY_TIME(keys[j]);
  5.1279 +				Point3 v = pos[tm];
  5.1280 +				v[i] = keys[j].bezierKey.fval;
  5.1281 +				pos[tm] = v;
  5.1282 +			}
  5.1283 +		} else if(ctrl->GetTCBKeys(keys, postype[i])) {
  5.1284 +			maxlog("node %s: getting %d tcb position %c keys\n", nodename, keys.Count(), "xyz"[i]);
  5.1285 +			for(int j=0; j<keys.Count(); j++) {
  5.1286 +				long tm = KEY_TIME(keys[j]);
  5.1287 +				Point3 v = pos[tm];
  5.1288 +				v[i] = keys[j].tcbKey.fval;
  5.1289 +				pos[tm] = v;
  5.1290 +			}
  5.1291 +		}
  5.1292 +	}
  5.1293 +
  5.1294 +	std::map<long, Point3>::iterator it = pos.begin();
  5.1295 +	while(it != pos.end()) {
  5.1296 +		Point3 p = it->second;
  5.1297 +		goat3d_set_node_position(node, p.x, p.y, p.z, it->first);
  5.1298 +		++it;
  5.1299 +	}
  5.1300 +}
  5.1301 +
  5.1302 +static void get_rotation_keys(IGameControl *ctrl, goat3d_node *node)
  5.1303 +{
  5.1304 +	const char *nodename = goat3d_get_node_name(node);
  5.1305 +	IGameKeyTab rkeys;
  5.1306 +
  5.1307 +	if(ctrl->GetLinearKeys(rkeys, IGAME_ROT)) {
  5.1308 +		maxlog("node %s: getting %d linear rotation keys\n", nodename, rkeys.Count());
  5.1309 +		for(int i=0; i<rkeys.Count(); i++) {
  5.1310 +			Quat q = rkeys[i].linearKey.qval;
  5.1311 +			goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, KEY_TIME(rkeys[i]));
  5.1312 +		}
  5.1313 +	} else if(ctrl->GetBezierKeys(rkeys, IGAME_ROT)) {
  5.1314 +		maxlog("node %s: getting %d bezier rotation keys\n", nodename, rkeys.Count());
  5.1315 +		for(int i=0; i<rkeys.Count(); i++) {
  5.1316 +			Quat q = rkeys[i].bezierKey.qval;
  5.1317 +			goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, KEY_TIME(rkeys[i]));
  5.1318 +		}
  5.1319 +	} else if(ctrl->GetTCBKeys(rkeys, IGAME_ROT)) {
  5.1320 +		maxlog("node %s: getting %d TCB rotation keys\n", nodename, rkeys.Count());
  5.1321 +		for(int i=0; i<rkeys.Count(); i++) {
  5.1322 +			Quat q(rkeys[i].tcbKey.aval);
  5.1323 +			goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, KEY_TIME(rkeys[i]));
  5.1324 +		}
  5.1325 +	} else {
  5.1326 +		get_euler_keys(ctrl, node);
  5.1327 +	}
  5.1328 +}
  5.1329 +
  5.1330 +static void get_euler_keys(IGameControl *ctrl, goat3d_node *node)
  5.1331 +{
  5.1332 +	const char *nodename = goat3d_get_node_name(node);
  5.1333 +	IGameKeyTab keys;
  5.1334 +	IGameControlType eulertype[] = {IGAME_EULER_X, IGAME_EULER_Y, IGAME_EULER_Z};
  5.1335 +	std::map<long, Point3> euler;
  5.1336 +
  5.1337 +	for(int i=0; i<3; i++) {
  5.1338 +		if(ctrl->GetLinearKeys(keys, eulertype[i])) {
  5.1339 +			maxlog("node %s: getting %d linear euler %c keys\n", nodename, keys.Count(), "xyz"[i]);
  5.1340 +			for(int j=0; j<keys.Count(); j++) {
  5.1341 +				long tm = KEY_TIME(keys[j]);
  5.1342 +				Point3 v = euler[tm];
  5.1343 +				v[i] = keys[j].linearKey.fval;
  5.1344 +				euler[tm] = v;
  5.1345 +			}
  5.1346 +		} else if(ctrl->GetBezierKeys(keys, eulertype[i])) {
  5.1347 +			maxlog("node %s: getting %d bezier euler %c keys\n", nodename, keys.Count(), "xyz"[i]);
  5.1348 +			for(int j=0; j<keys.Count(); j++) {
  5.1349 +				long tm = KEY_TIME(keys[j]);
  5.1350 +				Point3 v = euler[tm];
  5.1351 +				v[i] = keys[j].bezierKey.fval;
  5.1352 +				euler[tm] = v;
  5.1353 +			}
  5.1354 +		} else if(ctrl->GetTCBKeys(keys, eulertype[i])) {
  5.1355 +			maxlog("node %s: getting %d tcb euler %c keys\n", nodename, keys.Count(), "xyz"[i]);
  5.1356 +			for(int j=0; j<keys.Count(); j++) {
  5.1357 +				long tm = KEY_TIME(keys[j]);
  5.1358 +				Point3 v = euler[tm];
  5.1359 +				v[i] = keys[j].tcbKey.fval;
  5.1360 +				euler[tm] = v;
  5.1361 +			}
  5.1362 +		}
  5.1363 +	}
  5.1364 +
  5.1365 +	int order = ctrl->GetEulerOrder();
  5.1366 +	std::map<long, Point3>::iterator it = euler.begin();
  5.1367 +	while(it != euler.end()) {
  5.1368 +		Quat q;
  5.1369 +		EulerToQuat(it->second, q, order);
  5.1370 +		goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, it->first);
  5.1371 +		++it;
  5.1372 +	}
  5.1373 +}
  5.1374 +
  5.1375 +static void get_scaling_keys(IGameControl *ctrl, goat3d_node *node)
  5.1376 +{
  5.1377 +	const char *nodename = goat3d_get_node_name(node);
  5.1378 +	IGameKeyTab keys;
  5.1379 +
  5.1380 +	// XXX the way I'm using the ScaleValue is wrong, but fuck it...
  5.1381 +
  5.1382 +	if(ctrl->GetLinearKeys(keys, IGAME_SCALE)) {
  5.1383 +		maxlog("node %s: getting %d linear scaling keys\n", nodename, keys.Count());
  5.1384 +		for(int i=0; i<keys.Count(); i++) {
  5.1385 +			ScaleValue s = keys[i].linearKey.sval;
  5.1386 +			goat3d_set_node_scaling(node, s.s.x, s.s.y, s.s.z, KEY_TIME(keys[i]));
  5.1387 +		}
  5.1388 +	} else if(ctrl->GetBezierKeys(keys, IGAME_SCALE)) {
  5.1389 +		maxlog("node %s: getting %d bezier scaling keys\n", nodename, keys.Count());
  5.1390 +		for(int i=0; i<keys.Count(); i++) {
  5.1391 +			ScaleValue s = keys[i].bezierKey.sval;
  5.1392 +			goat3d_set_node_scaling(node, s.s.x, s.s.y, s.s.z, KEY_TIME(keys[i]));
  5.1393 +		}
  5.1394 +	} else if(ctrl->GetTCBKeys(keys, IGAME_SCALE)) {
  5.1395 +		maxlog("node %s: getting %d tcb scaling keys\n", nodename, keys.Count());
  5.1396 +		for(int i=0; i<keys.Count(); i++) {
  5.1397 +			ScaleValue s = keys[i].tcbKey.sval;
  5.1398 +			goat3d_set_node_scaling(node, s.s.x, s.s.y, s.s.z, KEY_TIME(keys[i]));
  5.1399 +		}
  5.1400 +	}
  5.1401 +}
  5.1402 +
  5.1403 +static bool get_anim_bounds(IGameNode *node, long *tstart, long *tend);
  5.1404 +static bool get_node_anim_bounds(IGameNode *node, long *tstart, long *tend);
  5.1405 +
  5.1406 +static bool get_anim_bounds(IGameScene *igame, long *tstart, long *tend)
  5.1407 +{
  5.1408 +	long tmin = LONG_MAX;
  5.1409 +	long tmax = LONG_MIN;
  5.1410 +
  5.1411 +	int num_nodes = igame->GetTopLevelNodeCount();
  5.1412 +	for(int i=0; i<num_nodes; i++) {
  5.1413 +		long t0, t1;
  5.1414 +		if(get_anim_bounds(igame->GetTopLevelNode(i), &t0, &t1)) {
  5.1415 +			if(t0 < tmin) tmin = t0;
  5.1416 +			if(t1 > tmax) tmax = t1;
  5.1417 +		}
  5.1418 +	}
  5.1419 +
  5.1420 +	if(tmin != LONG_MAX) {
  5.1421 +		*tstart = tmin;
  5.1422 +		*tend = tmax;
  5.1423 +		return true;
  5.1424 +	}
  5.1425 +	return false;
  5.1426 +}
  5.1427 +
  5.1428 +static bool get_anim_bounds(IGameNode *node, long *tstart, long *tend)
  5.1429 +{
  5.1430 +	long tmin = LONG_MAX;
  5.1431 +	long tmax = LONG_MIN;
  5.1432 +
  5.1433 +	get_node_anim_bounds(node, &tmin, &tmax);
  5.1434 +
  5.1435 +	int num_children = node->GetChildCount();
  5.1436 +	for(int i=0; i<num_children; i++) {
  5.1437 +		long t0, t1;
  5.1438 +		if(get_anim_bounds(node->GetNodeChild(i), &t0, &t1)) {
  5.1439 +			if(t0 < tmin) tmin = t0;
  5.1440 +			if(t1 > tmax) tmax = t1;
  5.1441 +		}
  5.1442 +	}
  5.1443 +
  5.1444 +	if(tmin != LONG_MAX) {
  5.1445 +		*tstart = tmin;
  5.1446 +		*tend = tmax;
  5.1447 +		return true;
  5.1448 +	}
  5.1449 +	return false;
  5.1450 +}
  5.1451 +
  5.1452 +static bool get_node_anim_bounds(IGameNode *node, long *tstart, long *tend)
  5.1453 +{
  5.1454 +	static const IGameControlType ctypes[] = {
  5.1455 +		IGAME_POS, IGAME_POS_X, IGAME_POS_Y, IGAME_POS_Z,
  5.1456 +		IGAME_ROT, IGAME_EULER_X, IGAME_EULER_Y, IGAME_EULER_Z,
  5.1457 +		IGAME_SCALE
  5.1458 +	};
  5.1459 +
  5.1460 +	// NOTE: apparently if I don't call GetIGameObject, then GetIGameControl always returns null...
  5.1461 +	node->GetIGameObject();
  5.1462 +	IGameControl *ctrl = node->GetIGameControl();
  5.1463 +	if(!ctrl) {
  5.1464 +		maxlog("%s: failed to get IGameControl for node: %s\n", __FUNCTION__, max_string(node->GetName()));
  5.1465 +		return false;
  5.1466 +	}
  5.1467 +
  5.1468 +	IGameKeyTab keys;
  5.1469 +	long t0, t1;
  5.1470 +	long tmin = LONG_MAX;
  5.1471 +	long tmax = LONG_MIN;
  5.1472 +
  5.1473 +	for(int i=0; i<sizeof ctypes / sizeof *ctypes; i++) {
  5.1474 +		if(ctrl->GetBezierKeys(keys, ctypes[i]) && keys.Count()) {
  5.1475 +			t0 = KEY_TIME(keys[0]);
  5.1476 +			t1 = KEY_TIME(keys[keys.Count() - 1]);
  5.1477 +			if(t0 < tmin) tmin = t0;
  5.1478 +			if(t1 > tmax) tmax = t1;
  5.1479 +		}
  5.1480 +		if(ctrl->GetLinearKeys(keys, ctypes[i]) && keys.Count()) {
  5.1481 +			t0 = KEY_TIME(keys[0]);
  5.1482 +			t1 = KEY_TIME(keys[keys.Count() - 1]);
  5.1483 +			if(t0 < tmin) tmin = t0;
  5.1484 +			if(t1 > tmax) tmax = t1;
  5.1485 +		}
  5.1486 +		if(ctrl->GetTCBKeys(keys, ctypes[i]) && keys.Count()) {
  5.1487 +			t0 = KEY_TIME(keys[0]);
  5.1488 +			t1 = KEY_TIME(keys[keys.Count() - 1]);
  5.1489 +			if(t0 < tmin) tmin = t0;
  5.1490 +			if(t1 > tmax) tmax = t1;
  5.1491 +		}
  5.1492 +	}
  5.1493 +
  5.1494 +	if(tmin != LONG_MAX) {
  5.1495 +		*tstart = tmin;
  5.1496 +		*tend = tmax;
  5.1497 +		return true;
  5.1498 +	}
  5.1499 +	return false;
  5.1500 +}
  5.1501 +
  5.1502 +void GoatExporter::process_mesh(goat3d *goat, goat3d_mesh *mesh, IGameObject *maxobj)
  5.1503 +{
  5.1504 +	IGameMesh *maxmesh = (IGameMesh*)maxobj;
  5.1505 +
  5.1506 +	maxmesh->SetCreateOptimizedNormalList();	// not needed any more according to docs
  5.1507 +	maxobj->InitializeData();
  5.1508 +
  5.1509 +	int num_verts = maxmesh->GetNumberOfVerts();
  5.1510 +	int num_faces = maxmesh->GetNumberOfFaces();
  5.1511 +	//assert(maxmesh->GetNumberOfTexVerts() == num_verts);
  5.1512 +
  5.1513 +	float *vertices = new float[num_verts * 3];
  5.1514 +	float *normals = new float[num_verts * 3];
  5.1515 +	//float *texcoords = new float[num_verts * 2];
  5.1516 +	int *indices = new int[num_faces * 3];
  5.1517 +
  5.1518 +	for(int i=0; i<num_verts; i++) {
  5.1519 +		Point3 v = maxmesh->GetVertex(i, true);
  5.1520 +		vertices[i * 3] = v.x;
  5.1521 +		vertices[i * 3 + 1] = v.y;
  5.1522 +		vertices[i * 3 + 2] = v.z;
  5.1523 +	}
  5.1524 +
  5.1525 +	for(int i=0; i<maxmesh->GetNumberOfNormals(); i++) {
  5.1526 +		Point3 norm = maxmesh->GetNormal(i);
  5.1527 +
  5.1528 +		int vidx = maxmesh->GetNormalVertexIndex(i);
  5.1529 +		normals[vidx * 3] = norm.x;
  5.1530 +		normals[vidx * 3 + 1] = norm.y;
  5.1531 +		normals[vidx * 3 + 2] = norm.z;
  5.1532 +	}
  5.1533 +
  5.1534 +	/*for(int i=0; i<maxmesh->GetNumberOfTexVerts(); i++) {
  5.1535 +		Point3 tex = maxmesh->GetTexVertex(i);
  5.1536 +
  5.1537 +		texcoords[i * 2] = tex.x;
  5.1538 +		texcoords[i * 2 + 1] = tex.y;
  5.1539 +	}*/
  5.1540 +
  5.1541 +	// get the faces
  5.1542 +	for(int i=0; i<num_faces; i++) {
  5.1543 +		FaceEx *face = maxmesh->GetFace(i);
  5.1544 +		indices[i * 3] = face->vert[0];
  5.1545 +		indices[i * 3 + 1] = face->vert[1];
  5.1546 +		indices[i * 3 + 2] = face->vert[2];
  5.1547 +		// TODO at some point I'll have to split based on normal/texcoord indices
  5.1548 +	}
  5.1549 +
  5.1550 +	goat3d_set_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX, vertices, num_verts);
  5.1551 +	goat3d_set_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL, normals, num_verts);
  5.1552 +	//goat3d_set_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD, texcoords, num_verts);
  5.1553 +	goat3d_set_mesh_faces(mesh, indices, num_faces);
  5.1554 +
  5.1555 +	delete [] vertices;
  5.1556 +	delete [] normals;
  5.1557 +	//delete [] texcoords;
  5.1558 +	delete [] indices;
  5.1559 +}
  5.1560 +
  5.1561 +void GoatExporter::process_light(goat3d *goat, goat3d_light *light, IGameObject *maxobj)
  5.1562 +{
  5.1563 +	// TODO
  5.1564 +}
  5.1565 +
  5.1566 +void GoatExporter::process_camera(goat3d *goat, goat3d_camera *cam, IGameObject *maxobj)
  5.1567 +{
  5.1568 +	// TODO
  5.1569 +}
  5.1570 +
  5.1571 +static INT_PTR CALLBACK scene_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
  5.1572 +{
  5.1573 +	switch(msg) {
  5.1574 +	case WM_INITDIALOG:
  5.1575 +		CheckDlgButton(win, IDC_GOAT_NODES, 1);
  5.1576 +		CheckDlgButton(win, IDC_GOAT_MESHES, 1);
  5.1577 +		CheckDlgButton(win, IDC_GOAT_LIGHTS, 1);
  5.1578 +		CheckDlgButton(win, IDC_GOAT_CAMERAS, 1);
  5.1579 +		break;
  5.1580 +
  5.1581 +	case WM_COMMAND:
  5.1582 +		switch(LOWORD(wparam)) {
  5.1583 +		case IDOK:
  5.1584 +			EndDialog(win, 1);
  5.1585 +			break;
  5.1586 +
  5.1587 +		case IDCANCEL:
  5.1588 +			EndDialog(win, 0);
  5.1589 +			break;
  5.1590 +
  5.1591 +		default:
  5.1592 +			return 0;
  5.1593 +		}
  5.1594 +		break;
  5.1595 +
  5.1596 +	default:
  5.1597 +		return 0;
  5.1598 +	}
  5.1599 +
  5.1600 +	return 1;
  5.1601 +}
  5.1602 +
  5.1603 +
  5.1604 +
  5.1605 +// ---- GoatAnimExporter implementation ----
  5.1606 +static long tstart, tend;
  5.1607 +
  5.1608 +int GoatAnimExporter::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent, DWORD opt)
  5.1609 +{
  5.1610 +	if(!(igame = GetIGameInterface())) {
  5.1611 +		maxlog("failed to get the igame interface\n");
  5.1612 +		return IMPEXP_FAIL;
  5.1613 +	}
  5.1614 +	IGameConversionManager *cm = GetConversionManager();
  5.1615 +	cm->SetCoordSystem(IGameConversionManager::IGAME_OGL);
  5.1616 +	igame->InitialiseIGame();
  5.1617 +	igame->SetStaticFrame(0);
  5.1618 +
  5.1619 +	tstart = tend = 0;
  5.1620 +	get_anim_bounds(igame, &tstart, &tend);
  5.1621 +
  5.1622 +	if(!DialogBox(hinst, MAKEINTRESOURCE(IDD_GOAT_ANM), 0, anim_gui_handler)) {
  5.1623 +		igame->ReleaseIGame();
  5.1624 +		return IMPEXP_CANCEL;
  5.1625 +	}
  5.1626 +
  5.1627 +	char fname[512];
  5.1628 +	wcstombs(fname, name, sizeof fname - 1);
  5.1629 +	for(int i=0; fname[i]; i++) {
  5.1630 +		fname[i] = tolower(fname[i]);
  5.1631 +	}
  5.1632 +
  5.1633 +	maxlog("Exporting Goat3D Animation (text) file: %s\n", fname);
  5.1634 +
  5.1635 +	goat3d *goat = goat3d_create();
  5.1636 +
  5.1637 +	// process all nodes
  5.1638 +	for(int i=0; i<igame->GetTopLevelNodeCount(); i++) {
  5.1639 +		IGameNode *node = igame->GetTopLevelNode(i);
  5.1640 +		process_node(goat, 0, node);
  5.1641 +	}
  5.1642 +
  5.1643 +	if(goat3d_save_anim(goat, fname) == -1) {
  5.1644 +		goat3d_free(goat);
  5.1645 +		igame->ReleaseIGame();
  5.1646 +		return IMPEXP_FAIL;
  5.1647 +	}
  5.1648 +
  5.1649 +	goat3d_free(goat);
  5.1650 +	igame->ReleaseIGame();
  5.1651 +	return IMPEXP_SUCCESS;
  5.1652 +}
  5.1653 +
  5.1654 +static INT_PTR CALLBACK anim_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
  5.1655 +{
  5.1656 +	switch(msg) {
  5.1657 +	case WM_INITDIALOG:
  5.1658 +		{
  5.1659 +			wchar_t buf[128];
  5.1660 +			CheckDlgButton(win, IDC_GOAT_ANM_FULL, BST_CHECKED);
  5.1661 +			CheckDlgButton(win, IDC_RAD_KEYS_ORIG, BST_CHECKED);
  5.1662 +			wsprintf(buf, L"%ld", tstart);
  5.1663 +			SetDlgItemText(win, IDC_EDIT_TSTART, buf);
  5.1664 +			wsprintf(buf, L"%ld", tend);
  5.1665 +			SetDlgItemText(win, IDC_EDIT_TEND, buf);
  5.1666 +		}
  5.1667 +		break;
  5.1668 +
  5.1669 +	case WM_COMMAND:
  5.1670 +		switch(LOWORD(wparam)) {
  5.1671 +		case IDOK:
  5.1672 +			EndDialog(win, 1);
  5.1673 +			break;
  5.1674 +
  5.1675 +		case IDCANCEL:
  5.1676 +			EndDialog(win, 0);
  5.1677 +			break;
  5.1678 +
  5.1679 +		default:
  5.1680 +			return 0;
  5.1681 +		}
  5.1682 +		break;
  5.1683 +
  5.1684 +	default:
  5.1685 +		return 0;
  5.1686 +	}
  5.1687 +
  5.1688 +	return 1;
  5.1689 +}
  5.1690 +
  5.1691 +// ------------------------------------------
  5.1692 +
  5.1693 +class GoatClassDesc : public ClassDesc2 {
  5.1694 +public:
  5.1695 +	int IsPublic() { return TRUE; }
  5.1696 +	void *Create(BOOL loading = FALSE) { return new GoatExporter; }
  5.1697 +	const TCHAR *ClassName() { return L"GoatExporter"; }
  5.1698 +	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
  5.1699 +	Class_ID ClassID() { return Class_ID(0x77050f0d, 0x7d4c5ab5); }
  5.1700 +	const TCHAR *Category() { return L"Mutant Stargoat"; }
  5.1701 +
  5.1702 +	const TCHAR *InternalName() { return L"GoatExporter"; }
  5.1703 +	HINSTANCE HInstance() { return hinst; }
  5.1704 +};
  5.1705 +
  5.1706 +class GoatAnimClassDesc : public ClassDesc2 {
  5.1707 +public:
  5.1708 +	int IsPublic() { return TRUE; }
  5.1709 +	void *Create(BOOL loading = FALSE) { return new GoatAnimExporter; }
  5.1710 +	const TCHAR *ClassName() { return L"GoatAnimExporter"; }
  5.1711 +	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
  5.1712 +	Class_ID ClassID() { return Class_ID(0x51b94924, 0x2e0332f3); }
  5.1713 +	const TCHAR *Category() { return L"Mutant Stargoat"; }
  5.1714 +
  5.1715 +	const TCHAR *InternalName() { return L"GoatAnimExporter"; }
  5.1716 +	HINSTANCE HInstance() { return hinst; }
  5.1717 +};
  5.1718 +
  5.1719 +// TODO: make 2 class descriptors, one for goat3d, one for goat3danim
  5.1720 +static GoatClassDesc class_desc;
  5.1721 +static GoatAnimClassDesc anim_class_desc;
  5.1722 +
  5.1723 +BOOL WINAPI DllMain(HINSTANCE inst_handle, ULONG reason, void *reserved)
  5.1724 +{
  5.1725 +	if(reason == DLL_PROCESS_ATTACH) {
  5.1726 +		hinst = inst_handle;
  5.1727 +		DisableThreadLibraryCalls(hinst);
  5.1728 +	}
  5.1729 +	return TRUE;
  5.1730 +}
  5.1731 +
  5.1732 +extern "C" {
  5.1733 +
  5.1734 +__declspec(dllexport) const TCHAR *LibDescription()
  5.1735 +{
  5.1736 +	return L"test exporter";
  5.1737 +}
  5.1738 +
  5.1739 +__declspec(dllexport) int LibNumberClasses()
  5.1740 +{
  5.1741 +	return 1;
  5.1742 +}
  5.1743 +
  5.1744 +__declspec(dllexport) ClassDesc *LibClassDesc(int i)
  5.1745 +{
  5.1746 +	switch(i) {
  5.1747 +	case 0:
  5.1748 +		return &class_desc;
  5.1749 +	case 1:
  5.1750 +		return &anim_class_desc;
  5.1751 +	default:
  5.1752 +		break;
  5.1753 +	}
  5.1754 +	return 0;
  5.1755 +}
  5.1756 +
  5.1757 +__declspec(dllexport) ULONG LibVersion()
  5.1758 +{
  5.1759 +	return Get3DSMAXVersion();
  5.1760 +}
  5.1761 +
  5.1762 +__declspec(dllexport) int LibInitialize()
  5.1763 +{
  5.1764 +	static char path[1024];
  5.1765 +
  5.1766 +	SHGetFolderPathA(0, CSIDL_PERSONAL, 0, 0, path);
  5.1767 +	strcat(path, "/testexp.log");
  5.1768 +
  5.1769 +	maxlog_open(path);
  5.1770 +	return TRUE;
  5.1771 +}
  5.1772 +
  5.1773 +__declspec(dllexport) int LibShutdown()
  5.1774 +{
  5.1775 +	maxlog_close();
  5.1776 +	return TRUE;
  5.1777 +}
  5.1778 +
  5.1779 +}	// extern "C"
  5.1780 +
  5.1781 +
  5.1782 +static const char *max_string(const MCHAR *wstr)
  5.1783 +{
  5.1784 +	if(!wstr) return 0;
  5.1785 +	static char str[512];
  5.1786 +	wcstombs(str, wstr, sizeof str - 1);
  5.1787 +	return str;
  5.1788 +}
     6.1 --- a/exporters/maxgoat_stub/src/stub.cc	Tue May 06 03:31:35 2014 +0300
     6.2 +++ b/exporters/maxgoat_stub/src/stub.cc	Tue May 06 03:57:11 2014 +0300
     6.3 @@ -1,274 +1,274 @@
     6.4 -#include <stdio.h>
     6.5 -#include <string.h>
     6.6 -#include <stdlib.h>
     6.7 -#include <errno.h>
     6.8 -#include <map>
     6.9 -#include <windows.h>
    6.10 -#include <shlobj.h>
    6.11 -#include "max.h"
    6.12 -#include "impexp.h"		// SceneExport
    6.13 -#include "iparamb2.h"	// ClassDesc2
    6.14 -#include "plugapi.h"
    6.15 -#include "IGame.h"
    6.16 -#include "IGameExport.h"
    6.17 -#include "IConversionmanager.h"
    6.18 -
    6.19 -
    6.20 -#pragma comment (lib, "core.lib")
    6.21 -#pragma comment (lib, "geom.lib")
    6.22 -#pragma comment (lib, "gfx.lib")
    6.23 -#pragma comment (lib, "mesh.lib")
    6.24 -#pragma comment (lib, "maxutil.lib")
    6.25 -#pragma comment (lib, "maxscrpt.lib")
    6.26 -#pragma comment (lib, "paramblk2.lib")
    6.27 -#pragma comment (lib, "msxml2.lib")
    6.28 -#pragma comment (lib, "igame.lib")
    6.29 -#pragma comment (lib, "comctl32.lib")
    6.30 -
    6.31 -
    6.32 -#define VER_MAJOR	1
    6.33 -#define VER_MINOR	0
    6.34 -#define VERSION(major, minor) \
    6.35 -	((major) * 100 + ((minor) < 10 ? (minor) * 10 : (minor)))
    6.36 -
    6.37 -typedef int (*PluginInitFunc)();
    6.38 -typedef int (*PluginShutdownFunc)();
    6.39 -typedef ClassDesc *(*PluginClassDescFunc)(int);
    6.40 -
    6.41 -static FILE *logfile;
    6.42 -static HINSTANCE hinst;
    6.43 -static const wchar_t *copyright_str = L"Copyright 2013 (C) John Tsiombikas - GNU General Public License v3, see COPYING for details.";
    6.44 -
    6.45 -class GoatExporterStub : public SceneExport {
    6.46 -public:
    6.47 -	IGameScene *igame;
    6.48 -
    6.49 -	int ExtCount() { return 1; }
    6.50 -	const TCHAR *Ext(int n) { return L"goatsce"; }
    6.51 -	const TCHAR *LongDesc() { return L"Goat3D Scene file"; }
    6.52 -	const TCHAR *ShortDesc() { return L"Goat3D Scene"; }
    6.53 -	const TCHAR *AuthorName() { return L"John Tsiombikas"; }
    6.54 -	const TCHAR *CopyrightMessage() { return copyright_str; }
    6.55 -	const TCHAR *OtherMessage1() { return L"foo1"; }
    6.56 -	const TCHAR *OtherMessage2() { return L"foo2"; }
    6.57 -	unsigned int Version() { return VERSION(VER_MAJOR, VER_MINOR); }
    6.58 -	void ShowAbout(HWND win) { MessageBoxA(win, "Goat3D exporter", "About this plugin", 0); }
    6.59 -
    6.60 -	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
    6.61 -};
    6.62 -
    6.63 -class GoatAnimExporterStub : public SceneExport {
    6.64 -public:
    6.65 -	IGameScene *igame;
    6.66 -
    6.67 -	int ExtCount() { return 1; }
    6.68 -	const TCHAR *Ext(int n) { return L"goatanm"; }
    6.69 -	const TCHAR *LongDesc() { return L"Goat3D Animation file"; }
    6.70 -	const TCHAR *ShortDesc() { return L"Goat3D Animation"; }
    6.71 -	const TCHAR *AuthorName() { return L"John Tsiombikas"; }
    6.72 -	const TCHAR *CopyrightMessage() { return copyright_str; }
    6.73 -	const TCHAR *OtherMessage1() { return L"bar1"; }
    6.74 -	const TCHAR *OtherMessage2() { return L"bar2"; }
    6.75 -	unsigned int Version() { return VERSION(VER_MAJOR, VER_MINOR); }
    6.76 -	void ShowAbout(HWND win) { MessageBoxA(win, "Goat3D anim exporter", "About this plugin", 0); }
    6.77 -
    6.78 -	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
    6.79 -};
    6.80 -
    6.81 -static const char *find_dll_dir()
    6.82 -{
    6.83 -	static char path[MAX_PATH];
    6.84 -
    6.85 -	HMODULE dll;
    6.86 -	if(!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
    6.87 -			(LPCSTR)find_dll_dir, &dll)) {
    6.88 -		return 0;
    6.89 -	}
    6.90 -	GetModuleFileNameA(dll, path, sizeof path);
    6.91 -
    6.92 -	char *last_slash = strrchr(path, '\\');
    6.93 -	if(last_slash && last_slash[1]) {
    6.94 -		*last_slash = 0;
    6.95 -	}
    6.96 -
    6.97 -	return path;
    6.98 -}
    6.99 -
   6.100 -static int do_export(int which, const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL non_int, DWORD opt)
   6.101 -{
   6.102 -	const char *dll_fname = "maxgoat.dll";
   6.103 -	char *dll_path;
   6.104 -	HMODULE dll = 0;
   6.105 -	PluginInitFunc init;
   6.106 -	PluginShutdownFunc shutdown;
   6.107 -	PluginClassDescFunc get_class_desc;
   6.108 -	ClassDesc *desc;
   6.109 -	SceneExport *ex;
   6.110 -	int result = IMPEXP_FAIL;
   6.111 -
   6.112 -	const char *plugdir = find_dll_dir();
   6.113 -	if(plugdir) {
   6.114 -		dll_path = new char[strlen(dll_fname) + strlen(plugdir) + 2];
   6.115 -		sprintf(dll_path, "%s\\%s", plugdir, dll_fname);
   6.116 -	} else {
   6.117 -		dll_path = new char[strlen(dll_fname) + 1];
   6.118 -		strcpy(dll_path, dll_fname);
   6.119 -	}
   6.120 -
   6.121 -	if(!(dll = LoadLibraryA(dll_path))) {
   6.122 -		fprintf(logfile, "failed to load exporter: %s\n", dll_path);
   6.123 -		goto done;
   6.124 -	}
   6.125 -
   6.126 -	if(!(get_class_desc = (PluginClassDescFunc)GetProcAddress(dll, "LibClassDesc"))) {
   6.127 -		fprintf(logfile, "maxgoat.dll is invalid (no LibClassDesc function)\n");
   6.128 -		goto done;
   6.129 -	}
   6.130 -
   6.131 -	// first initialize the library
   6.132 -	if((init = (PluginInitFunc)GetProcAddress(dll, "LibInitialize"))) {
   6.133 -		if(!init()) {
   6.134 -			fprintf(logfile, "exporter initialization failed!\n");
   6.135 -			goto done;
   6.136 -		}
   6.137 -	}
   6.138 -
   6.139 -	if(!(desc = get_class_desc(which))) {
   6.140 -		fprintf(logfile, "failed to get the class descriptor\n");
   6.141 -		goto done;
   6.142 -	}
   6.143 -
   6.144 -	if(!(ex = (SceneExport*)desc->Create())) {
   6.145 -		fprintf(logfile, "failed to create exporter class instance\n");
   6.146 -		goto done;
   6.147 -	}
   6.148 -
   6.149 -	__try {
   6.150 -		result = ex->DoExport(name, eiface, iface);
   6.151 -	}
   6.152 -	__except(EXCEPTION_EXECUTE_HANDLER) {
   6.153 -		fprintf(logfile, "Exception caught!\n");
   6.154 -		delete ex;
   6.155 -		goto done;
   6.156 -	}
   6.157 -	delete ex;
   6.158 -
   6.159 -	if((shutdown = (PluginShutdownFunc)GetProcAddress(dll, "LibShutdown"))) {
   6.160 -		shutdown();
   6.161 -	}
   6.162 -
   6.163 -done:
   6.164 -	delete [] dll_path;
   6.165 -	if(dll) {
   6.166 -		FreeLibrary(dll);
   6.167 -	}
   6.168 -	return result;
   6.169 -}
   6.170 -
   6.171 -int GoatExporterStub::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
   6.172 -		BOOL non_interactive, DWORD opt)
   6.173 -{
   6.174 -	return do_export(0, name, eiface, iface, non_interactive, opt);
   6.175 -}
   6.176 -
   6.177 -
   6.178 -int GoatAnimExporterStub::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
   6.179 -		BOOL non_interactive, DWORD opt)
   6.180 -{
   6.181 -	return do_export(1, name, eiface, iface, non_interactive, opt);
   6.182 -}
   6.183 -
   6.184 -// ------------------------------------------
   6.185 -
   6.186 -class GoatClassDesc : public ClassDesc2 {
   6.187 -public:
   6.188 -	int IsPublic() { return TRUE; }
   6.189 -	void *Create(BOOL loading = FALSE) { return new GoatExporterStub; }
   6.190 -	const TCHAR *ClassName() { return L"GoatExporterStub"; }
   6.191 -	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
   6.192 -	Class_ID ClassID() { return Class_ID(0x2e4e6311, 0x2b154d91); }
   6.193 -	const TCHAR *Category() { return L"Mutant Stargoat"; }
   6.194 -
   6.195 -	const TCHAR *InternalName() { return L"GoatExporterStub"; }
   6.196 -	HINSTANCE HInstance() { return hinst; }
   6.197 -};
   6.198 -
   6.199 -class GoatAnimClassDesc : public ClassDesc2 {
   6.200 -public:
   6.201 -	int IsPublic() { return TRUE; }
   6.202 -	void *Create(BOOL loading = FALSE) { return new GoatAnimExporterStub; }
   6.203 -	const TCHAR *ClassName() { return L"GoatAnimExporterStub"; }
   6.204 -	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
   6.205 -	Class_ID ClassID() { return Class_ID(0x75054666, 0x45487285); }
   6.206 -	const TCHAR *Category() { return L"Mutant Stargoat"; }
   6.207 -
   6.208 -	const TCHAR *InternalName() { return L"GoatAnimExporterStub"; }
   6.209 -	HINSTANCE HInstance() { return hinst; }
   6.210 -};
   6.211 -
   6.212 -
   6.213 -static GoatClassDesc class_desc;
   6.214 -static GoatAnimClassDesc anim_class_desc;
   6.215 -
   6.216 -BOOL WINAPI DllMain(HINSTANCE inst_handle, ULONG reason, void *reserved)
   6.217 -{
   6.218 -	if(reason == DLL_PROCESS_ATTACH) {
   6.219 -		hinst = inst_handle;
   6.220 -		DisableThreadLibraryCalls(hinst);
   6.221 -	}
   6.222 -	return TRUE;
   6.223 -}
   6.224 -
   6.225 -extern "C" {
   6.226 -
   6.227 -__declspec(dllexport) const TCHAR *LibDescription()
   6.228 -{
   6.229 -	return L"Goat3D exporter stub";
   6.230 -}
   6.231 -
   6.232 -__declspec(dllexport) int LibNumberClasses()
   6.233 -{
   6.234 -	return 2;
   6.235 -}
   6.236 -
   6.237 -__declspec(dllexport) ClassDesc *LibClassDesc(int i)
   6.238 -{
   6.239 -	switch(i) {
   6.240 -	case 0:
   6.241 -		return &class_desc;
   6.242 -	case 1:
   6.243 -		return &anim_class_desc;
   6.244 -	default:
   6.245 -		break;
   6.246 -	}
   6.247 -	return 0;
   6.248 -}
   6.249 -
   6.250 -__declspec(dllexport) ULONG LibVersion()
   6.251 -{
   6.252 -	return Get3DSMAXVersion();
   6.253 -}
   6.254 -
   6.255 -__declspec(dllexport) int LibInitialize()
   6.256 -{
   6.257 -	static char path[1024];
   6.258 -
   6.259 -	SHGetFolderPathA(0, CSIDL_PERSONAL, 0, 0, path);
   6.260 -	strcat(path, "/testexpstub.log");
   6.261 -
   6.262 -	if((logfile = fopen(path, "w"))) {
   6.263 -		setvbuf(logfile, 0, _IONBF, 0);
   6.264 -	}
   6.265 -	return TRUE;
   6.266 -}
   6.267 -
   6.268 -__declspec(dllexport) int LibShutdown()
   6.269 -{
   6.270 -	if(logfile) {
   6.271 -		fclose(logfile);
   6.272 -		logfile = 0;
   6.273 -	}
   6.274 -	return TRUE;
   6.275 -}
   6.276 -
   6.277 -}	// extern "C"
   6.278 \ No newline at end of file
   6.279 +#include <stdio.h>
   6.280 +#include <string.h>
   6.281 +#include <stdlib.h>
   6.282 +#include <errno.h>
   6.283 +#include <map>
   6.284 +#include <windows.h>
   6.285 +#include <shlobj.h>
   6.286 +#include "max.h"
   6.287 +#include "impexp.h"		// SceneExport
   6.288 +#include "iparamb2.h"	// ClassDesc2
   6.289 +#include "plugapi.h"
   6.290 +#include "IGame.h"
   6.291 +#include "IGameExport.h"
   6.292 +#include "IConversionmanager.h"
   6.293 +
   6.294 +
   6.295 +#pragma comment (lib, "core.lib")
   6.296 +#pragma comment (lib, "geom.lib")
   6.297 +#pragma comment (lib, "gfx.lib")
   6.298 +#pragma comment (lib, "mesh.lib")
   6.299 +#pragma comment (lib, "maxutil.lib")
   6.300 +#pragma comment (lib, "maxscrpt.lib")
   6.301 +#pragma comment (lib, "paramblk2.lib")
   6.302 +#pragma comment (lib, "msxml2.lib")
   6.303 +#pragma comment (lib, "igame.lib")
   6.304 +#pragma comment (lib, "comctl32.lib")
   6.305 +
   6.306 +
   6.307 +#define VER_MAJOR	1
   6.308 +#define VER_MINOR	0
   6.309 +#define VERSION(major, minor) \
   6.310 +	((major) * 100 + ((minor) < 10 ? (minor) * 10 : (minor)))
   6.311 +
   6.312 +typedef int (*PluginInitFunc)();
   6.313 +typedef int (*PluginShutdownFunc)();
   6.314 +typedef ClassDesc *(*PluginClassDescFunc)(int);
   6.315 +
   6.316 +static FILE *logfile;
   6.317 +static HINSTANCE hinst;
   6.318 +static const wchar_t *copyright_str = L"Copyright 2013 (C) John Tsiombikas - GNU General Public License v3, see COPYING for details.";
   6.319 +
   6.320 +class GoatExporterStub : public SceneExport {
   6.321 +public:
   6.322 +	IGameScene *igame;
   6.323 +
   6.324 +	int ExtCount() { return 1; }
   6.325 +	const TCHAR *Ext(int n) { return L"goatsce"; }
   6.326 +	const TCHAR *LongDesc() { return L"Goat3D Scene file"; }
   6.327 +	const TCHAR *ShortDesc() { return L"Goat3D Scene"; }
   6.328 +	const TCHAR *AuthorName() { return L"John Tsiombikas"; }
   6.329 +	const TCHAR *CopyrightMessage() { return copyright_str; }
   6.330 +	const TCHAR *OtherMessage1() { return L"foo1"; }
   6.331 +	const TCHAR *OtherMessage2() { return L"foo2"; }
   6.332 +	unsigned int Version() { return VERSION(VER_MAJOR, VER_MINOR); }
   6.333 +	void ShowAbout(HWND win) { MessageBoxA(win, "Goat3D exporter", "About this plugin", 0); }
   6.334 +
   6.335 +	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
   6.336 +};
   6.337 +
   6.338 +class GoatAnimExporterStub : public SceneExport {
   6.339 +public:
   6.340 +	IGameScene *igame;
   6.341 +
   6.342 +	int ExtCount() { return 1; }
   6.343 +	const TCHAR *Ext(int n) { return L"goatanm"; }
   6.344 +	const TCHAR *LongDesc() { return L"Goat3D Animation file"; }
   6.345 +	const TCHAR *ShortDesc() { return L"Goat3D Animation"; }
   6.346 +	const TCHAR *AuthorName() { return L"John Tsiombikas"; }
   6.347 +	const TCHAR *CopyrightMessage() { return copyright_str; }
   6.348 +	const TCHAR *OtherMessage1() { return L"bar1"; }
   6.349 +	const TCHAR *OtherMessage2() { return L"bar2"; }
   6.350 +	unsigned int Version() { return VERSION(VER_MAJOR, VER_MINOR); }
   6.351 +	void ShowAbout(HWND win) { MessageBoxA(win, "Goat3D anim exporter", "About this plugin", 0); }
   6.352 +
   6.353 +	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
   6.354 +};
   6.355 +
   6.356 +static const char *find_dll_dir()
   6.357 +{
   6.358 +	static char path[MAX_PATH];
   6.359 +
   6.360 +	HMODULE dll;
   6.361 +	if(!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
   6.362 +			(LPCSTR)find_dll_dir, &dll)) {
   6.363 +		return 0;
   6.364 +	}
   6.365 +	GetModuleFileNameA(dll, path, sizeof path);
   6.366 +
   6.367 +	char *last_slash = strrchr(path, '\\');
   6.368 +	if(last_slash && last_slash[1]) {
   6.369 +		*last_slash = 0;
   6.370 +	}
   6.371 +
   6.372 +	return path;
   6.373 +}
   6.374 +
   6.375 +static int do_export(int which, const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL non_int, DWORD opt)
   6.376 +{
   6.377 +	const char *dll_fname = "maxgoat.dll";
   6.378 +	char *dll_path;
   6.379 +	HMODULE dll = 0;
   6.380 +	PluginInitFunc init;
   6.381 +	PluginShutdownFunc shutdown;
   6.382 +	PluginClassDescFunc get_class_desc;
   6.383 +	ClassDesc *desc;
   6.384 +	SceneExport *ex;
   6.385 +	int result = IMPEXP_FAIL;
   6.386 +
   6.387 +	const char *plugdir = find_dll_dir();
   6.388 +	if(plugdir) {
   6.389 +		dll_path = new char[strlen(dll_fname) + strlen(plugdir) + 2];
   6.390 +		sprintf(dll_path, "%s\\%s", plugdir, dll_fname);
   6.391 +	} else {
   6.392 +		dll_path = new char[strlen(dll_fname) + 1];
   6.393 +		strcpy(dll_path, dll_fname);
   6.394 +	}
   6.395 +
   6.396 +	if(!(dll = LoadLibraryA(dll_path))) {
   6.397 +		fprintf(logfile, "failed to load exporter: %s\n", dll_path);
   6.398 +		goto done;
   6.399 +	}
   6.400 +
   6.401 +	if(!(get_class_desc = (PluginClassDescFunc)GetProcAddress(dll, "LibClassDesc"))) {
   6.402 +		fprintf(logfile, "maxgoat.dll is invalid (no LibClassDesc function)\n");
   6.403 +		goto done;
   6.404 +	}
   6.405 +
   6.406 +	// first initialize the library
   6.407 +	if((init = (PluginInitFunc)GetProcAddress(dll, "LibInitialize"))) {
   6.408 +		if(!init()) {
   6.409 +			fprintf(logfile, "exporter initialization failed!\n");
   6.410 +			goto done;
   6.411 +		}
   6.412 +	}
   6.413 +
   6.414 +	if(!(desc = get_class_desc(which))) {
   6.415 +		fprintf(logfile, "failed to get the class descriptor\n");
   6.416 +		goto done;
   6.417 +	}
   6.418 +
   6.419 +	if(!(ex = (SceneExport*)desc->Create())) {
   6.420 +		fprintf(logfile, "failed to create exporter class instance\n");
   6.421 +		goto done;
   6.422 +	}
   6.423 +
   6.424 +	__try {
   6.425 +		result = ex->DoExport(name, eiface, iface);
   6.426 +	}
   6.427 +	__except(EXCEPTION_EXECUTE_HANDLER) {
   6.428 +		fprintf(logfile, "Exception caught!\n");
   6.429 +		delete ex;
   6.430 +		goto done;
   6.431 +	}
   6.432 +	delete ex;
   6.433 +
   6.434 +	if((shutdown = (PluginShutdownFunc)GetProcAddress(dll, "LibShutdown"))) {
   6.435 +		shutdown();
   6.436 +	}
   6.437 +
   6.438 +done:
   6.439 +	delete [] dll_path;
   6.440 +	if(dll) {
   6.441 +		FreeLibrary(dll);
   6.442 +	}
   6.443 +	return result;
   6.444 +}
   6.445 +
   6.446 +int GoatExporterStub::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
   6.447 +		BOOL non_interactive, DWORD opt)
   6.448 +{
   6.449 +	return do_export(0, name, eiface, iface, non_interactive, opt);
   6.450 +}
   6.451 +
   6.452 +
   6.453 +int GoatAnimExporterStub::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
   6.454 +		BOOL non_interactive, DWORD opt)
   6.455 +{
   6.456 +	return do_export(1, name, eiface, iface, non_interactive, opt);
   6.457 +}
   6.458 +
   6.459 +// ------------------------------------------
   6.460 +
   6.461 +class GoatClassDesc : public ClassDesc2 {
   6.462 +public:
   6.463 +	int IsPublic() { return TRUE; }
   6.464 +	void *Create(BOOL loading = FALSE) { return new GoatExporterStub; }
   6.465 +	const TCHAR *ClassName() { return L"GoatExporterStub"; }
   6.466 +	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
   6.467 +	Class_ID ClassID() { return Class_ID(0x2e4e6311, 0x2b154d91); }
   6.468 +	const TCHAR *Category() { return L"Mutant Stargoat"; }
   6.469 +
   6.470 +	const TCHAR *InternalName() { return L"GoatExporterStub"; }
   6.471 +	HINSTANCE HInstance() { return hinst; }
   6.472 +};
   6.473 +
   6.474 +class GoatAnimClassDesc : public ClassDesc2 {
   6.475 +public:
   6.476 +	int IsPublic() { return TRUE; }
   6.477 +	void *Create(BOOL loading = FALSE) { return new GoatAnimExporterStub; }
   6.478 +	const TCHAR *ClassName() { return L"GoatAnimExporterStub"; }
   6.479 +	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
   6.480 +	Class_ID ClassID() { return Class_ID(0x75054666, 0x45487285); }
   6.481 +	const TCHAR *Category() { return L"Mutant Stargoat"; }
   6.482 +
   6.483 +	const TCHAR *InternalName() { return L"GoatAnimExporterStub"; }
   6.484 +	HINSTANCE HInstance() { return hinst; }
   6.485 +};
   6.486 +
   6.487 +
   6.488 +static GoatClassDesc class_desc;
   6.489 +static GoatAnimClassDesc anim_class_desc;
   6.490 +
   6.491 +BOOL WINAPI DllMain(HINSTANCE inst_handle, ULONG reason, void *reserved)
   6.492 +{
   6.493 +	if(reason == DLL_PROCESS_ATTACH) {
   6.494 +		hinst = inst_handle;
   6.495 +		DisableThreadLibraryCalls(hinst);
   6.496 +	}
   6.497 +	return TRUE;
   6.498 +}
   6.499 +
   6.500 +extern "C" {
   6.501 +
   6.502 +__declspec(dllexport) const TCHAR *LibDescription()
   6.503 +{
   6.504 +	return L"Goat3D exporter stub";
   6.505 +}
   6.506 +
   6.507 +__declspec(dllexport) int LibNumberClasses()
   6.508 +{
   6.509 +	return 2;
   6.510 +}
   6.511 +
   6.512 +__declspec(dllexport) ClassDesc *LibClassDesc(int i)
   6.513 +{
   6.514 +	switch(i) {
   6.515 +	case 0:
   6.516 +		return &class_desc;
   6.517 +	case 1:
   6.518 +		return &anim_class_desc;
   6.519 +	default:
   6.520 +		break;
   6.521 +	}
   6.522 +	return 0;
   6.523 +}
   6.524 +
   6.525 +__declspec(dllexport) ULONG LibVersion()
   6.526 +{
   6.527 +	return Get3DSMAXVersion();
   6.528 +}
   6.529 +
   6.530 +__declspec(dllexport) int LibInitialize()
   6.531 +{
   6.532 +	static char path[1024];
   6.533 +
   6.534 +	SHGetFolderPathA(0, CSIDL_PERSONAL, 0, 0, path);
   6.535 +	strcat(path, "/testexpstub.log");
   6.536 +
   6.537 +	if((logfile = fopen(path, "w"))) {
   6.538 +		setvbuf(logfile, 0, _IONBF, 0);
   6.539 +	}
   6.540 +	return TRUE;
   6.541 +}
   6.542 +
   6.543 +__declspec(dllexport) int LibShutdown()
   6.544 +{
   6.545 +	if(logfile) {
   6.546 +		fclose(logfile);
   6.547 +		logfile = 0;
   6.548 +	}
   6.549 +	return TRUE;
   6.550 +}
   6.551 +
   6.552 +}	// extern "C"
     7.1 --- a/goatview/Makefile	Tue May 06 03:31:35 2014 +0300
     7.2 +++ b/goatview/Makefile	Tue May 06 03:57:11 2014 +0300
     7.3 @@ -1,32 +1,41 @@
     7.4  PREFIX = /usr/local
     7.5  
     7.6 -src = $(wildcard src/*.c)
     7.7 -obj = $(src:.c=.o)
     7.8 +src = $(wildcard src/*.cc)
     7.9 +mochdr = src/goatview.h
    7.10 +mocsrc = $(patsubst src/%.h,src/moc_%.cc,$(mochdr))
    7.11 +obj = $(sort $(src:.cc=.o) $(mocsrc:.cc=.o))
    7.12  dep = $(obj:.o=.d)
    7.13  bin = goatview
    7.14  
    7.15  goat_root = ..
    7.16  
    7.17 -CC = clang
    7.18 -CPP = clang -E
    7.19 -CFLAGS = -pedantic -Wall -g -I$(goat_root)/src
    7.20 -LDFLAGS = $(libgoat) $(libgl)
    7.21 +CXXFLAGS = -std=c++11 -pedantic -Wall -g $(pic) -I$(goat_root)/src $(qtinc)
    7.22 +LDFLAGS = $(libgoat) $(libgl) $(qtlib)
    7.23 +MOC = moc
    7.24 +
    7.25 +qtinc = `pkg-config --cflags Qt5Gui Qt5Core Qt5OpenGL`
    7.26 +qtlib = `pkg-config --libs Qt5Gui Qt5Core Qt5OpenGL`
    7.27  
    7.28  ifeq ($(shell uname -s), Darwin)
    7.29  	libgl = -framework OpenGL -framework GLUT -lGLEW
    7.30  	libgoat = $(goat_root)/libgoat3d.dylib
    7.31  else
    7.32 +	pic = -fPIC
    7.33  	libgl = -lGL -lGLU -lglut -lGLEW
    7.34  	libgoat = $(goat_root)/libgoat3d.so.0.1
    7.35  endif
    7.36  
    7.37  $(bin): $(obj) $(libgoat)
    7.38 -	$(CC) -o $@ $(obj) $(LDFLAGS)
    7.39 +	$(CXX) -o $@ $(obj) $(LDFLAGS)
    7.40 +
    7.41 +# rule for running moc on ui header files
    7.42 +moc_%.cc: %.h
    7.43 +	$(MOC) -o $@ $<
    7.44  
    7.45  -include $(dep)
    7.46  
    7.47 -%.d: %.c
    7.48 -	@$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
    7.49 +%.d: %.cc
    7.50 +	@$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@
    7.51  
    7.52  .PHONY: clean
    7.53  clean:
     8.1 --- a/goatview/src/goatview.cc	Tue May 06 03:31:35 2014 +0300
     8.2 +++ b/goatview/src/goatview.cc	Tue May 06 03:57:11 2014 +0300
     8.3 @@ -1,117 +1,117 @@
     8.4 -#include "goatview.h"
     8.5 -
     8.6 -GoatView::GoatView()
     8.7 -{
     8.8 -	make_menu();
     8.9 -	make_dock();
    8.10 -	make_center();
    8.11 -
    8.12 -	statusBar();
    8.13 -
    8.14 -	setWindowTitle("GoatView");
    8.15 -}
    8.16 -
    8.17 -GoatView::~GoatView()
    8.18 -{
    8.19 -}
    8.20 -
    8.21 -bool GoatView::make_menu()
    8.22 -{
    8.23 -	QMenu *menu_file = menuBar()->addMenu("&File");
    8.24 -
    8.25 -	QAction *act_open_sce = new QAction("&Open Scene", this);
    8.26 -	act_open_sce->setShortcuts(QKeySequence::Open);
    8.27 -	connect(act_open_sce, &QAction::triggered, this, &GoatView::open_scene);
    8.28 -	menu_file->addAction(act_open_sce);
    8.29 -
    8.30 -	QAction *act_open_anm = new QAction("Open &Animation", this);
    8.31 -	connect(act_open_anm, &QAction::triggered, this, &GoatView::open_anim);
    8.32 -	menu_file->addAction(act_open_anm);
    8.33 -
    8.34 -	QAction *act_quit = new QAction("&Quit", this);
    8.35 -	act_quit->setShortcuts(QKeySequence::Quit);
    8.36 -	connect(act_quit, &QAction::triggered, [&](){qApp->quit();});
    8.37 -	menu_file->addAction(act_quit);
    8.38 -	return true;
    8.39 -}
    8.40 -
    8.41 -bool GoatView::make_dock()
    8.42 -{
    8.43 -	// ---- side-dock ----
    8.44 -	QWidget *dock_cont = new QWidget;
    8.45 -	QVBoxLayout *dock_vbox = new QVBoxLayout;
    8.46 -	dock_cont->setLayout(dock_vbox);
    8.47 -
    8.48 -	QPushButton *bn_quit = new QPushButton("quit");
    8.49 -	dock_vbox->addWidget(bn_quit);
    8.50 -	connect(bn_quit, &QPushButton::clicked, [&](){qApp->quit();});
    8.51 -
    8.52 -	QDockWidget *dock = new QDockWidget("Scene graph", this);
    8.53 -	dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    8.54 -	dock->setWidget(dock_cont);
    8.55 -	addDockWidget(Qt::LeftDockWidgetArea, dock);
    8.56 -
    8.57 -	// ---- bottom dock ----
    8.58 -	dock_cont = new QWidget;
    8.59 -	QHBoxLayout *dock_hbox = new QHBoxLayout;
    8.60 -	dock_cont->setLayout(dock_hbox);
    8.61 -
    8.62 -	QSlider *slider_time = new QSlider(Qt::Orientation::Horizontal);
    8.63 -	slider_time->setDisabled(true);
    8.64 -	dock_hbox->addWidget(slider_time);
    8.65 -
    8.66 -	dock = new QDockWidget("Animation", this);
    8.67 -	dock->setAllowedAreas(Qt::BottomDockWidgetArea);
    8.68 -	dock->setWidget(dock_cont);
    8.69 -	addDockWidget(Qt::BottomDockWidgetArea, dock);
    8.70 -
    8.71 -	return true;
    8.72 -}
    8.73 -
    8.74 -bool GoatView::make_center()
    8.75 -{
    8.76 -	GoatViewport *vport = new GoatViewport;
    8.77 -	setCentralWidget(vport);
    8.78 -	return true;
    8.79 -}
    8.80 -
    8.81 -void GoatView::open_scene()
    8.82 -{
    8.83 -	statusBar()->showMessage("opening scene...");
    8.84 -}
    8.85 -
    8.86 -void GoatView::open_anim()
    8.87 -{
    8.88 -	statusBar()->showMessage("opening animation...");
    8.89 -}
    8.90 -
    8.91 -
    8.92 -// ---- OpenGL viewport ----
    8.93 -GoatViewport::GoatViewport()
    8.94 -	: QGLWidget(QGLFormat(QGL::DepthBuffer))
    8.95 -{
    8.96 -}
    8.97 -
    8.98 -GoatViewport::~GoatViewport()
    8.99 -{
   8.100 -}
   8.101 -
   8.102 -QSize GoatViewport::sizeHint() const
   8.103 -{
   8.104 -	return QSize(800, 600);
   8.105 -}
   8.106 -
   8.107 -void GoatViewport::initializeGL()
   8.108 -{
   8.109 -}
   8.110 -
   8.111 -void GoatViewport::resizeGL(int xsz, int ysz)
   8.112 -{
   8.113 -	glViewport(0, 0, xsz, ysz);
   8.114 -}
   8.115 -
   8.116 -void GoatViewport::paintGL()
   8.117 -{
   8.118 -	glClearColor(1, 0, 0, 1);
   8.119 -	glClear(GL_COLOR_BUFFER_BIT);
   8.120 -}
   8.121 \ No newline at end of file
   8.122 +#include "goatview.h"
   8.123 +
   8.124 +GoatView::GoatView()
   8.125 +{
   8.126 +	make_menu();
   8.127 +	make_dock();
   8.128 +	make_center();
   8.129 +
   8.130 +	statusBar();
   8.131 +
   8.132 +	setWindowTitle("GoatView");
   8.133 +}
   8.134 +
   8.135 +GoatView::~GoatView()
   8.136 +{
   8.137 +}
   8.138 +
   8.139 +bool GoatView::make_menu()
   8.140 +{
   8.141 +	QMenu *menu_file = menuBar()->addMenu("&File");
   8.142 +
   8.143 +	QAction *act_open_sce = new QAction("&Open Scene", this);
   8.144 +	act_open_sce->setShortcuts(QKeySequence::Open);
   8.145 +	connect(act_open_sce, &QAction::triggered, this, &GoatView::open_scene);
   8.146 +	menu_file->addAction(act_open_sce);
   8.147 +
   8.148 +	QAction *act_open_anm = new QAction("Open &Animation", this);
   8.149 +	connect(act_open_anm, &QAction::triggered, this, &GoatView::open_anim);
   8.150 +	menu_file->addAction(act_open_anm);
   8.151 +
   8.152 +	QAction *act_quit = new QAction("&Quit", this);
   8.153 +	act_quit->setShortcuts(QKeySequence::Quit);
   8.154 +	connect(act_quit, &QAction::triggered, [&](){qApp->quit();});
   8.155 +	menu_file->addAction(act_quit);
   8.156 +	return true;
   8.157 +}
   8.158 +
   8.159 +bool GoatView::make_dock()
   8.160 +{
   8.161 +	// ---- side-dock ----
   8.162 +	QWidget *dock_cont = new QWidget;
   8.163 +	QVBoxLayout *dock_vbox = new QVBoxLayout;
   8.164 +	dock_cont->setLayout(dock_vbox);
   8.165 +
   8.166 +	QPushButton *bn_quit = new QPushButton("quit");
   8.167 +	dock_vbox->addWidget(bn_quit);
   8.168 +	connect(bn_quit, &QPushButton::clicked, [&](){qApp->quit();});
   8.169 +
   8.170 +	QDockWidget *dock = new QDockWidget("Scene graph", this);
   8.171 +	dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
   8.172 +	dock->setWidget(dock_cont);
   8.173 +	addDockWidget(Qt::LeftDockWidgetArea, dock);
   8.174 +
   8.175 +	// ---- bottom dock ----
   8.176 +	dock_cont = new QWidget;
   8.177 +	QHBoxLayout *dock_hbox = new QHBoxLayout;
   8.178 +	dock_cont->setLayout(dock_hbox);
   8.179 +
   8.180 +	QSlider *slider_time = new QSlider(Qt::Orientation::Horizontal);
   8.181 +	slider_time->setDisabled(true);
   8.182 +	dock_hbox->addWidget(slider_time);
   8.183 +
   8.184 +	dock = new QDockWidget("Animation", this);
   8.185 +	dock->setAllowedAreas(Qt::BottomDockWidgetArea);
   8.186 +	dock->setWidget(dock_cont);
   8.187 +	addDockWidget(Qt::BottomDockWidgetArea, dock);
   8.188 +
   8.189 +	return true;
   8.190 +}
   8.191 +
   8.192 +bool GoatView::make_center()
   8.193 +{
   8.194 +	GoatViewport *vport = new GoatViewport;
   8.195 +	setCentralWidget(vport);
   8.196 +	return true;
   8.197 +}
   8.198 +
   8.199 +void GoatView::open_scene()
   8.200 +{
   8.201 +	statusBar()->showMessage("opening scene...");
   8.202 +}
   8.203 +
   8.204 +void GoatView::open_anim()
   8.205 +{
   8.206 +	statusBar()->showMessage("opening animation...");
   8.207 +}
   8.208 +
   8.209 +
   8.210 +// ---- OpenGL viewport ----
   8.211 +GoatViewport::GoatViewport()
   8.212 +	: QGLWidget(QGLFormat(QGL::DepthBuffer))
   8.213 +{
   8.214 +}
   8.215 +
   8.216 +GoatViewport::~GoatViewport()
   8.217 +{
   8.218 +}
   8.219 +
   8.220 +QSize GoatViewport::sizeHint() const
   8.221 +{
   8.222 +	return QSize(800, 600);
   8.223 +}
   8.224 +
   8.225 +void GoatViewport::initializeGL()
   8.226 +{
   8.227 +}
   8.228 +
   8.229 +void GoatViewport::resizeGL(int xsz, int ysz)
   8.230 +{
   8.231 +	glViewport(0, 0, xsz, ysz);
   8.232 +}
   8.233 +
   8.234 +void GoatViewport::paintGL()
   8.235 +{
   8.236 +	glClearColor(1, 0, 0, 1);
   8.237 +	glClear(GL_COLOR_BUFFER_BIT);
   8.238 +}
     9.1 --- a/goatview/src/goatview.h	Tue May 06 03:31:35 2014 +0300
     9.2 +++ b/goatview/src/goatview.h	Tue May 06 03:57:11 2014 +0300
     9.3 @@ -1,36 +1,36 @@
     9.4 -#ifndef GOATVIEW_H_
     9.5 -#define GOATVIEW_H_
     9.6 -
     9.7 -#include <QtWidgets/QtWidgets>
     9.8 -#include <QtOpenGL/QGLWidget>
     9.9 -
    9.10 -class GoatView : public QMainWindow {
    9.11 -	Q_OBJECT
    9.12 -private:
    9.13 -	bool make_menu();
    9.14 -	bool make_dock();
    9.15 -	bool make_center();
    9.16 -
    9.17 -private slots:
    9.18 -	void open_scene();
    9.19 -	void open_anim();
    9.20 -
    9.21 -public:
    9.22 -	GoatView();
    9.23 -	~GoatView();
    9.24 -};
    9.25 -
    9.26 -class GoatViewport : public QGLWidget {
    9.27 -	Q_OBJECT
    9.28 -public:
    9.29 -	GoatViewport();
    9.30 -	~GoatViewport();
    9.31 -
    9.32 -	QSize sizeHint() const;
    9.33 -
    9.34 -	void initializeGL();
    9.35 -	void resizeGL(int xsz, int ysz);
    9.36 -	void paintGL();
    9.37 -};
    9.38 -
    9.39 -#endif	// GOATVIEW_H_
    9.40 \ No newline at end of file
    9.41 +#ifndef GOATVIEW_H_
    9.42 +#define GOATVIEW_H_
    9.43 +
    9.44 +#include <QtWidgets/QtWidgets>
    9.45 +#include <QtOpenGL/QGLWidget>
    9.46 +
    9.47 +class GoatView : public QMainWindow {
    9.48 +	Q_OBJECT
    9.49 +private:
    9.50 +	bool make_menu();
    9.51 +	bool make_dock();
    9.52 +	bool make_center();
    9.53 +
    9.54 +private slots:
    9.55 +	void open_scene();
    9.56 +	void open_anim();
    9.57 +
    9.58 +public:
    9.59 +	GoatView();
    9.60 +	~GoatView();
    9.61 +};
    9.62 +
    9.63 +class GoatViewport : public QGLWidget {
    9.64 +	Q_OBJECT
    9.65 +public:
    9.66 +	GoatViewport();
    9.67 +	~GoatViewport();
    9.68 +
    9.69 +	QSize sizeHint() const;
    9.70 +
    9.71 +	void initializeGL();
    9.72 +	void resizeGL(int xsz, int ysz);
    9.73 +	void paintGL();
    9.74 +};
    9.75 +
    9.76 +#endif	// GOATVIEW_H_
    10.1 --- a/goatview/src/main.cc	Tue May 06 03:31:35 2014 +0300
    10.2 +++ b/goatview/src/main.cc	Tue May 06 03:57:11 2014 +0300
    10.3 @@ -1,12 +1,12 @@
    10.4 -#include <QtWidgets/QtWidgets>
    10.5 -#include "goatview.h"
    10.6 -
    10.7 -int main(int argc, char **argv)
    10.8 -{
    10.9 -	QApplication app(argc, argv);
   10.10 -
   10.11 -	GoatView gview;
   10.12 -	gview.show();
   10.13 -
   10.14 -	return app.exec();
   10.15 -}
   10.16 \ No newline at end of file
   10.17 +#include <QtWidgets/QtWidgets>
   10.18 +#include "goatview.h"
   10.19 +
   10.20 +int main(int argc, char **argv)
   10.21 +{
   10.22 +	QApplication app(argc, argv);
   10.23 +
   10.24 +	GoatView gview;
   10.25 +	gview.show();
   10.26 +
   10.27 +	return app.exec();
   10.28 +}
    11.1 --- a/libs/tinyxml2/tinyxml2.h	Tue May 06 03:31:35 2014 +0300
    11.2 +++ b/libs/tinyxml2/tinyxml2.h	Tue May 06 03:57:11 2014 +0300
    11.3 @@ -1,1987 +1,1987 @@
    11.4 -/*
    11.5 -Original code by Lee Thomason (www.grinninglizard.com)
    11.6 -
    11.7 -This software is provided 'as-is', without any express or implied
    11.8 -warranty. In no event will the authors be held liable for any
    11.9 -damages arising from the use of this software.
   11.10 -
   11.11 -Permission is granted to anyone to use this software for any
   11.12 -purpose, including commercial applications, and to alter it and
   11.13 -redistribute it freely, subject to the following restrictions:
   11.14 -
   11.15 -1. The origin of this software must not be misrepresented; you must
   11.16 -not claim that you wrote the original software. If you use this
   11.17 -software in a product, an acknowledgment in the product documentation
   11.18 -would be appreciated but is not required.
   11.19 -
   11.20 -
   11.21 -2. Altered source versions must be plainly marked as such, and
   11.22 -must not be misrepresented as being the original software.
   11.23 -
   11.24 -3. This notice may not be removed or altered from any source
   11.25 -distribution.
   11.26 -*/
   11.27 -
   11.28 -#ifndef TINYXML2_INCLUDED
   11.29 -#define TINYXML2_INCLUDED
   11.30 -
   11.31 -#if defined(ANDROID_NDK) || defined(__BORLANDC__)
   11.32 -#   include <ctype.h>
   11.33 -#   include <limits.h>
   11.34 -#   include <stdio.h>
   11.35 -#   include <stdlib.h>
   11.36 -#   include <string.h>
   11.37 -#   include <stdarg.h>
   11.38 -#else
   11.39 -#   include <cctype>
   11.40 -#   include <climits>
   11.41 -#   include <cstdio>
   11.42 -#   include <cstdlib>
   11.43 -#   include <cstring>
   11.44 -#   include <cstdarg>
   11.45 -#endif
   11.46 -
   11.47 -/*
   11.48 -   TODO: intern strings instead of allocation.
   11.49 -*/
   11.50 -/*
   11.51 -	gcc:
   11.52 -        g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
   11.53 -
   11.54 -    Formatting, Artistic Style:
   11.55 -        AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
   11.56 -*/
   11.57 -
   11.58 -#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
   11.59 -#   ifndef DEBUG
   11.60 -#       define DEBUG
   11.61 -#   endif
   11.62 -#endif
   11.63 -
   11.64 -#ifdef _MSC_VER
   11.65 -#   pragma warning(push)
   11.66 -#   pragma warning(disable: 4251)
   11.67 -#endif
   11.68 -
   11.69 -#ifdef _WIN32
   11.70 -#   ifdef TINYXML2_EXPORT
   11.71 -#       define TINYXML2_LIB __declspec(dllexport)
   11.72 -#   elif defined(TINYXML2_IMPORT)
   11.73 -#       define TINYXML2_LIB __declspec(dllimport)
   11.74 -#   else
   11.75 -#       define TINYXML2_LIB
   11.76 -#   endif
   11.77 -#else
   11.78 -#   define TINYXML2_LIB
   11.79 -#endif
   11.80 -
   11.81 -
   11.82 -#if defined(DEBUG)
   11.83 -#   if defined(_MSC_VER)
   11.84 -#       define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
   11.85 -#   elif defined (ANDROID_NDK)
   11.86 -#       include <android/log.h>
   11.87 -#       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
   11.88 -#   else
   11.89 -#       include <assert.h>
   11.90 -#       define TIXMLASSERT                assert
   11.91 -#   endif
   11.92 -#   else
   11.93 -#       define TIXMLASSERT( x )           {}
   11.94 -#endif
   11.95 -
   11.96 -
   11.97 -#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
   11.98 -// Microsoft visual studio, version 2005 and higher.
   11.99 -/*int _snprintf_s(
  11.100 -   char *buffer,
  11.101 -   size_t sizeOfBuffer,
  11.102 -   size_t count,
  11.103 -   const char *format [,
  11.104 -	  argument] ...
  11.105 -);*/
  11.106 -inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
  11.107 -{
  11.108 -    va_list va;
  11.109 -    va_start( va, format );
  11.110 -    int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
  11.111 -    va_end( va );
  11.112 -    return result;
  11.113 -}
  11.114 -#define TIXML_SSCANF   sscanf_s
  11.115 -#else
  11.116 -// GCC version 3 and higher
  11.117 -//#warning( "Using sn* functions." )
  11.118 -#define TIXML_SNPRINTF snprintf
  11.119 -#define TIXML_SSCANF   sscanf
  11.120 -#endif
  11.121 -
  11.122 -static const int TIXML2_MAJOR_VERSION = 1;
  11.123 -static const int TIXML2_MINOR_VERSION = 0;
  11.124 -static const int TIXML2_PATCH_VERSION = 11;
  11.125 -
  11.126 -namespace tinyxml2
  11.127 -{
  11.128 -class XMLDocument;
  11.129 -class XMLElement;
  11.130 -class XMLAttribute;
  11.131 -class XMLComment;
  11.132 -class XMLText;
  11.133 -class XMLDeclaration;
  11.134 -class XMLUnknown;
  11.135 -class XMLPrinter;
  11.136 -
  11.137 -/*
  11.138 -	A class that wraps strings. Normally stores the start and end
  11.139 -	pointers into the XML file itself, and will apply normalization
  11.140 -	and entity translation if actually read. Can also store (and memory
  11.141 -	manage) a traditional char[]
  11.142 -*/
  11.143 -class StrPair
  11.144 -{
  11.145 -public:
  11.146 -    enum {
  11.147 -        NEEDS_ENTITY_PROCESSING			= 0x01,
  11.148 -        NEEDS_NEWLINE_NORMALIZATION		= 0x02,
  11.149 -        COLLAPSE_WHITESPACE	                = 0x04,
  11.150 -
  11.151 -        TEXT_ELEMENT		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
  11.152 -        TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
  11.153 -        ATTRIBUTE_NAME		            	= 0,
  11.154 -        ATTRIBUTE_VALUE		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
  11.155 -        ATTRIBUTE_VALUE_LEAVE_ENTITIES  	= NEEDS_NEWLINE_NORMALIZATION,
  11.156 -        COMMENT				        = NEEDS_NEWLINE_NORMALIZATION
  11.157 -    };
  11.158 -
  11.159 -    StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
  11.160 -    ~StrPair();
  11.161 -
  11.162 -    void Set( char* start, char* end, int flags ) {
  11.163 -        Reset();
  11.164 -        _start  = start;
  11.165 -        _end    = end;
  11.166 -        _flags  = flags | NEEDS_FLUSH;
  11.167 -    }
  11.168 -
  11.169 -    const char* GetStr();
  11.170 -
  11.171 -    bool Empty() const {
  11.172 -        return _start == _end;
  11.173 -    }
  11.174 -
  11.175 -    void SetInternedStr( const char* str ) {
  11.176 -        Reset();
  11.177 -        _start = const_cast<char*>(str);
  11.178 -    }
  11.179 -
  11.180 -    void SetStr( const char* str, int flags=0 );
  11.181 -
  11.182 -    char* ParseText( char* in, const char* endTag, int strFlags );
  11.183 -    char* ParseName( char* in );
  11.184 -
  11.185 -private:
  11.186 -    void Reset();
  11.187 -    void CollapseWhitespace();
  11.188 -
  11.189 -    enum {
  11.190 -        NEEDS_FLUSH = 0x100,
  11.191 -        NEEDS_DELETE = 0x200
  11.192 -    };
  11.193 -
  11.194 -    // After parsing, if *_end != 0, it can be set to zero.
  11.195 -    int     _flags;
  11.196 -    char*   _start;
  11.197 -    char*   _end;
  11.198 -};
  11.199 -
  11.200 -
  11.201 -/*
  11.202 -	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
  11.203 -	Has a small initial memory pool, so that low or no usage will not
  11.204 -	cause a call to new/delete
  11.205 -*/
  11.206 -template <class T, int INIT>
  11.207 -class DynArray
  11.208 -{
  11.209 -public:
  11.210 -    DynArray< T, INIT >() {
  11.211 -        _mem = _pool;
  11.212 -        _allocated = INIT;
  11.213 -        _size = 0;
  11.214 -    }
  11.215 -
  11.216 -    ~DynArray() {
  11.217 -        if ( _mem != _pool ) {
  11.218 -            delete [] _mem;
  11.219 -        }
  11.220 -    }
  11.221 -
  11.222 -    void Push( T t ) {
  11.223 -        EnsureCapacity( _size+1 );
  11.224 -        _mem[_size++] = t;
  11.225 -    }
  11.226 -
  11.227 -    T* PushArr( int count ) {
  11.228 -        EnsureCapacity( _size+count );
  11.229 -        T* ret = &_mem[_size];
  11.230 -        _size += count;
  11.231 -        return ret;
  11.232 -    }
  11.233 -
  11.234 -    T Pop() {
  11.235 -        return _mem[--_size];
  11.236 -    }
  11.237 -
  11.238 -    void PopArr( int count ) {
  11.239 -        TIXMLASSERT( _size >= count );
  11.240 -        _size -= count;
  11.241 -    }
  11.242 -
  11.243 -    bool Empty() const					{
  11.244 -        return _size == 0;
  11.245 -    }
  11.246 -
  11.247 -    T& operator[](int i)				{
  11.248 -        TIXMLASSERT( i>= 0 && i < _size );
  11.249 -        return _mem[i];
  11.250 -    }
  11.251 -
  11.252 -    const T& operator[](int i) const	{
  11.253 -        TIXMLASSERT( i>= 0 && i < _size );
  11.254 -        return _mem[i];
  11.255 -    }
  11.256 -
  11.257 -    int Size() const					{
  11.258 -        return _size;
  11.259 -    }
  11.260 -
  11.261 -    int Capacity() const				{
  11.262 -        return _allocated;
  11.263 -    }
  11.264 -
  11.265 -    const T* Mem() const				{
  11.266 -        return _mem;
  11.267 -    }
  11.268 -
  11.269 -    T* Mem()							{
  11.270 -        return _mem;
  11.271 -    }
  11.272 -
  11.273 -private:
  11.274 -    void EnsureCapacity( int cap ) {
  11.275 -        if ( cap > _allocated ) {
  11.276 -            int newAllocated = cap * 2;
  11.277 -            T* newMem = new T[newAllocated];
  11.278 -            memcpy( newMem, _mem, sizeof(T)*_size );	// warning: not using constructors, only works for PODs
  11.279 -            if ( _mem != _pool ) {
  11.280 -                delete [] _mem;
  11.281 -            }
  11.282 -            _mem = newMem;
  11.283 -            _allocated = newAllocated;
  11.284 -        }
  11.285 -    }
  11.286 -
  11.287 -    T*  _mem;
  11.288 -    T   _pool[INIT];
  11.289 -    int _allocated;		// objects allocated
  11.290 -    int _size;			// number objects in use
  11.291 -};
  11.292 -
  11.293 -
  11.294 -/*
  11.295 -	Parent virtual class of a pool for fast allocation
  11.296 -	and deallocation of objects.
  11.297 -*/
  11.298 -class MemPool
  11.299 -{
  11.300 -public:
  11.301 -    MemPool() {}
  11.302 -    virtual ~MemPool() {}
  11.303 -
  11.304 -    virtual int ItemSize() const = 0;
  11.305 -    virtual void* Alloc() = 0;
  11.306 -    virtual void Free( void* ) = 0;
  11.307 -    virtual void SetTracked() = 0;
  11.308 -};
  11.309 -
  11.310 -
  11.311 -/*
  11.312 -	Template child class to create pools of the correct type.
  11.313 -*/
  11.314 -template< int SIZE >
  11.315 -class MemPoolT : public MemPool
  11.316 -{
  11.317 -public:
  11.318 -    MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
  11.319 -    ~MemPoolT() {
  11.320 -        // Delete the blocks.
  11.321 -        for( int i=0; i<_blockPtrs.Size(); ++i ) {
  11.322 -            delete _blockPtrs[i];
  11.323 -        }
  11.324 -    }
  11.325 -
  11.326 -    virtual int ItemSize() const	{
  11.327 -        return SIZE;
  11.328 -    }
  11.329 -    int CurrentAllocs() const		{
  11.330 -        return _currentAllocs;
  11.331 -    }
  11.332 -
  11.333 -    virtual void* Alloc() {
  11.334 -        if ( !_root ) {
  11.335 -            // Need a new block.
  11.336 -            Block* block = new Block();
  11.337 -            _blockPtrs.Push( block );
  11.338 -
  11.339 -            for( int i=0; i<COUNT-1; ++i ) {
  11.340 -                block->chunk[i].next = &block->chunk[i+1];
  11.341 -            }
  11.342 -            block->chunk[COUNT-1].next = 0;
  11.343 -            _root = block->chunk;
  11.344 -        }
  11.345 -        void* result = _root;
  11.346 -        _root = _root->next;
  11.347 -
  11.348 -        ++_currentAllocs;
  11.349 -        if ( _currentAllocs > _maxAllocs ) {
  11.350 -            _maxAllocs = _currentAllocs;
  11.351 -        }
  11.352 -        _nAllocs++;
  11.353 -        _nUntracked++;
  11.354 -        return result;
  11.355 -    }
  11.356 -    virtual void Free( void* mem ) {
  11.357 -        if ( !mem ) {
  11.358 -            return;
  11.359 -        }
  11.360 -        --_currentAllocs;
  11.361 -        Chunk* chunk = (Chunk*)mem;
  11.362 -#ifdef DEBUG
  11.363 -        memset( chunk, 0xfe, sizeof(Chunk) );
  11.364 -#endif
  11.365 -        chunk->next = _root;
  11.366 -        _root = chunk;
  11.367 -    }
  11.368 -    void Trace( const char* name ) {
  11.369 -        printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
  11.370 -                name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
  11.371 -    }
  11.372 -
  11.373 -    void SetTracked() {
  11.374 -        _nUntracked--;
  11.375 -    }
  11.376 -
  11.377 -    int Untracked() const {
  11.378 -        return _nUntracked;
  11.379 -    }
  11.380 -
  11.381 -	// This number is perf sensitive. 4k seems like a good tradeoff on my machine.
  11.382 -	// The test file is large, 170k.
  11.383 -	// Release:		VS2010 gcc(no opt)
  11.384 -	//		1k:		4000
  11.385 -	//		2k:		4000
  11.386 -	//		4k:		3900	21000
  11.387 -	//		16k:	5200
  11.388 -	//		32k:	4300
  11.389 -	//		64k:	4000	21000
  11.390 -    enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
  11.391 -
  11.392 -private:
  11.393 -    union Chunk {
  11.394 -        Chunk*  next;
  11.395 -        char    mem[SIZE];
  11.396 -    };
  11.397 -    struct Block {
  11.398 -        Chunk chunk[COUNT];
  11.399 -    };
  11.400 -    DynArray< Block*, 10 > _blockPtrs;
  11.401 -    Chunk* _root;
  11.402 -
  11.403 -    int _currentAllocs;
  11.404 -    int _nAllocs;
  11.405 -    int _maxAllocs;
  11.406 -    int _nUntracked;
  11.407 -};
  11.408 -
  11.409 -
  11.410 -
  11.411 -/**
  11.412 -	Implements the interface to the "Visitor pattern" (see the Accept() method.)
  11.413 -	If you call the Accept() method, it requires being passed a XMLVisitor
  11.414 -	class to handle callbacks. For nodes that contain other nodes (Document, Element)
  11.415 -	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
  11.416 -	are simply called with Visit().
  11.417 -
  11.418 -	If you return 'true' from a Visit method, recursive parsing will continue. If you return
  11.419 -	false, <b>no children of this node or its siblings</b> will be visited.
  11.420 -
  11.421 -	All flavors of Visit methods have a default implementation that returns 'true' (continue
  11.422 -	visiting). You need to only override methods that are interesting to you.
  11.423 -
  11.424 -	Generally Accept() is called on the XMLDocument, although all nodes support visiting.
  11.425 -
  11.426 -	You should never change the document from a callback.
  11.427 -
  11.428 -	@sa XMLNode::Accept()
  11.429 -*/
  11.430 -class TINYXML2_LIB XMLVisitor
  11.431 -{
  11.432 -public:
  11.433 -    virtual ~XMLVisitor() {}
  11.434 -
  11.435 -    /// Visit a document.
  11.436 -    virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{
  11.437 -        return true;
  11.438 -    }
  11.439 -    /// Visit a document.
  11.440 -    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
  11.441 -        return true;
  11.442 -    }
  11.443 -
  11.444 -    /// Visit an element.
  11.445 -    virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{
  11.446 -        return true;
  11.447 -    }
  11.448 -    /// Visit an element.
  11.449 -    virtual bool VisitExit( const XMLElement& /*element*/ )			{
  11.450 -        return true;
  11.451 -    }
  11.452 -
  11.453 -    /// Visit a declaration.
  11.454 -    virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{
  11.455 -        return true;
  11.456 -    }
  11.457 -    /// Visit a text node.
  11.458 -    virtual bool Visit( const XMLText& /*text*/ )					{
  11.459 -        return true;
  11.460 -    }
  11.461 -    /// Visit a comment node.
  11.462 -    virtual bool Visit( const XMLComment& /*comment*/ )				{
  11.463 -        return true;
  11.464 -    }
  11.465 -    /// Visit an unknown node.
  11.466 -    virtual bool Visit( const XMLUnknown& /*unknown*/ )				{
  11.467 -        return true;
  11.468 -    }
  11.469 -};
  11.470 -
  11.471 -
  11.472 -/*
  11.473 -	Utility functionality.
  11.474 -*/
  11.475 -class XMLUtil
  11.476 -{
  11.477 -public:
  11.478 -    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
  11.479 -    // correct, but simple, and usually works.
  11.480 -    static const char* SkipWhiteSpace( const char* p )	{
  11.481 -        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
  11.482 -            ++p;
  11.483 -        }
  11.484 -        return p;
  11.485 -    }
  11.486 -    static char* SkipWhiteSpace( char* p )				{
  11.487 -        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) )		{
  11.488 -            ++p;
  11.489 -        }
  11.490 -        return p;
  11.491 -    }
  11.492 -    static bool IsWhiteSpace( char p )					{
  11.493 -        return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
  11.494 -    }
  11.495 -    
  11.496 -    inline static bool IsNameStartChar( unsigned char ch ) {
  11.497 -        return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
  11.498 -               || ch == ':'
  11.499 -               || ch == '_';
  11.500 -    }
  11.501 -    
  11.502 -    inline static bool IsNameChar( unsigned char ch ) {
  11.503 -        return IsNameStartChar( ch )
  11.504 -               || isdigit( ch )
  11.505 -               || ch == '.'
  11.506 -               || ch == '-';
  11.507 -    }
  11.508 -
  11.509 -    inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
  11.510 -        int n = 0;
  11.511 -        if ( p == q ) {
  11.512 -            return true;
  11.513 -        }
  11.514 -        while( *p && *q && *p == *q && n<nChar ) {
  11.515 -            ++p;
  11.516 -            ++q;
  11.517 -            ++n;
  11.518 -        }
  11.519 -        if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
  11.520 -            return true;
  11.521 -        }
  11.522 -        return false;
  11.523 -    }
  11.524 -    
  11.525 -    inline static int IsUTF8Continuation( const char p ) {
  11.526 -        return p & 0x80;
  11.527 -    }
  11.528 -
  11.529 -    static const char* ReadBOM( const char* p, bool* hasBOM );
  11.530 -    // p is the starting location,
  11.531 -    // the UTF-8 value of the entity will be placed in value, and length filled in.
  11.532 -    static const char* GetCharacterRef( const char* p, char* value, int* length );
  11.533 -    static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
  11.534 -
  11.535 -    // converts primitive types to strings
  11.536 -    static void ToStr( int v, char* buffer, int bufferSize );
  11.537 -    static void ToStr( unsigned v, char* buffer, int bufferSize );
  11.538 -    static void ToStr( bool v, char* buffer, int bufferSize );
  11.539 -    static void ToStr( float v, char* buffer, int bufferSize );
  11.540 -    static void ToStr( double v, char* buffer, int bufferSize );
  11.541 -
  11.542 -    // converts strings to primitive types
  11.543 -    static bool	ToInt( const char* str, int* value );
  11.544 -    static bool ToUnsigned( const char* str, unsigned* value );
  11.545 -    static bool	ToBool( const char* str, bool* value );
  11.546 -    static bool	ToFloat( const char* str, float* value );
  11.547 -    static bool ToDouble( const char* str, double* value );
  11.548 -};
  11.549 -
  11.550 -
  11.551 -/** XMLNode is a base class for every object that is in the
  11.552 -	XML Document Object Model (DOM), except XMLAttributes.
  11.553 -	Nodes have siblings, a parent, and children which can
  11.554 -	be navigated. A node is always in a XMLDocument.
  11.555 -	The type of a XMLNode can be queried, and it can
  11.556 -	be cast to its more defined type.
  11.557 -
  11.558 -	A XMLDocument allocates memory for all its Nodes.
  11.559 -	When the XMLDocument gets deleted, all its Nodes
  11.560 -	will also be deleted.
  11.561 -
  11.562 -	@verbatim
  11.563 -	A Document can contain:	Element	(container or leaf)
  11.564 -							Comment (leaf)
  11.565 -							Unknown (leaf)
  11.566 -							Declaration( leaf )
  11.567 -
  11.568 -	An Element can contain:	Element (container or leaf)
  11.569 -							Text	(leaf)
  11.570 -							Attributes (not on tree)
  11.571 -							Comment (leaf)
  11.572 -							Unknown (leaf)
  11.573 -
  11.574 -	@endverbatim
  11.575 -*/
  11.576 -class TINYXML2_LIB XMLNode
  11.577 -{
  11.578 -    friend class XMLDocument;
  11.579 -    friend class XMLElement;
  11.580 -public:
  11.581 -
  11.582 -    /// Get the XMLDocument that owns this XMLNode.
  11.583 -    const XMLDocument* GetDocument() const	{
  11.584 -        return _document;
  11.585 -    }
  11.586 -    /// Get the XMLDocument that owns this XMLNode.
  11.587 -    XMLDocument* GetDocument()				{
  11.588 -        return _document;
  11.589 -    }
  11.590 -
  11.591 -    /// Safely cast to an Element, or null.
  11.592 -    virtual XMLElement*		ToElement()		{
  11.593 -        return 0;
  11.594 -    }
  11.595 -    /// Safely cast to Text, or null.
  11.596 -    virtual XMLText*		ToText()		{
  11.597 -        return 0;
  11.598 -    }
  11.599 -    /// Safely cast to a Comment, or null.
  11.600 -    virtual XMLComment*		ToComment()		{
  11.601 -        return 0;
  11.602 -    }
  11.603 -    /// Safely cast to a Document, or null.
  11.604 -    virtual XMLDocument*	ToDocument()	{
  11.605 -        return 0;
  11.606 -    }
  11.607 -    /// Safely cast to a Declaration, or null.
  11.608 -    virtual XMLDeclaration*	ToDeclaration()	{
  11.609 -        return 0;
  11.610 -    }
  11.611 -    /// Safely cast to an Unknown, or null.
  11.612 -    virtual XMLUnknown*		ToUnknown()		{
  11.613 -        return 0;
  11.614 -    }
  11.615 -
  11.616 -    virtual const XMLElement*		ToElement() const		{
  11.617 -        return 0;
  11.618 -    }
  11.619 -    virtual const XMLText*			ToText() const			{
  11.620 -        return 0;
  11.621 -    }
  11.622 -    virtual const XMLComment*		ToComment() const		{
  11.623 -        return 0;
  11.624 -    }
  11.625 -    virtual const XMLDocument*		ToDocument() const		{
  11.626 -        return 0;
  11.627 -    }
  11.628 -    virtual const XMLDeclaration*	ToDeclaration() const	{
  11.629 -        return 0;
  11.630 -    }
  11.631 -    virtual const XMLUnknown*		ToUnknown() const		{
  11.632 -        return 0;
  11.633 -    }
  11.634 -
  11.635 -    /** The meaning of 'value' changes for the specific type.
  11.636 -    	@verbatim
  11.637 -    	Document:	empty
  11.638 -    	Element:	name of the element
  11.639 -    	Comment:	the comment text
  11.640 -    	Unknown:	the tag contents
  11.641 -    	Text:		the text string
  11.642 -    	@endverbatim
  11.643 -    */
  11.644 -    const char* Value() const			{
  11.645 -        return _value.GetStr();
  11.646 -    }
  11.647 -
  11.648 -    /** Set the Value of an XML node.
  11.649 -    	@sa Value()
  11.650 -    */
  11.651 -    void SetValue( const char* val, bool staticMem=false );
  11.652 -
  11.653 -    /// Get the parent of this node on the DOM.
  11.654 -    const XMLNode*	Parent() const			{
  11.655 -        return _parent;
  11.656 -    }
  11.657 -
  11.658 -    XMLNode* Parent()						{
  11.659 -        return _parent;
  11.660 -    }
  11.661 -
  11.662 -    /// Returns true if this node has no children.
  11.663 -    bool NoChildren() const					{
  11.664 -        return !_firstChild;
  11.665 -    }
  11.666 -
  11.667 -    /// Get the first child node, or null if none exists.
  11.668 -    const XMLNode*  FirstChild() const		{
  11.669 -        return _firstChild;
  11.670 -    }
  11.671 -
  11.672 -    XMLNode*		FirstChild()			{
  11.673 -        return _firstChild;
  11.674 -    }
  11.675 -
  11.676 -    /** Get the first child element, or optionally the first child
  11.677 -        element with the specified name.
  11.678 -    */
  11.679 -    const XMLElement* FirstChildElement( const char* value=0 ) const;
  11.680 -
  11.681 -    XMLElement* FirstChildElement( const char* value=0 )	{
  11.682 -        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
  11.683 -    }
  11.684 -
  11.685 -    /// Get the last child node, or null if none exists.
  11.686 -    const XMLNode*	LastChild() const						{
  11.687 -        return _lastChild;
  11.688 -    }
  11.689 -
  11.690 -    XMLNode*		LastChild()								{
  11.691 -        return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
  11.692 -    }
  11.693 -
  11.694 -    /** Get the last child element or optionally the last child
  11.695 -        element with the specified name.
  11.696 -    */
  11.697 -    const XMLElement* LastChildElement( const char* value=0 ) const;
  11.698 -
  11.699 -    XMLElement* LastChildElement( const char* value=0 )	{
  11.700 -        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
  11.701 -    }
  11.702 -
  11.703 -    /// Get the previous (left) sibling node of this node.
  11.704 -    const XMLNode*	PreviousSibling() const					{
  11.705 -        return _prev;
  11.706 -    }
  11.707 -
  11.708 -    XMLNode*	PreviousSibling()							{
  11.709 -        return _prev;
  11.710 -    }
  11.711 -
  11.712 -    /// Get the previous (left) sibling element of this node, with an optionally supplied name.
  11.713 -    const XMLElement*	PreviousSiblingElement( const char* value=0 ) const ;
  11.714 -
  11.715 -    XMLElement*	PreviousSiblingElement( const char* value=0 ) {
  11.716 -        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
  11.717 -    }
  11.718 -
  11.719 -    /// Get the next (right) sibling node of this node.
  11.720 -    const XMLNode*	NextSibling() const						{
  11.721 -        return _next;
  11.722 -    }
  11.723 -
  11.724 -    XMLNode*	NextSibling()								{
  11.725 -        return _next;
  11.726 -    }
  11.727 -
  11.728 -    /// Get the next (right) sibling element of this node, with an optionally supplied name.
  11.729 -    const XMLElement*	NextSiblingElement( const char* value=0 ) const;
  11.730 -
  11.731 -    XMLElement*	NextSiblingElement( const char* value=0 )	{
  11.732 -        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
  11.733 -    }
  11.734 -
  11.735 -    /**
  11.736 -    	Add a child node as the last (right) child.
  11.737 -    */
  11.738 -    XMLNode* InsertEndChild( XMLNode* addThis );
  11.739 -
  11.740 -    XMLNode* LinkEndChild( XMLNode* addThis )	{
  11.741 -        return InsertEndChild( addThis );
  11.742 -    }
  11.743 -    /**
  11.744 -    	Add a child node as the first (left) child.
  11.745 -    */
  11.746 -    XMLNode* InsertFirstChild( XMLNode* addThis );
  11.747 -    /**
  11.748 -    	Add a node after the specified child node.
  11.749 -    */
  11.750 -    XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
  11.751 -
  11.752 -    /**
  11.753 -    	Delete all the children of this node.
  11.754 -    */
  11.755 -    void DeleteChildren();
  11.756 -
  11.757 -    /**
  11.758 -    	Delete a child of this node.
  11.759 -    */
  11.760 -    void DeleteChild( XMLNode* node );
  11.761 -
  11.762 -    /**
  11.763 -    	Make a copy of this node, but not its children.
  11.764 -    	You may pass in a Document pointer that will be
  11.765 -    	the owner of the new Node. If the 'document' is
  11.766 -    	null, then the node returned will be allocated
  11.767 -    	from the current Document. (this->GetDocument())
  11.768 -
  11.769 -    	Note: if called on a XMLDocument, this will return null.
  11.770 -    */
  11.771 -    virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
  11.772 -
  11.773 -    /**
  11.774 -    	Test if 2 nodes are the same, but don't test children.
  11.775 -    	The 2 nodes do not need to be in the same Document.
  11.776 -
  11.777 -    	Note: if called on a XMLDocument, this will return false.
  11.778 -    */
  11.779 -    virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
  11.780 -
  11.781 -    /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
  11.782 -    	XML tree will be conditionally visited and the host will be called back
  11.783 -    	via the XMLVisitor interface.
  11.784 -
  11.785 -    	This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
  11.786 -    	the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
  11.787 -    	interface versus any other.)
  11.788 -
  11.789 -    	The interface has been based on ideas from:
  11.790 -
  11.791 -    	- http://www.saxproject.org/
  11.792 -    	- http://c2.com/cgi/wiki?HierarchicalVisitorPattern
  11.793 -
  11.794 -    	Which are both good references for "visiting".
  11.795 -
  11.796 -    	An example of using Accept():
  11.797 -    	@verbatim
  11.798 -    	XMLPrinter printer;
  11.799 -    	tinyxmlDoc.Accept( &printer );
  11.800 -    	const char* xmlcstr = printer.CStr();
  11.801 -    	@endverbatim
  11.802 -    */
  11.803 -    virtual bool Accept( XMLVisitor* visitor ) const = 0;
  11.804 -
  11.805 -    // internal
  11.806 -    virtual char* ParseDeep( char*, StrPair* );
  11.807 -
  11.808 -protected:
  11.809 -    XMLNode( XMLDocument* );
  11.810 -    virtual ~XMLNode();
  11.811 -    XMLNode( const XMLNode& );	// not supported
  11.812 -    XMLNode& operator=( const XMLNode& );	// not supported
  11.813 -
  11.814 -    XMLDocument*	_document;
  11.815 -    XMLNode*		_parent;
  11.816 -    mutable StrPair	_value;
  11.817 -
  11.818 -    XMLNode*		_firstChild;
  11.819 -    XMLNode*		_lastChild;
  11.820 -
  11.821 -    XMLNode*		_prev;
  11.822 -    XMLNode*		_next;
  11.823 -
  11.824 -private:
  11.825 -    MemPool*		_memPool;
  11.826 -    void Unlink( XMLNode* child );
  11.827 -};
  11.828 -
  11.829 -
  11.830 -/** XML text.
  11.831 -
  11.832 -	Note that a text node can have child element nodes, for example:
  11.833 -	@verbatim
  11.834 -	<root>This is <b>bold</b></root>
  11.835 -	@endverbatim
  11.836 -
  11.837 -	A text node can have 2 ways to output the next. "normal" output
  11.838 -	and CDATA. It will default to the mode it was parsed from the XML file and
  11.839 -	you generally want to leave it alone, but you can change the output mode with
  11.840 -	SetCData() and query it with CData().
  11.841 -*/
  11.842 -class TINYXML2_LIB XMLText : public XMLNode
  11.843 -{
  11.844 -    friend class XMLBase;
  11.845 -    friend class XMLDocument;
  11.846 -public:
  11.847 -    virtual bool Accept( XMLVisitor* visitor ) const;
  11.848 -
  11.849 -    virtual XMLText* ToText()			{
  11.850 -        return this;
  11.851 -    }
  11.852 -    virtual const XMLText* ToText() const	{
  11.853 -        return this;
  11.854 -    }
  11.855 -
  11.856 -    /// Declare whether this should be CDATA or standard text.
  11.857 -    void SetCData( bool isCData )			{
  11.858 -        _isCData = isCData;
  11.859 -    }
  11.860 -    /// Returns true if this is a CDATA text element.
  11.861 -    bool CData() const						{
  11.862 -        return _isCData;
  11.863 -    }
  11.864 -
  11.865 -    char* ParseDeep( char*, StrPair* endTag );
  11.866 -    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
  11.867 -    virtual bool ShallowEqual( const XMLNode* compare ) const;
  11.868 -
  11.869 -protected:
  11.870 -    XMLText( XMLDocument* doc )	: XMLNode( doc ), _isCData( false )	{}
  11.871 -    virtual ~XMLText()												{}
  11.872 -    XMLText( const XMLText& );	// not supported
  11.873 -    XMLText& operator=( const XMLText& );	// not supported
  11.874 -
  11.875 -private:
  11.876 -    bool _isCData;
  11.877 -};
  11.878 -
  11.879 -
  11.880 -/** An XML Comment. */
  11.881 -class TINYXML2_LIB XMLComment : public XMLNode
  11.882 -{
  11.883 -    friend class XMLDocument;
  11.884 -public:
  11.885 -    virtual XMLComment*	ToComment()					{
  11.886 -        return this;
  11.887 -    }
  11.888 -    virtual const XMLComment* ToComment() const		{
  11.889 -        return this;
  11.890 -    }
  11.891 -
  11.892 -    virtual bool Accept( XMLVisitor* visitor ) const;
  11.893 -
  11.894 -    char* ParseDeep( char*, StrPair* endTag );
  11.895 -    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
  11.896 -    virtual bool ShallowEqual( const XMLNode* compare ) const;
  11.897 -
  11.898 -protected:
  11.899 -    XMLComment( XMLDocument* doc );
  11.900 -    virtual ~XMLComment();
  11.901 -    XMLComment( const XMLComment& );	// not supported
  11.902 -    XMLComment& operator=( const XMLComment& );	// not supported
  11.903 -
  11.904 -private:
  11.905 -};
  11.906 -
  11.907 -
  11.908 -/** In correct XML the declaration is the first entry in the file.
  11.909 -	@verbatim
  11.910 -		<?xml version="1.0" standalone="yes"?>
  11.911 -	@endverbatim
  11.912 -
  11.913 -	TinyXML-2 will happily read or write files without a declaration,
  11.914 -	however.
  11.915 -
  11.916 -	The text of the declaration isn't interpreted. It is parsed
  11.917 -	and written as a string.
  11.918 -*/
  11.919 -class TINYXML2_LIB XMLDeclaration : public XMLNode
  11.920 -{
  11.921 -    friend class XMLDocument;
  11.922 -public:
  11.923 -    virtual XMLDeclaration*	ToDeclaration()					{
  11.924 -        return this;
  11.925 -    }
  11.926 -    virtual const XMLDeclaration* ToDeclaration() const		{
  11.927 -        return this;
  11.928 -    }
  11.929 -
  11.930 -    virtual bool Accept( XMLVisitor* visitor ) const;
  11.931 -
  11.932 -    char* ParseDeep( char*, StrPair* endTag );
  11.933 -    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
  11.934 -    virtual bool ShallowEqual( const XMLNode* compare ) const;
  11.935 -
  11.936 -protected:
  11.937 -    XMLDeclaration( XMLDocument* doc );
  11.938 -    virtual ~XMLDeclaration();
  11.939 -    XMLDeclaration( const XMLDeclaration& );	// not supported
  11.940 -    XMLDeclaration& operator=( const XMLDeclaration& );	// not supported
  11.941 -};
  11.942 -
  11.943 -
  11.944 -/** Any tag that TinyXML-2 doesn't recognize is saved as an
  11.945 -	unknown. It is a tag of text, but should not be modified.
  11.946 -	It will be written back to the XML, unchanged, when the file
  11.947 -	is saved.
  11.948 -
  11.949 -	DTD tags get thrown into XMLUnknowns.
  11.950 -*/
  11.951 -class TINYXML2_LIB XMLUnknown : public XMLNode
  11.952 -{
  11.953 -    friend class XMLDocument;
  11.954 -public:
  11.955 -    virtual XMLUnknown*	ToUnknown()					{
  11.956 -        return this;
  11.957 -    }
  11.958 -    virtual const XMLUnknown* ToUnknown() const		{
  11.959 -        return this;
  11.960 -    }
  11.961 -
  11.962 -    virtual bool Accept( XMLVisitor* visitor ) const;
  11.963 -
  11.964 -    char* ParseDeep( char*, StrPair* endTag );
  11.965 -    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
  11.966 -    virtual bool ShallowEqual( const XMLNode* compare ) const;
  11.967 -
  11.968 -protected:
  11.969 -    XMLUnknown( XMLDocument* doc );
  11.970 -    virtual ~XMLUnknown();
  11.971 -    XMLUnknown( const XMLUnknown& );	// not supported
  11.972 -    XMLUnknown& operator=( const XMLUnknown& );	// not supported
  11.973 -};
  11.974 -
  11.975 -
  11.976 -enum XMLError {
  11.977 -    XML_NO_ERROR = 0,
  11.978 -    XML_SUCCESS = 0,
  11.979 -
  11.980 -    XML_NO_ATTRIBUTE,
  11.981 -    XML_WRONG_ATTRIBUTE_TYPE,
  11.982 -
  11.983 -    XML_ERROR_FILE_NOT_FOUND,
  11.984 -    XML_ERROR_FILE_COULD_NOT_BE_OPENED,
  11.985 -    XML_ERROR_FILE_READ_ERROR,
  11.986 -    XML_ERROR_ELEMENT_MISMATCH,
  11.987 -    XML_ERROR_PARSING_ELEMENT,
  11.988 -    XML_ERROR_PARSING_ATTRIBUTE,
  11.989 -    XML_ERROR_IDENTIFYING_TAG,
  11.990 -    XML_ERROR_PARSING_TEXT,
  11.991 -    XML_ERROR_PARSING_CDATA,
  11.992 -    XML_ERROR_PARSING_COMMENT,
  11.993 -    XML_ERROR_PARSING_DECLARATION,
  11.994 -    XML_ERROR_PARSING_UNKNOWN,
  11.995 -    XML_ERROR_EMPTY_DOCUMENT,
  11.996 -    XML_ERROR_MISMATCHED_ELEMENT,
  11.997 -    XML_ERROR_PARSING,
  11.998 -
  11.999 -    XML_CAN_NOT_CONVERT_TEXT,
 11.1000 -    XML_NO_TEXT_NODE
 11.1001 -};
 11.1002 -
 11.1003 -
 11.1004 -/** An attribute is a name-value pair. Elements have an arbitrary
 11.1005 -	number of attributes, each with a unique name.
 11.1006 -
 11.1007 -	@note The attributes are not XMLNodes. You may only query the
 11.1008 -	Next() attribute in a list.
 11.1009 -*/
 11.1010 -class TINYXML2_LIB XMLAttribute
 11.1011 -{
 11.1012 -    friend class XMLElement;
 11.1013 -public:
 11.1014 -    /// The name of the attribute.
 11.1015 -    const char* Name() const {
 11.1016 -        return _name.GetStr();
 11.1017 -    }
 11.1018 -    /// The value of the attribute.
 11.1019 -    const char* Value() const {
 11.1020 -        return _value.GetStr();
 11.1021 -    }
 11.1022 -    /// The next attribute in the list.
 11.1023 -    const XMLAttribute* Next() const {
 11.1024 -        return _next;
 11.1025 -    }
 11.1026 -
 11.1027 -    /** IntValue interprets the attribute as an integer, and returns the value.
 11.1028 -        If the value isn't an integer, 0 will be returned. There is no error checking;
 11.1029 -    	use QueryIntValue() if you need error checking.
 11.1030 -    */
 11.1031 -    int		 IntValue() const				{
 11.1032 -        int i=0;
 11.1033 -        QueryIntValue( &i );
 11.1034 -        return i;
 11.1035 -    }
 11.1036 -    /// Query as an unsigned integer. See IntValue()
 11.1037 -    unsigned UnsignedValue() const			{
 11.1038 -        unsigned i=0;
 11.1039 -        QueryUnsignedValue( &i );
 11.1040 -        return i;
 11.1041 -    }
 11.1042 -    /// Query as a boolean. See IntValue()
 11.1043 -    bool	 BoolValue() const				{
 11.1044 -        bool b=false;
 11.1045 -        QueryBoolValue( &b );
 11.1046 -        return b;
 11.1047 -    }
 11.1048 -    /// Query as a double. See IntValue()
 11.1049 -    double 	 DoubleValue() const			{
 11.1050 -        double d=0;
 11.1051 -        QueryDoubleValue( &d );
 11.1052 -        return d;
 11.1053 -    }
 11.1054 -    /// Query as a float. See IntValue()
 11.1055 -    float	 FloatValue() const				{
 11.1056 -        float f=0;
 11.1057 -        QueryFloatValue( &f );
 11.1058 -        return f;
 11.1059 -    }
 11.1060 -
 11.1061 -    /** QueryIntValue interprets the attribute as an integer, and returns the value
 11.1062 -    	in the provided parameter. The function will return XML_NO_ERROR on success,
 11.1063 -    	and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
 11.1064 -    */
 11.1065 -    XMLError QueryIntValue( int* value ) const;
 11.1066 -    /// See QueryIntValue
 11.1067 -    XMLError QueryUnsignedValue( unsigned int* value ) const;
 11.1068 -    /// See QueryIntValue
 11.1069 -    XMLError QueryBoolValue( bool* value ) const;
 11.1070 -    /// See QueryIntValue
 11.1071 -    XMLError QueryDoubleValue( double* value ) const;
 11.1072 -    /// See QueryIntValue
 11.1073 -    XMLError QueryFloatValue( float* value ) const;
 11.1074 -
 11.1075 -    /// Set the attribute to a string value.
 11.1076 -    void SetAttribute( const char* value );
 11.1077 -    /// Set the attribute to value.
 11.1078 -    void SetAttribute( int value );
 11.1079 -    /// Set the attribute to value.
 11.1080 -    void SetAttribute( unsigned value );
 11.1081 -    /// Set the attribute to value.
 11.1082 -    void SetAttribute( bool value );
 11.1083 -    /// Set the attribute to value.
 11.1084 -    void SetAttribute( double value );
 11.1085 -    /// Set the attribute to value.
 11.1086 -    void SetAttribute( float value );
 11.1087 -
 11.1088 -private:
 11.1089 -    enum { BUF_SIZE = 200 };
 11.1090 -
 11.1091 -    XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
 11.1092 -    virtual ~XMLAttribute()	{}
 11.1093 -
 11.1094 -    XMLAttribute( const XMLAttribute& );	// not supported
 11.1095 -    void operator=( const XMLAttribute& );	// not supported
 11.1096 -    void SetName( const char* name );
 11.1097 -
 11.1098 -    char* ParseDeep( char* p, bool processEntities );
 11.1099 -
 11.1100 -    mutable StrPair _name;
 11.1101 -    mutable StrPair _value;
 11.1102 -    XMLAttribute*   _next;
 11.1103 -    MemPool*        _memPool;
 11.1104 -};
 11.1105 -
 11.1106 -
 11.1107 -/** The element is a container class. It has a value, the element name,
 11.1108 -	and can contain other elements, text, comments, and unknowns.
 11.1109 -	Elements also contain an arbitrary number of attributes.
 11.1110 -*/
 11.1111 -class TINYXML2_LIB XMLElement : public XMLNode
 11.1112 -{
 11.1113 -    friend class XMLBase;
 11.1114 -    friend class XMLDocument;
 11.1115 -public:
 11.1116 -    /// Get the name of an element (which is the Value() of the node.)
 11.1117 -    const char* Name() const		{
 11.1118 -        return Value();
 11.1119 -    }
 11.1120 -    /// Set the name of the element.
 11.1121 -    void SetName( const char* str, bool staticMem=false )	{
 11.1122 -        SetValue( str, staticMem );
 11.1123 -    }
 11.1124 -
 11.1125 -    virtual XMLElement* ToElement()				{
 11.1126 -        return this;
 11.1127 -    }
 11.1128 -    virtual const XMLElement* ToElement() const {
 11.1129 -        return this;
 11.1130 -    }
 11.1131 -    virtual bool Accept( XMLVisitor* visitor ) const;
 11.1132 -
 11.1133 -    /** Given an attribute name, Attribute() returns the value
 11.1134 -    	for the attribute of that name, or null if none
 11.1135 -    	exists. For example:
 11.1136 -
 11.1137 -    	@verbatim
 11.1138 -    	const char* value = ele->Attribute( "foo" );
 11.1139 -    	@endverbatim
 11.1140 -
 11.1141 -    	The 'value' parameter is normally null. However, if specified,
 11.1142 -    	the attribute will only be returned if the 'name' and 'value'
 11.1143 -    	match. This allow you to write code:
 11.1144 -
 11.1145 -    	@verbatim
 11.1146 -    	if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
 11.1147 -    	@endverbatim
 11.1148 -
 11.1149 -    	rather than:
 11.1150 -    	@verbatim
 11.1151 -    	if ( ele->Attribute( "foo" ) ) {
 11.1152 -    		if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
 11.1153 -    	}
 11.1154 -    	@endverbatim
 11.1155 -    */
 11.1156 -    const char* Attribute( const char* name, const char* value=0 ) const;
 11.1157 -
 11.1158 -    /** Given an attribute name, IntAttribute() returns the value
 11.1159 -    	of the attribute interpreted as an integer. 0 will be
 11.1160 -    	returned if there is an error. For a method with error
 11.1161 -    	checking, see QueryIntAttribute()
 11.1162 -    */
 11.1163 -    int		 IntAttribute( const char* name ) const		{
 11.1164 -        int i=0;
 11.1165 -        QueryIntAttribute( name, &i );
 11.1166 -        return i;
 11.1167 -    }
 11.1168 -    /// See IntAttribute()
 11.1169 -    unsigned UnsignedAttribute( const char* name ) const {
 11.1170 -        unsigned i=0;
 11.1171 -        QueryUnsignedAttribute( name, &i );
 11.1172 -        return i;
 11.1173 -    }
 11.1174 -    /// See IntAttribute()
 11.1175 -    bool	 BoolAttribute( const char* name ) const	{
 11.1176 -        bool b=false;
 11.1177 -        QueryBoolAttribute( name, &b );
 11.1178 -        return b;
 11.1179 -    }
 11.1180 -    /// See IntAttribute()
 11.1181 -    double 	 DoubleAttribute( const char* name ) const	{
 11.1182 -        double d=0;
 11.1183 -        QueryDoubleAttribute( name, &d );
 11.1184 -        return d;
 11.1185 -    }
 11.1186 -    /// See IntAttribute()
 11.1187 -    float	 FloatAttribute( const char* name ) const	{
 11.1188 -        float f=0;
 11.1189 -        QueryFloatAttribute( name, &f );
 11.1190 -        return f;
 11.1191 -    }
 11.1192 -
 11.1193 -    /** Given an attribute name, QueryIntAttribute() returns
 11.1194 -    	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
 11.1195 -    	can't be performed, or XML_NO_ATTRIBUTE if the attribute
 11.1196 -    	doesn't exist. If successful, the result of the conversion
 11.1197 -    	will be written to 'value'. If not successful, nothing will
 11.1198 -    	be written to 'value'. This allows you to provide default
 11.1199 -    	value:
 11.1200 -
 11.1201 -    	@verbatim
 11.1202 -    	int value = 10;
 11.1203 -    	QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
 11.1204 -    	@endverbatim
 11.1205 -    */
 11.1206 -    XMLError QueryIntAttribute( const char* name, int* value ) const				{
 11.1207 -        const XMLAttribute* a = FindAttribute( name );
 11.1208 -        if ( !a ) {
 11.1209 -            return XML_NO_ATTRIBUTE;
 11.1210 -        }
 11.1211 -        return a->QueryIntValue( value );
 11.1212 -    }
 11.1213 -    /// See QueryIntAttribute()
 11.1214 -    XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const	{
 11.1215 -        const XMLAttribute* a = FindAttribute( name );
 11.1216 -        if ( !a ) {
 11.1217 -            return XML_NO_ATTRIBUTE;
 11.1218 -        }
 11.1219 -        return a->QueryUnsignedValue( value );
 11.1220 -    }
 11.1221 -    /// See QueryIntAttribute()
 11.1222 -    XMLError QueryBoolAttribute( const char* name, bool* value ) const				{
 11.1223 -        const XMLAttribute* a = FindAttribute( name );
 11.1224 -        if ( !a ) {
 11.1225 -            return XML_NO_ATTRIBUTE;
 11.1226 -        }
 11.1227 -        return a->QueryBoolValue( value );
 11.1228 -    }
 11.1229 -    /// See QueryIntAttribute()
 11.1230 -    XMLError QueryDoubleAttribute( const char* name, double* value ) const			{
 11.1231 -        const XMLAttribute* a = FindAttribute( name );
 11.1232 -        if ( !a ) {
 11.1233 -            return XML_NO_ATTRIBUTE;
 11.1234 -        }
 11.1235 -        return a->QueryDoubleValue( value );
 11.1236 -    }
 11.1237 -    /// See QueryIntAttribute()
 11.1238 -    XMLError QueryFloatAttribute( const char* name, float* value ) const			{
 11.1239 -        const XMLAttribute* a = FindAttribute( name );
 11.1240 -        if ( !a ) {
 11.1241 -            return XML_NO_ATTRIBUTE;
 11.1242 -        }
 11.1243 -        return a->QueryFloatValue( value );
 11.1244 -    }
 11.1245 -
 11.1246 -	
 11.1247 -    /** Given an attribute name, QueryAttribute() returns
 11.1248 -    	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
 11.1249 -    	can't be performed, or XML_NO_ATTRIBUTE if the attribute
 11.1250 -    	doesn't exist. It is overloaded for the primitive types,
 11.1251 -		and is a generally more convenient replacement of
 11.1252 -		QueryIntAttribute() and related functions.
 11.1253 -		
 11.1254 -		If successful, the result of the conversion
 11.1255 -    	will be written to 'value'. If not successful, nothing will
 11.1256 -    	be written to 'value'. This allows you to provide default
 11.1257 -    	value:
 11.1258 -
 11.1259 -    	@verbatim
 11.1260 -    	int value = 10;
 11.1261 -    	QueryAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
 11.1262 -    	@endverbatim
 11.1263 -    */
 11.1264 -	int QueryAttribute( const char* name, int* value ) const {
 11.1265 -		return QueryIntAttribute( name, value );
 11.1266 -	}
 11.1267 -
 11.1268 -	int QueryAttribute( const char* name, unsigned int* value ) const {
 11.1269 -		return QueryUnsignedAttribute( name, value );
 11.1270 -	}
 11.1271 -
 11.1272 -	int QueryAttribute( const char* name, bool* value ) const {
 11.1273 -		return QueryBoolAttribute( name, value );
 11.1274 -	}
 11.1275 -
 11.1276 -	int QueryAttribute( const char* name, double* value ) const {
 11.1277 -		return QueryDoubleAttribute( name, value );
 11.1278 -	}
 11.1279 -
 11.1280 -	int QueryAttribute( const char* name, float* value ) const {
 11.1281 -		return QueryFloatAttribute( name, value );
 11.1282 -	}
 11.1283 -
 11.1284 -	/// Sets the named attribute to value.
 11.1285 -    void SetAttribute( const char* name, const char* value )	{
 11.1286 -        XMLAttribute* a = FindOrCreateAttribute( name );
 11.1287 -        a->SetAttribute( value );
 11.1288 -    }
 11.1289 -    /// Sets the named attribute to value.
 11.1290 -    void SetAttribute( const char* name, int value )			{
 11.1291 -        XMLAttribute* a = FindOrCreateAttribute( name );
 11.1292 -        a->SetAttribute( value );
 11.1293 -    }
 11.1294 -    /// Sets the named attribute to value.
 11.1295 -    void SetAttribute( const char* name, unsigned value )		{
 11.1296 -        XMLAttribute* a = FindOrCreateAttribute( name );
 11.1297 -        a->SetAttribute( value );
 11.1298 -    }
 11.1299 -    /// Sets the named attribute to value.
 11.1300 -    void SetAttribute( const char* name, bool value )			{
 11.1301 -        XMLAttribute* a = FindOrCreateAttribute( name );
 11.1302 -        a->SetAttribute( value );
 11.1303 -    }
 11.1304 -    /// Sets the named attribute to value.
 11.1305 -    void SetAttribute( const char* name, double value )		{
 11.1306 -        XMLAttribute* a = FindOrCreateAttribute( name );
 11.1307 -        a->SetAttribute( value );
 11.1308 -    }
 11.1309 -
 11.1310 -    /**
 11.1311 -    	Delete an attribute.
 11.1312 -    */
 11.1313 -    void DeleteAttribute( const char* name );
 11.1314 -
 11.1315 -    /// Return the first attribute in the list.
 11.1316 -    const XMLAttribute* FirstAttribute() const {
 11.1317 -        return _rootAttribute;
 11.1318 -    }
 11.1319 -    /// Query a specific attribute in the list.
 11.1320 -    const XMLAttribute* FindAttribute( const char* name ) const;
 11.1321 -
 11.1322 -    /** Convenience function for easy access to the text inside an element. Although easy
 11.1323 -    	and concise, GetText() is limited compared to getting the XMLText child
 11.1324 -    	and accessing it directly.
 11.1325 -
 11.1326 -    	If the first child of 'this' is a XMLText, the GetText()
 11.1327 -    	returns the character string of the Text node, else null is returned.
 11.1328 -
 11.1329 -    	This is a convenient method for getting the text of simple contained text:
 11.1330 -    	@verbatim
 11.1331 -    	<foo>This is text</foo>
 11.1332 -    		const char* str = fooElement->GetText();
 11.1333 -    	@endverbatim
 11.1334 -
 11.1335 -    	'str' will be a pointer to "This is text".
 11.1336 -
 11.1337 -    	Note that this function can be misleading. If the element foo was created from
 11.1338 -    	this XML:
 11.1339 -    	@verbatim
 11.1340 -    		<foo><b>This is text</b></foo>
 11.1341 -    	@endverbatim
 11.1342 -
 11.1343 -    	then the value of str would be null. The first child node isn't a text node, it is
 11.1344 -    	another element. From this XML:
 11.1345 -    	@verbatim
 11.1346 -    		<foo>This is <b>text</b></foo>
 11.1347 -    	@endverbatim
 11.1348 -    	GetText() will return "This is ".
 11.1349 -    */
 11.1350 -    const char* GetText() const;
 11.1351 -
 11.1352 -    /**
 11.1353 -    	Convenience method to query the value of a child text node. This is probably best
 11.1354 -    	shown by example. Given you have a document is this form:
 11.1355 -    	@verbatim
 11.1356 -    		<point>
 11.1357 -    			<x>1</x>
 11.1358 -    			<y>1.4</y>
 11.1359 -    		</point>
 11.1360 -    	@endverbatim
 11.1361 -
 11.1362 -    	The QueryIntText() and similar functions provide a safe and easier way to get to the
 11.1363 -    	"value" of x and y.
 11.1364 -
 11.1365 -    	@verbatim
 11.1366 -    		int x = 0;
 11.1367 -    		float y = 0;	// types of x and y are contrived for example
 11.1368 -    		const XMLElement* xElement = pointElement->FirstChildElement( "x" );
 11.1369 -    		const XMLElement* yElement = pointElement->FirstChildElement( "y" );
 11.1370 -    		xElement->QueryIntText( &x );
 11.1371 -    		yElement->QueryFloatText( &y );
 11.1372 -    	@endverbatim
 11.1373 -
 11.1374 -    	@returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
 11.1375 -    			 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
 11.1376 -
 11.1377 -    */
 11.1378 -    XMLError QueryIntText( int* ival ) const;
 11.1379 -    /// See QueryIntText()
 11.1380 -    XMLError QueryUnsignedText( unsigned* uval ) const;
 11.1381 -    /// See QueryIntText()
 11.1382 -    XMLError QueryBoolText( bool* bval ) const;
 11.1383 -    /// See QueryIntText()
 11.1384 -    XMLError QueryDoubleText( double* dval ) const;
 11.1385 -    /// See QueryIntText()
 11.1386 -    XMLError QueryFloatText( float* fval ) const;
 11.1387 -
 11.1388 -    // internal:
 11.1389 -    enum {
 11.1390 -        OPEN,		// <foo>
 11.1391 -        CLOSED,		// <foo/>
 11.1392 -        CLOSING		// </foo>
 11.1393 -    };
 11.1394 -    int ClosingType() const {
 11.1395 -        return _closingType;
 11.1396 -    }
 11.1397 -    char* ParseDeep( char* p, StrPair* endTag );
 11.1398 -    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
 11.1399 -    virtual bool ShallowEqual( const XMLNode* compare ) const;
 11.1400 -
 11.1401 -private:
 11.1402 -    XMLElement( XMLDocument* doc );
 11.1403 -    virtual ~XMLElement();
 11.1404 -    XMLElement( const XMLElement& );	// not supported
 11.1405 -    void operator=( const XMLElement& );	// not supported
 11.1406 -
 11.1407 -    XMLAttribute* FindAttribute( const char* name );
 11.1408 -    XMLAttribute* FindOrCreateAttribute( const char* name );
 11.1409 -    //void LinkAttribute( XMLAttribute* attrib );
 11.1410 -    char* ParseAttributes( char* p );
 11.1411 -
 11.1412 -    int _closingType;
 11.1413 -    // The attribute list is ordered; there is no 'lastAttribute'
 11.1414 -    // because the list needs to be scanned for dupes before adding
 11.1415 -    // a new attribute.
 11.1416 -    XMLAttribute* _rootAttribute;
 11.1417 -};
 11.1418 -
 11.1419 -
 11.1420 -enum Whitespace {
 11.1421 -    PRESERVE_WHITESPACE,
 11.1422 -    COLLAPSE_WHITESPACE
 11.1423 -};
 11.1424 -
 11.1425 -
 11.1426 -/** A Document binds together all the functionality.
 11.1427 -	It can be saved, loaded, and printed to the screen.
 11.1428 -	All Nodes are connected and allocated to a Document.
 11.1429 -	If the Document is deleted, all its Nodes are also deleted.
 11.1430 -*/
 11.1431 -class TINYXML2_LIB XMLDocument : public XMLNode
 11.1432 -{
 11.1433 -    friend class XMLElement;
 11.1434 -public:
 11.1435 -    /// constructor
 11.1436 -    XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
 11.1437 -    ~XMLDocument();
 11.1438 -
 11.1439 -    virtual XMLDocument* ToDocument()				{
 11.1440 -        return this;
 11.1441 -    }
 11.1442 -    virtual const XMLDocument* ToDocument() const	{
 11.1443 -        return this;
 11.1444 -    }
 11.1445 -
 11.1446 -    /**
 11.1447 -    	Parse an XML file from a character string.
 11.1448 -    	Returns XML_NO_ERROR (0) on success, or
 11.1449 -    	an errorID.
 11.1450 -
 11.1451 -    	You may optionally pass in the 'nBytes', which is
 11.1452 -    	the number of bytes which will be parsed. If not
 11.1453 -    	specified, TinyXML-2 will assume 'xml' points to a
 11.1454 -    	null terminated string.
 11.1455 -    */
 11.1456 -    XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
 11.1457 -
 11.1458 -    /**
 11.1459 -    	Load an XML file from disk.
 11.1460 -    	Returns XML_NO_ERROR (0) on success, or
 11.1461 -    	an errorID.
 11.1462 -    */
 11.1463 -    XMLError LoadFile( const char* filename );
 11.1464 -
 11.1465 -    /**
 11.1466 -    	Load an XML file from disk. You are responsible
 11.1467 -    	for providing and closing the FILE*.
 11.1468 -
 11.1469 -    	Returns XML_NO_ERROR (0) on success, or
 11.1470 -    	an errorID.
 11.1471 -    */
 11.1472 -    XMLError LoadFile( FILE* );
 11.1473 -
 11.1474 -    /**
 11.1475 -    	Save the XML file to disk.
 11.1476 -    	Returns XML_NO_ERROR (0) on success, or
 11.1477 -    	an errorID.
 11.1478 -    */
 11.1479 -    XMLError SaveFile( const char* filename, bool compact = false );
 11.1480 -
 11.1481 -    /**
 11.1482 -    	Save the XML file to disk. You are responsible
 11.1483 -    	for providing and closing the FILE*.
 11.1484 -
 11.1485 -    	Returns XML_NO_ERROR (0) on success, or
 11.1486 -    	an errorID.
 11.1487 -    */
 11.1488 -    XMLError SaveFile( FILE* fp, bool compact = false );
 11.1489 -
 11.1490 -    bool ProcessEntities() const		{
 11.1491 -        return _processEntities;
 11.1492 -    }
 11.1493 -    Whitespace WhitespaceMode() const	{
 11.1494 -        return _whitespace;
 11.1495 -    }
 11.1496 -
 11.1497 -    /**
 11.1498 -    	Returns true if this document has a leading Byte Order Mark of UTF8.
 11.1499 -    */
 11.1500 -    bool HasBOM() const {
 11.1501 -        return _writeBOM;
 11.1502 -    }
 11.1503 -    /** Sets whether to write the BOM when writing the file.
 11.1504 -    */
 11.1505 -    void SetBOM( bool useBOM ) {
 11.1506 -        _writeBOM = useBOM;
 11.1507 -    }
 11.1508 -
 11.1509 -    /** Return the root element of DOM. Equivalent to FirstChildElement().
 11.1510 -        To get the first node, use FirstChild().
 11.1511 -    */
 11.1512 -    XMLElement* RootElement()				{
 11.1513 -        return FirstChildElement();
 11.1514 -    }
 11.1515 -    const XMLElement* RootElement() const	{
 11.1516 -        return FirstChildElement();
 11.1517 -    }
 11.1518 -
 11.1519 -    /** Print the Document. If the Printer is not provided, it will
 11.1520 -        print to stdout. If you provide Printer, this can print to a file:
 11.1521 -    	@verbatim
 11.1522 -    	XMLPrinter printer( fp );
 11.1523 -    	doc.Print( &printer );
 11.1524 -    	@endverbatim
 11.1525 -
 11.1526 -    	Or you can use a printer to print to memory:
 11.1527 -    	@verbatim
 11.1528 -    	XMLPrinter printer;
 11.1529 -    	doc.Print( &printer );
 11.1530 -    	// printer.CStr() has a const char* to the XML
 11.1531 -    	@endverbatim
 11.1532 -    */
 11.1533 -    void Print( XMLPrinter* streamer=0 ) const;
 11.1534 -    virtual bool Accept( XMLVisitor* visitor ) const;
 11.1535 -
 11.1536 -    /**
 11.1537 -    	Create a new Element associated with
 11.1538 -    	this Document. The memory for the Element
 11.1539 -    	is managed by the Document.
 11.1540 -    */
 11.1541 -    XMLElement* NewElement( const char* name );
 11.1542 -    /**
 11.1543 -    	Create a new Comment associated with
 11.1544 -    	this Document. The memory for the Comment
 11.1545 -    	is managed by the Document.
 11.1546 -    */
 11.1547 -    XMLComment* NewComment( const char* comment );
 11.1548 -    /**
 11.1549 -    	Create a new Text associated with
 11.1550 -    	this Document. The memory for the Text
 11.1551 -    	is managed by the Document.
 11.1552 -    */
 11.1553 -    XMLText* NewText( const char* text );
 11.1554 -    /**
 11.1555 -    	Create a new Declaration associated with
 11.1556 -    	this Document. The memory for the object
 11.1557 -    	is managed by the Document.
 11.1558 -
 11.1559 -    	If the 'text' param is null, the standard
 11.1560 -    	declaration is used.:
 11.1561 -    	@verbatim
 11.1562 -    		<?xml version="1.0" encoding="UTF-8"?>
 11.1563 -    	@endverbatim
 11.1564 -    */
 11.1565 -    XMLDeclaration* NewDeclaration( const char* text=0 );
 11.1566 -    /**
 11.1567 -    	Create a new Unknown associated with
 11.1568 -    	this Document. The memory for the object
 11.1569 -    	is managed by the Document.
 11.1570 -    */
 11.1571 -    XMLUnknown* NewUnknown( const char* text );
 11.1572 -
 11.1573 -    /**
 11.1574 -    	Delete a node associated with this document.
 11.1575 -    	It will be unlinked from the DOM.
 11.1576 -    */
 11.1577 -    void DeleteNode( XMLNode* node )	{
 11.1578 -        node->_parent->DeleteChild( node );
 11.1579 -    }
 11.1580 -
 11.1581 -    void SetError( XMLError error, const char* str1, const char* str2 );
 11.1582 -
 11.1583 -    /// Return true if there was an error parsing the document.
 11.1584 -    bool Error() const {
 11.1585 -        return _errorID != XML_NO_ERROR;
 11.1586 -    }
 11.1587 -    /// Return the errorID.
 11.1588 -    XMLError  ErrorID() const {
 11.1589 -        return _errorID;
 11.1590 -    }
 11.1591 -    /// Return a possibly helpful diagnostic location or string.
 11.1592 -    const char* GetErrorStr1() const {
 11.1593 -        return _errorStr1;
 11.1594 -    }
 11.1595 -    /// Return a possibly helpful secondary diagnostic location or string.
 11.1596 -    const char* GetErrorStr2() const {
 11.1597 -        return _errorStr2;
 11.1598 -    }
 11.1599 -    /// If there is an error, print it to stdout.
 11.1600 -    void PrintError() const;
 11.1601 -    
 11.1602 -    /// Clear the document, resetting it to the initial state.
 11.1603 -    void Clear();
 11.1604 -
 11.1605 -    // internal
 11.1606 -    char* Identify( char* p, XMLNode** node );
 11.1607 -
 11.1608 -    virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{
 11.1609 -        return 0;
 11.1610 -    }
 11.1611 -    virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{
 11.1612 -        return false;
 11.1613 -    }
 11.1614 -
 11.1615 -private:
 11.1616 -    XMLDocument( const XMLDocument& );	// not supported
 11.1617 -    void operator=( const XMLDocument& );	// not supported
 11.1618 -
 11.1619 -    bool        _writeBOM;
 11.1620 -    bool        _processEntities;
 11.1621 -    XMLError    _errorID;
 11.1622 -    Whitespace  _whitespace;
 11.1623 -    const char* _errorStr1;
 11.1624 -    const char* _errorStr2;
 11.1625 -    char*       _charBuffer;
 11.1626 -
 11.1627 -    MemPoolT< sizeof(XMLElement) >	 _elementPool;
 11.1628 -    MemPoolT< sizeof(XMLAttribute) > _attributePool;
 11.1629 -    MemPoolT< sizeof(XMLText) >		 _textPool;
 11.1630 -    MemPoolT< sizeof(XMLComment) >	 _commentPool;
 11.1631 -};
 11.1632 -
 11.1633 -
 11.1634 -/**
 11.1635 -	A XMLHandle is a class that wraps a node pointer with null checks; this is
 11.1636 -	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
 11.1637 -	DOM structure. It is a separate utility class.
 11.1638 -
 11.1639 -	Take an example:
 11.1640 -	@verbatim
 11.1641 -	<Document>
 11.1642 -		<Element attributeA = "valueA">
 11.1643 -			<Child attributeB = "value1" />
 11.1644 -			<Child attributeB = "value2" />
 11.1645 -		</Element>
 11.1646 -	</Document>
 11.1647 -	@endverbatim
 11.1648 -
 11.1649 -	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
 11.1650 -	easy to write a *lot* of code that looks like:
 11.1651 -
 11.1652 -	@verbatim
 11.1653 -	XMLElement* root = document.FirstChildElement( "Document" );
 11.1654 -	if ( root )
 11.1655 -	{
 11.1656 -		XMLElement* element = root->FirstChildElement( "Element" );
 11.1657 -		if ( element )
 11.1658 -		{
 11.1659 -			XMLElement* child = element->FirstChildElement( "Child" );
 11.1660 -			if ( child )
 11.1661 -			{
 11.1662 -				XMLElement* child2 = child->NextSiblingElement( "Child" );
 11.1663 -				if ( child2 )
 11.1664 -				{
 11.1665 -					// Finally do something useful.
 11.1666 -	@endverbatim
 11.1667 -
 11.1668 -	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
 11.1669 -	of such code. A XMLHandle checks for null pointers so it is perfectly safe
 11.1670 -	and correct to use:
 11.1671 -
 11.1672 -	@verbatim
 11.1673 -	XMLHandle docHandle( &document );
 11.1674 -	XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
 11.1675 -	if ( child2 )
 11.1676 -	{
 11.1677 -		// do something useful
 11.1678 -	@endverbatim
 11.1679 -
 11.1680 -	Which is MUCH more concise and useful.
 11.1681 -
 11.1682 -	It is also safe to copy handles - internally they are nothing more than node pointers.
 11.1683 -	@verbatim
 11.1684 -	XMLHandle handleCopy = handle;
 11.1685 -	@endverbatim
 11.1686 -
 11.1687 -	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
 11.1688 -*/
 11.1689 -class TINYXML2_LIB XMLHandle
 11.1690 -{
 11.1691 -public:
 11.1692 -    /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
 11.1693 -    XMLHandle( XMLNode* node )												{
 11.1694 -        _node = node;
 11.1695 -    }
 11.1696 -    /// Create a handle from a node.
 11.1697 -    XMLHandle( XMLNode& node )												{
 11.1698 -        _node = &node;
 11.1699 -    }
 11.1700 -    /// Copy constructor
 11.1701 -    XMLHandle( const XMLHandle& ref )										{
 11.1702 -        _node = ref._node;
 11.1703 -    }
 11.1704 -    /// Assignment
 11.1705 -    XMLHandle& operator=( const XMLHandle& ref )							{
 11.1706 -        _node = ref._node;
 11.1707 -        return *this;
 11.1708 -    }
 11.1709 -
 11.1710 -    /// Get the first child of this handle.
 11.1711 -    XMLHandle FirstChild() 													{
 11.1712 -        return XMLHandle( _node ? _node->FirstChild() : 0 );
 11.1713 -    }
 11.1714 -    /// Get the first child element of this handle.
 11.1715 -    XMLHandle FirstChildElement( const char* value=0 )						{
 11.1716 -        return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
 11.1717 -    }
 11.1718 -    /// Get the last child of this handle.
 11.1719 -    XMLHandle LastChild()													{
 11.1720 -        return XMLHandle( _node ? _node->LastChild() : 0 );
 11.1721 -    }
 11.1722 -    /// Get the last child element of this handle.
 11.1723 -    XMLHandle LastChildElement( const char* _value=0 )						{
 11.1724 -        return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
 11.1725 -    }
 11.1726 -    /// Get the previous sibling of this handle.
 11.1727 -    XMLHandle PreviousSibling()												{
 11.1728 -        return XMLHandle( _node ? _node->PreviousSibling() : 0 );
 11.1729 -    }
 11.1730 -    /// Get the previous sibling element of this handle.
 11.1731 -    XMLHandle PreviousSiblingElement( const char* _value=0 )				{
 11.1732 -        return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
 11.1733 -    }
 11.1734 -    /// Get the next sibling of this handle.
 11.1735 -    XMLHandle NextSibling()													{
 11.1736 -        return XMLHandle( _node ? _node->NextSibling() : 0 );
 11.1737 -    }
 11.1738 -    /// Get the next sibling element of this handle.
 11.1739 -    XMLHandle NextSiblingElement( const char* _value=0 )					{
 11.1740 -        return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
 11.1741 -    }
 11.1742 -
 11.1743 -    /// Safe cast to XMLNode. This can return null.
 11.1744 -    XMLNode* ToNode()							{
 11.1745 -        return _node;
 11.1746 -    }
 11.1747 -    /// Safe cast to XMLElement. This can return null.
 11.1748 -    XMLElement* ToElement() 					{
 11.1749 -        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
 11.1750 -    }
 11.1751 -    /// Safe cast to XMLText. This can return null.
 11.1752 -    XMLText* ToText() 							{
 11.1753 -        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
 11.1754 -    }
 11.1755 -    /// Safe cast to XMLUnknown. This can return null.
 11.1756 -    XMLUnknown* ToUnknown() 					{
 11.1757 -        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
 11.1758 -    }
 11.1759 -    /// Safe cast to XMLDeclaration. This can return null.
 11.1760 -    XMLDeclaration* ToDeclaration() 			{
 11.1761 -        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
 11.1762 -    }
 11.1763 -
 11.1764 -private:
 11.1765 -    XMLNode* _node;
 11.1766 -};
 11.1767 -
 11.1768 -
 11.1769 -/**
 11.1770 -	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
 11.1771 -	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
 11.1772 -*/
 11.1773 -class TINYXML2_LIB XMLConstHandle
 11.1774 -{
 11.1775 -public:
 11.1776 -    XMLConstHandle( const XMLNode* node )											{
 11.1777 -        _node = node;
 11.1778 -    }
 11.1779 -    XMLConstHandle( const XMLNode& node )											{
 11.1780 -        _node = &node;
 11.1781 -    }
 11.1782 -    XMLConstHandle( const XMLConstHandle& ref )										{
 11.1783 -        _node = ref._node;
 11.1784 -    }
 11.1785 -
 11.1786 -    XMLConstHandle& operator=( const XMLConstHandle& ref )							{
 11.1787 -        _node = ref._node;
 11.1788 -        return *this;
 11.1789 -    }
 11.1790 -
 11.1791 -    const XMLConstHandle FirstChild() const											{
 11.1792 -        return XMLConstHandle( _node ? _node->FirstChild() : 0 );
 11.1793 -    }
 11.1794 -    const XMLConstHandle FirstChildElement( const char* value=0 ) const				{
 11.1795 -        return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
 11.1796 -    }
 11.1797 -    const XMLConstHandle LastChild()	const										{
 11.1798 -        return XMLConstHandle( _node ? _node->LastChild() : 0 );
 11.1799 -    }
 11.1800 -    const XMLConstHandle LastChildElement( const char* _value=0 ) const				{
 11.1801 -        return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
 11.1802 -    }
 11.1803 -    const XMLConstHandle PreviousSibling() const									{
 11.1804 -        return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
 11.1805 -    }
 11.1806 -    const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const		{
 11.1807 -        return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
 11.1808 -    }
 11.1809 -    const XMLConstHandle NextSibling() const										{
 11.1810 -        return XMLConstHandle( _node ? _node->NextSibling() : 0 );
 11.1811 -    }
 11.1812 -    const XMLConstHandle NextSiblingElement( const char* _value=0 ) const			{
 11.1813 -        return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
 11.1814 -    }
 11.1815 -
 11.1816 -
 11.1817 -    const XMLNode* ToNode() const				{
 11.1818 -        return _node;
 11.1819 -    }
 11.1820 -    const XMLElement* ToElement() const			{
 11.1821 -        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
 11.1822 -    }
 11.1823 -    const XMLText* ToText() const				{
 11.1824 -        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
 11.1825 -    }
 11.1826 -    const XMLUnknown* ToUnknown() const			{
 11.1827 -        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
 11.1828 -    }
 11.1829 -    const XMLDeclaration* ToDeclaration() const	{
 11.1830 -        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
 11.1831 -    }
 11.1832 -
 11.1833 -private:
 11.1834 -    const XMLNode* _node;
 11.1835 -};
 11.1836 -
 11.1837 -
 11.1838 -/**
 11.1839 -	Printing functionality. The XMLPrinter gives you more
 11.1840 -	options than the XMLDocument::Print() method.
 11.1841 -
 11.1842 -	It can:
 11.1843 -	-# Print to memory.
 11.1844 -	-# Print to a file you provide.
 11.1845 -	-# Print XML without a XMLDocument.
 11.1846 -
 11.1847 -	Print to Memory
 11.1848 -
 11.1849 -	@verbatim
 11.1850 -	XMLPrinter printer;
 11.1851 -	doc.Print( &printer );
 11.1852 -	SomeFunction( printer.CStr() );
 11.1853 -	@endverbatim
 11.1854 -
 11.1855 -	Print to a File
 11.1856 -
 11.1857 -	You provide the file pointer.
 11.1858 -	@verbatim
 11.1859 -	XMLPrinter printer( fp );
 11.1860 -	doc.Print( &printer );
 11.1861 -	@endverbatim
 11.1862 -
 11.1863 -	Print without a XMLDocument
 11.1864 -
 11.1865 -	When loading, an XML parser is very useful. However, sometimes
 11.1866 -	when saving, it just gets in the way. The code is often set up
 11.1867 -	for streaming, and constructing the DOM is just overhead.
 11.1868 -
 11.1869 -	The Printer supports the streaming case. The following code
 11.1870 -	prints out a trivially simple XML file without ever creating
 11.1871 -	an XML document.
 11.1872 -
 11.1873 -	@verbatim
 11.1874 -	XMLPrinter printer( fp );
 11.1875 -	printer.OpenElement( "foo" );
 11.1876 -	printer.PushAttribute( "foo", "bar" );
 11.1877 -	printer.CloseElement();
 11.1878 -	@endverbatim
 11.1879 -*/
 11.1880 -class TINYXML2_LIB XMLPrinter : public XMLVisitor
 11.1881 -{
 11.1882 -public:
 11.1883 -    /** Construct the printer. If the FILE* is specified,
 11.1884 -    	this will print to the FILE. Else it will print
 11.1885 -    	to memory, and the result is available in CStr().
 11.1886 -    	If 'compact' is set to true, then output is created
 11.1887 -    	with only required whitespace and newlines.
 11.1888 -    */
 11.1889 -    XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
 11.1890 -    ~XMLPrinter()	{}
 11.1891 -
 11.1892 -    /** If streaming, write the BOM and declaration. */
 11.1893 -    void PushHeader( bool writeBOM, bool writeDeclaration );
 11.1894 -    /** If streaming, start writing an element.
 11.1895 -        The element must be closed with CloseElement()
 11.1896 -    */
 11.1897 -    void OpenElement( const char* name );
 11.1898 -    /// If streaming, add an attribute to an open element.
 11.1899 -    void PushAttribute( const char* name, const char* value );
 11.1900 -    void PushAttribute( const char* name, int value );
 11.1901 -    void PushAttribute( const char* name, unsigned value );
 11.1902 -    void PushAttribute( const char* name, bool value );
 11.1903 -    void PushAttribute( const char* name, double value );
 11.1904 -    /// If streaming, close the Element.
 11.1905 -    void CloseElement();
 11.1906 -
 11.1907 -    /// Add a text node.
 11.1908 -    void PushText( const char* text, bool cdata=false );
 11.1909 -    /// Add a text node from an integer.
 11.1910 -    void PushText( int value );
 11.1911 -    /// Add a text node from an unsigned.
 11.1912 -    void PushText( unsigned value );
 11.1913 -    /// Add a text node from a bool.
 11.1914 -    void PushText( bool value );
 11.1915 -    /// Add a text node from a float.
 11.1916 -    void PushText( float value );
 11.1917 -    /// Add a text node from a double.
 11.1918 -    void PushText( double value );
 11.1919 -
 11.1920 -    /// Add a comment
 11.1921 -    void PushComment( const char* comment );
 11.1922 -
 11.1923 -    void PushDeclaration( const char* value );
 11.1924 -    void PushUnknown( const char* value );
 11.1925 -
 11.1926 -    virtual bool VisitEnter( const XMLDocument& /*doc*/ );
 11.1927 -    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
 11.1928 -        return true;
 11.1929 -    }
 11.1930 -
 11.1931 -    virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
 11.1932 -    virtual bool VisitExit( const XMLElement& element );
 11.1933 -
 11.1934 -    virtual bool Visit( const XMLText& text );
 11.1935 -    virtual bool Visit( const XMLComment& comment );
 11.1936 -    virtual bool Visit( const XMLDeclaration& declaration );
 11.1937 -    virtual bool Visit( const XMLUnknown& unknown );
 11.1938 -
 11.1939 -    /**
 11.1940 -    	If in print to memory mode, return a pointer to
 11.1941 -    	the XML file in memory.
 11.1942 -    */
 11.1943 -    const char* CStr() const {
 11.1944 -        return _buffer.Mem();
 11.1945 -    }
 11.1946 -    /**
 11.1947 -    	If in print to memory mode, return the size
 11.1948 -    	of the XML file in memory. (Note the size returned
 11.1949 -    	includes the terminating null.)
 11.1950 -    */
 11.1951 -    int CStrSize() const {
 11.1952 -        return _buffer.Size();
 11.1953 -    }
 11.1954 -
 11.1955 -private:
 11.1956 -    void SealElement();
 11.1957 -    void PrintSpace( int depth );
 11.1958 -    void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
 11.1959 -    void Print( const char* format, ... );
 11.1960 -
 11.1961 -    bool _elementJustOpened;
 11.1962 -    bool _firstElement;
 11.1963 -    FILE* _fp;
 11.1964 -    int _depth;
 11.1965 -    int _textDepth;
 11.1966 -    bool _processEntities;
 11.1967 -    bool _compactMode;
 11.1968 -
 11.1969 -    enum {
 11.1970 -        ENTITY_RANGE = 64,
 11.1971 -        BUF_SIZE = 200
 11.1972 -    };
 11.1973 -    bool _entityFlag[ENTITY_RANGE];
 11.1974 -    bool _restrictedEntityFlag[ENTITY_RANGE];
 11.1975 -
 11.1976 -    DynArray< const char*, 10 > _stack;
 11.1977 -    DynArray< char, 20 > _buffer;
 11.1978 -#ifdef _MSC_VER
 11.1979 -    DynArray< char, 20 > _accumulator;
 11.1980 -#endif
 11.1981 -};
 11.1982 -
 11.1983 -
 11.1984 -}	// tinyxml2
 11.1985 -
 11.1986 -#if defined(_MSC_VER)
 11.1987 -#   pragma warning(pop)
 11.1988 -#endif
 11.1989 -
 11.1990 -#endif // TINYXML2_INCLUDED
 11.1991 +/*
 11.1992 +Original code by Lee Thomason (www.grinninglizard.com)
 11.1993 +
 11.1994 +This software is provided 'as-is', without any express or implied
 11.1995 +warranty. In no event will the authors be held liable for any
 11.1996 +damages arising from the use of this software.
 11.1997 +
 11.1998 +Permission is granted to anyone to use this software for any
 11.1999 +purpose, including commercial applications, and to alter it and
 11.2000 +redistribute it freely, subject to the following restrictions:
 11.2001 +
 11.2002 +1. The origin of this software must not be misrepresented; you must
 11.2003 +not claim that you wrote the original software. If you use this
 11.2004 +software in a product, an acknowledgment in the product documentation
 11.2005 +would be appreciated but is not required.
 11.2006 +
 11.2007 +
 11.2008 +2. Altered source versions must be plainly marked as such, and
 11.2009 +must not be misrepresented as being the original software.
 11.2010 +
 11.2011 +3. This notice may not be removed or altered from any source
 11.2012 +distribution.
 11.2013 +*/
 11.2014 +
 11.2015 +#ifndef TINYXML2_INCLUDED
 11.2016 +#define TINYXML2_INCLUDED
 11.2017 +
 11.2018 +#if defined(ANDROID_NDK) || defined(__BORLANDC__)
 11.2019 +#   include <ctype.h>
 11.2020 +#   include <limits.h>
 11.2021 +#   include <stdio.h>
 11.2022 +#   include <stdlib.h>
 11.2023 +#   include <string.h>
 11.2024 +#   include <stdarg.h>
 11.2025 +#else
 11.2026 +#   include <cctype>
 11.2027 +#   include <climits>
 11.2028 +#   include <cstdio>
 11.2029 +#   include <cstdlib>
 11.2030 +#   include <cstring>
 11.2031 +#   include <cstdarg>
 11.2032 +#endif
 11.2033 +
 11.2034 +/*
 11.2035 +   TODO: intern strings instead of allocation.
 11.2036 +*/
 11.2037 +/*
 11.2038 +	gcc:
 11.2039 +        g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
 11.2040 +
 11.2041 +    Formatting, Artistic Style:
 11.2042 +        AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
 11.2043 +*/
 11.2044 +
 11.2045 +#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
 11.2046 +#   ifndef DEBUG
 11.2047 +#       define DEBUG
 11.2048 +#   endif
 11.2049 +#endif
 11.2050 +
 11.2051 +#ifdef _MSC_VER
 11.2052 +#   pragma warning(push)
 11.2053 +#   pragma warning(disable: 4251)
 11.2054 +#endif
 11.2055 +
 11.2056 +#ifdef _WIN32
 11.2057 +#   ifdef TINYXML2_EXPORT
 11.2058 +#       define TINYXML2_LIB __declspec(dllexport)
 11.2059 +#   elif defined(TINYXML2_IMPORT)
 11.2060 +#       define TINYXML2_LIB __declspec(dllimport)
 11.2061 +#   else
 11.2062 +#       define TINYXML2_LIB
 11.2063 +#   endif
 11.2064 +#else
 11.2065 +#   define TINYXML2_LIB
 11.2066 +#endif
 11.2067 +
 11.2068 +
 11.2069 +#if defined(DEBUG)
 11.2070 +#   if defined(_MSC_VER)
 11.2071 +#       define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
 11.2072 +#   elif defined (ANDROID_NDK)
 11.2073 +#       include <android/log.h>
 11.2074 +#       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
 11.2075 +#   else
 11.2076 +#       include <assert.h>
 11.2077 +#       define TIXMLASSERT                assert
 11.2078 +#   endif
 11.2079 +#   else
 11.2080 +#       define TIXMLASSERT( x )           {}
 11.2081 +#endif
 11.2082 +
 11.2083 +
 11.2084 +#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
 11.2085 +// Microsoft visual studio, version 2005 and higher.
 11.2086 +/*int _snprintf_s(
 11.2087 +   char *buffer,
 11.2088 +   size_t sizeOfBuffer,
 11.2089 +   size_t count,
 11.2090 +   const char *format [,
 11.2091 +	  argument] ...
 11.2092 +);*/
 11.2093 +inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
 11.2094 +{
 11.2095 +    va_list va;
 11.2096 +    va_start( va, format );
 11.2097 +    int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
 11.2098 +    va_end( va );
 11.2099 +    return result;
 11.2100 +}
 11.2101 +#define TIXML_SSCANF   sscanf_s
 11.2102 +#else
 11.2103 +// GCC version 3 and higher
 11.2104 +//#warning( "Using sn* functions." )
 11.2105 +#define TIXML_SNPRINTF snprintf
 11.2106 +#define TIXML_SSCANF   sscanf
 11.2107 +#endif
 11.2108 +
 11.2109 +static const int TIXML2_MAJOR_VERSION = 1;
 11.2110 +static const int TIXML2_MINOR_VERSION = 0;
 11.2111 +static const int TIXML2_PATCH_VERSION = 11;
 11.2112 +
 11.2113 +namespace tinyxml2
 11.2114 +{
 11.2115 +class XMLDocument;
 11.2116 +class XMLElement;
 11.2117 +class XMLAttribute;
 11.2118 +class XMLComment;
 11.2119 +class XMLText;
 11.2120 +class XMLDeclaration;
 11.2121 +class XMLUnknown;
 11.2122 +class XMLPrinter;
 11.2123 +
 11.2124 +/*
 11.2125 +	A class that wraps strings. Normally stores the start and end
 11.2126 +	pointers into the XML file itself, and will apply normalization
 11.2127 +	and entity translation if actually read. Can also store (and memory
 11.2128 +	manage) a traditional char[]
 11.2129 +*/
 11.2130 +class StrPair
 11.2131 +{
 11.2132 +public:
 11.2133 +    enum {
 11.2134 +        NEEDS_ENTITY_PROCESSING			= 0x01,
 11.2135 +        NEEDS_NEWLINE_NORMALIZATION		= 0x02,
 11.2136 +        COLLAPSE_WHITESPACE	                = 0x04,
 11.2137 +
 11.2138 +        TEXT_ELEMENT		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
 11.2139 +        TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
 11.2140 +        ATTRIBUTE_NAME		            	= 0,
 11.2141 +        ATTRIBUTE_VALUE		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
 11.2142 +        ATTRIBUTE_VALUE_LEAVE_ENTITIES  	= NEEDS_NEWLINE_NORMALIZATION,
 11.2143 +        COMMENT				        = NEEDS_NEWLINE_NORMALIZATION
 11.2144 +    };
 11.2145 +
 11.2146 +    StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
 11.2147 +    ~StrPair();
 11.2148 +
 11.2149 +    void Set( char* start, char* end, int flags ) {
 11.2150 +        Reset();
 11.2151 +        _start  = start;
 11.2152 +        _end    = end;
 11.2153 +        _flags  = flags | NEEDS_FLUSH;
 11.2154 +    }
 11.2155 +
 11.2156 +    const char* GetStr();
 11.2157 +
 11.2158 +    bool Empty() const {
 11.2159 +        return _start == _end;
 11.2160 +    }
 11.2161 +
 11.2162 +    void SetInternedStr( const char* str ) {
 11.2163 +        Reset();
 11.2164 +        _start = const_cast<char*>(str);
 11.2165 +    }
 11.2166 +
 11.2167 +    void SetStr( const char* str, int flags=0 );
 11.2168 +
 11.2169 +    char* ParseText( char* in, const char* endTag, int strFlags );
 11.2170 +    char* ParseName( char* in );
 11.2171 +
 11.2172 +private:
 11.2173 +    void Reset();
 11.2174 +    void CollapseWhitespace();
 11.2175 +
 11.2176 +    enum {
 11.2177 +        NEEDS_FLUSH = 0x100,
 11.2178 +        NEEDS_DELETE = 0x200
 11.2179 +    };
 11.2180 +
 11.2181 +    // After parsing, if *_end != 0, it can be set to zero.
 11.2182 +    int     _flags;
 11.2183 +    char*   _start;
 11.2184 +    char*   _end;
 11.2185 +};
 11.2186 +
 11.2187 +
 11.2188 +/*
 11.2189 +	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
 11.2190 +	Has a small initial memory pool, so that low or no usage will not
 11.2191 +	cause a call to new/delete
 11.2192 +*/
 11.2193 +template <class T, int INIT>
 11.2194 +class DynArray
 11.2195 +{
 11.2196 +public:
 11.2197 +    DynArray< T, INIT >() {
 11.2198 +        _mem = _pool;
 11.2199 +        _allocated = INIT;
 11.2200 +        _size = 0;
 11.2201 +    }
 11.2202 +
 11.2203 +    ~DynArray() {
 11.2204 +        if ( _mem != _pool ) {
 11.2205 +            delete [] _mem;
 11.2206 +        }
 11.2207 +    }
 11.2208 +
 11.2209 +    void Push( T t ) {
 11.2210 +        EnsureCapacity( _size+1 );
 11.2211 +        _mem[_size++] = t;
 11.2212 +    }
 11.2213 +
 11.2214 +    T* PushArr( int count ) {
 11.2215 +        EnsureCapacity( _size+count );
 11.2216 +        T* ret = &_mem[_size];
 11.2217 +        _size += count;
 11.2218 +        return ret;
 11.2219 +    }
 11.2220 +
 11.2221 +    T Pop() {
 11.2222 +        return _mem[--_size];
 11.2223 +    }
 11.2224 +
 11.2225 +    void PopArr( int count ) {
 11.2226 +        TIXMLASSERT( _size >= count );
 11.2227 +        _size -= count;
 11.2228 +    }
 11.2229 +
 11.2230 +    bool Empty() const					{
 11.2231 +        return _size == 0;
 11.2232 +    }
 11.2233 +
 11.2234 +    T& operator[](int i)				{
 11.2235 +        TIXMLASSERT( i>= 0 && i < _size );
 11.2236 +        return _mem[i];
 11.2237 +    }
 11.2238 +
 11.2239 +    const T& operator[](int i) const	{
 11.2240 +        TIXMLASSERT( i>= 0 && i < _size );
 11.2241 +        return _mem[i];
 11.2242 +    }
 11.2243 +
 11.2244 +    int Size() const					{
 11.2245 +        return _size;
 11.2246 +    }
 11.2247 +
 11.2248 +    int Capacity() const				{
 11.2249 +        return _allocated;
 11.2250 +    }
 11.2251 +
 11.2252 +    const T* Mem() const				{
 11.2253 +        return _mem;
 11.2254 +    }
 11.2255 +
 11.2256 +    T* Mem()							{
 11.2257 +        return _mem;
 11.2258 +    }
 11.2259 +
 11.2260 +private:
 11.2261 +    void EnsureCapacity( int cap ) {
 11.2262 +        if ( cap > _allocated ) {
 11.2263 +            int newAllocated = cap * 2;
 11.2264 +            T* newMem = new T[newAllocated];
 11.2265 +            memcpy( newMem, _mem, sizeof(T)*_size );	// warning: not using constructors, only works for PODs
 11.2266 +            if ( _mem != _pool ) {
 11.2267 +                delete [] _mem;
 11.2268 +            }
 11.2269 +            _mem = newMem;
 11.2270 +            _allocated = newAllocated;
 11.2271 +        }
 11.2272 +    }
 11.2273 +
 11.2274 +    T*  _mem;
 11.2275 +    T   _pool[INIT];
 11.2276 +    int _allocated;		// objects allocated
 11.2277 +    int _size;			// number objects in use
 11.2278 +};
 11.2279 +
 11.2280 +
 11.2281 +/*
 11.2282 +	Parent virtual class of a pool for fast allocation
 11.2283 +	and deallocation of objects.
 11.2284 +*/
 11.2285 +class MemPool
 11.2286 +{
 11.2287 +public:
 11.2288 +    MemPool() {}
 11.2289 +    virtual ~MemPool() {}
 11.2290 +
 11.2291 +    virtual int ItemSize() const = 0;
 11.2292 +    virtual void* Alloc() = 0;
 11.2293 +    virtual void Free( void* ) = 0;
 11.2294 +    virtual void SetTracked() = 0;
 11.2295 +};
 11.2296 +
 11.2297 +
 11.2298 +/*
 11.2299 +	Template child class to create pools of the correct type.
 11.2300 +*/
 11.2301 +template< int SIZE >
 11.2302 +class MemPoolT : public MemPool
 11.2303 +{
 11.2304 +public:
 11.2305 +    MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
 11.2306 +    ~MemPoolT() {
 11.2307 +        // Delete the blocks.
 11.2308 +        for( int i=0; i<_blockPtrs.Size(); ++i ) {
 11.2309 +            delete _blockPtrs[i];
 11.2310 +        }
 11.2311 +    }
 11.2312 +
 11.2313 +    virtual int ItemSize() const	{
 11.2314 +        return SIZE;
 11.2315 +    }
 11.2316 +    int CurrentAllocs() const		{
 11.2317 +        return _currentAllocs;
 11.2318 +    }
 11.2319 +
 11.2320 +    virtual void* Alloc() {
 11.2321 +        if ( !_root ) {
 11.2322 +            // Need a new block.
 11.2323 +            Block* block = new Block();
 11.2324 +            _blockPtrs.Push( block );
 11.2325 +
 11.2326 +            for( int i=0; i<COUNT-1; ++i ) {
 11.2327 +                block->chunk[i].next = &block->chunk[i+1];
 11.2328 +            }
 11.2329 +            block->chunk[COUNT-1].next = 0;
 11.2330 +            _root = block->chunk;
 11.2331 +        }
 11.2332 +        void* result = _root;
 11.2333 +        _root = _root->next;
 11.2334 +
 11.2335 +        ++_currentAllocs;
 11.2336 +        if ( _currentAllocs > _maxAllocs ) {
 11.2337 +            _maxAllocs = _currentAllocs;
 11.2338 +        }
 11.2339 +        _nAllocs++;
 11.2340 +        _nUntracked++;
 11.2341 +        return result;
 11.2342 +    }
 11.2343 +    virtual void Free( void* mem ) {
 11.2344 +        if ( !mem ) {
 11.2345 +            return;
 11.2346 +        }
 11.2347 +        --_currentAllocs;
 11.2348 +        Chunk* chunk = (Chunk*)mem;
 11.2349 +#ifdef DEBUG
 11.2350 +        memset( chunk, 0xfe, sizeof(Chunk) );
 11.2351 +#endif
 11.2352 +        chunk->next = _root;
 11.2353 +        _root = chunk;
 11.2354 +    }
 11.2355 +    void Trace( const char* name ) {
 11.2356 +        printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
 11.2357 +                name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
 11.2358 +    }
 11.2359 +
 11.2360 +    void SetTracked() {
 11.2361 +        _nUntracked--;
 11.2362 +    }
 11.2363 +
 11.2364 +    int Untracked() const {
 11.2365 +        return _nUntracked;
 11.2366 +    }
 11.2367 +
 11.2368 +	// This number is perf sensitive. 4k seems like a good tradeoff on my machine.
 11.2369 +	// The test file is large, 170k.
 11.2370 +	// Release:		VS2010 gcc(no opt)
 11.2371 +	//		1k:		4000
 11.2372 +	//		2k:		4000
 11.2373 +	//		4k:		3900	21000
 11.2374 +	//		16k:	5200
 11.2375 +	//		32k:	4300
 11.2376 +	//		64k:	4000	21000
 11.2377 +    enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
 11.2378 +
 11.2379 +private:
 11.2380 +    union Chunk {
 11.2381 +        Chunk*  next;
 11.2382 +        char    mem[SIZE];
 11.2383 +    };
 11.2384 +    struct Block {
 11.2385 +        Chunk chunk[COUNT];
 11.2386 +    };
 11.2387 +    DynArray< Block*, 10 > _blockPtrs;
 11.2388 +    Chunk* _root;
 11.2389 +
 11.2390 +    int _currentAllocs;
 11.2391 +    int _nAllocs;
 11.2392 +    int _maxAllocs;
 11.2393 +    int _nUntracked;
 11.2394 +};
 11.2395 +
 11.2396 +
 11.2397 +
 11.2398 +/**
 11.2399 +	Implements the interface to the "Visitor pattern" (see the Accept() method.)
 11.2400 +	If you call the Accept() method, it requires being passed a XMLVisitor
 11.2401 +	class to handle callbacks. For nodes that contain other nodes (Document, Element)
 11.2402 +	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
 11.2403 +	are simply called with Visit().
 11.2404 +
 11.2405 +	If you return 'true' from a Visit method, recursive parsing will continue. If you return
 11.2406 +	false, <b>no children of this node or its siblings</b> will be visited.
 11.2407 +
 11.2408 +	All flavors of Visit methods have a default implementation that returns 'true' (continue
 11.2409 +	visiting). You need to only override methods that are interesting to you.
 11.2410 +
 11.2411 +	Generally Accept() is called on the XMLDocument, although all nodes support visiting.
 11.2412 +
 11.2413 +	You should never change the document from a callback.
 11.2414 +
 11.2415 +	@sa XMLNode::Accept()
 11.2416 +*/
 11.2417 +class TINYXML2_LIB XMLVisitor
 11.2418 +{
 11.2419 +public:
 11.2420 +    virtual ~XMLVisitor() {}
 11.2421 +
 11.2422 +    /// Visit a document.
 11.2423 +    virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{
 11.2424 +        return true;
 11.2425 +    }
 11.2426 +    /// Visit a document.
 11.2427 +    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
 11.2428 +        return true;
 11.2429 +    }
 11.2430 +
 11.2431 +    /// Visit an element.
 11.2432 +    virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{
 11.2433 +        return true;
 11.2434 +    }
 11.2435 +    /// Visit an element.
 11.2436 +    virtual bool VisitExit( const XMLElement& /*element*/ )			{
 11.2437 +        return true;
 11.2438 +    }
 11.2439 +
 11.2440 +    /// Visit a declaration.
 11.2441 +    virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{
 11.2442 +        return true;
 11.2443 +    }
 11.2444 +    /// Visit a text node.
 11.2445 +    virtual bool Visit( const XMLText& /*text*/ )					{
 11.2446 +        return true;
 11.2447 +    }
 11.2448 +    /// Visit a comment node.
 11.2449 +    virtual bool Visit( const XMLComment& /*comment*/ )				{
 11.2450 +        return true;
 11.2451 +    }
 11.2452 +    /// Visit an unknown node.
 11.2453 +    virtual bool Visit( const XMLUnknown& /*unknown*/ )				{
 11.2454 +        return true;
 11.2455 +    }
 11.2456 +};
 11.2457 +
 11.2458 +
 11.2459 +/*
 11.2460 +	Utility functionality.
 11.2461 +*/
 11.2462 +class XMLUtil
 11.2463 +{
 11.2464 +public:
 11.2465 +    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
 11.2466 +    // correct, but simple, and usually works.
 11.2467 +    static const char* SkipWhiteSpace( const char* p )	{
 11.2468 +        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
 11.2469 +            ++p;
 11.2470 +        }
 11.2471 +        return p;
 11.2472 +    }
 11.2473 +    static char* SkipWhiteSpace( char* p )				{
 11.2474 +        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) )		{
 11.2475 +            ++p;
 11.2476 +        }
 11.2477 +        return p;
 11.2478 +    }
 11.2479 +    static bool IsWhiteSpace( char p )					{
 11.2480 +        return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
 11.2481 +    }
 11.2482 +    
 11.2483 +    inline static bool IsNameStartChar( unsigned char ch ) {
 11.2484 +        return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
 11.2485 +               || ch == ':'
 11.2486 +               || ch == '_';
 11.2487 +    }
 11.2488 +    
 11.2489 +    inline static bool IsNameChar( unsigned char ch ) {
 11.2490 +        return IsNameStartChar( ch )
 11.2491 +               || isdigit( ch )
 11.2492 +               || ch == '.'
 11.2493 +               || ch == '-';
 11.2494 +    }
 11.2495 +
 11.2496 +    inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
 11.2497 +        int n = 0;
 11.2498 +        if ( p == q ) {
 11.2499 +            return true;
 11.2500 +        }
 11.2501 +        while( *p && *q && *p == *q && n<nChar ) {
 11.2502 +            ++p;
 11.2503 +            ++q;
 11.2504 +            ++n;
 11.2505 +        }
 11.2506 +        if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
 11.2507 +            return true;
 11.2508 +        }
 11.2509 +        return false;
 11.2510 +    }
 11.2511 +    
 11.2512 +    inline static int IsUTF8Continuation( const char p ) {
 11.2513 +        return p & 0x80;
 11.2514 +    }
 11.2515 +
 11.2516 +    static const char* ReadBOM( const char* p, bool* hasBOM );
 11.2517 +    // p is the starting location,
 11.2518 +    // the UTF-8 value of the entity will be placed in value, and length filled in.
 11.2519 +    static const char* GetCharacterRef( const char* p, char* value, int* length );
 11.2520 +    static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
 11.2521 +
 11.2522 +    // converts primitive types to strings
 11.2523 +    static void ToStr( int v, char* buffer, int bufferSize );
 11.2524 +    static void ToStr( unsigned v, char* buffer, int bufferSize );
 11.2525 +    static void ToStr( bool v, char* buffer, int bufferSize );
 11.2526 +    static void ToStr( float v, char* buffer, int bufferSize );
 11.2527 +    static void ToStr( double v, char* buffer, int bufferSize );
 11.2528 +
 11.2529 +    // converts strings to primitive types
 11.2530 +    static bool	ToInt( const char* str, int* value );
 11.2531 +    static bool ToUnsigned( const char* str, unsigned* value );
 11.2532 +    static bool	ToBool( const char* str, bool* value );
 11.2533 +    static bool	ToFloat( const char* str, float* value );
 11.2534 +    static bool ToDouble( const char* str, double* value );
 11.2535 +};
 11.2536 +
 11.2537 +
 11.2538 +/** XMLNode is a base class for every object that is in the
 11.2539 +	XML Document Object Model (DOM), except XMLAttributes.
 11.2540 +	Nodes have siblings, a parent, and children which can
 11.2541 +	be navigated. A node is always in a XMLDocument.
 11.2542 +	The type of a XMLNode can be queried, and it can
 11.2543 +	be cast to its more defined type.
 11.2544 +
 11.2545 +	A XMLDocument allocates memory for all its Nodes.
 11.2546 +	When the XMLDocument gets deleted, all its Nodes
 11.2547 +	will also be deleted.
 11.2548 +
 11.2549 +	@verbatim
 11.2550 +	A Document can contain:	Element	(container or leaf)
 11.2551 +							Comment (leaf)
 11.2552 +							Unknown (leaf)
 11.2553 +							Declaration( leaf )
 11.2554 +
 11.2555 +	An Element can contain:	Element (container or leaf)
 11.2556 +							Text	(leaf)
 11.2557 +							Attributes (not on tree)
 11.2558 +							Comment (leaf)
 11.2559 +							Unknown (leaf)
 11.2560 +
 11.2561 +	@endverbatim
 11.2562 +*/
 11.2563 +class TINYXML2_LIB XMLNode
 11.2564 +{
 11.2565 +    friend class XMLDocument;
 11.2566 +    friend class XMLElement;
 11.2567 +public:
 11.2568 +
 11.2569 +    /// Get the XMLDocument that owns this XMLNode.
 11.2570 +    const XMLDocument* GetDocument() const	{
 11.2571 +        return _document;
 11.2572 +    }
 11.2573 +    /// Get the XMLDocument that owns this XMLNode.
 11.2574 +    XMLDocument* GetDocument()				{
 11.2575 +        return _document;
 11.2576 +    }
 11.2577 +
 11.2578 +    /// Safely cast to an Element, or null.
 11.2579 +    virtual XMLElement*		ToElement()		{
 11.2580 +        return 0;
 11.2581 +    }
 11.2582 +    /// Safely cast to Text, or null.
 11.2583 +    virtual XMLText*		ToText()		{
 11.2584 +        return 0;
 11.2585 +    }
 11.2586 +    /// Safely cast to a Comment, or null.
 11.2587 +    virtual XMLComment*		ToComment()		{
 11.2588 +        return 0;
 11.2589 +    }
 11.2590 +    /// Safely cast to a Document, or null.
 11.2591 +    virtual XMLDocument*	ToDocument()	{
 11.2592 +        return 0;
 11.2593 +    }
 11.2594 +    /// Safely cast to a Declaration, or null.
 11.2595 +    virtual XMLDeclaration*	ToDeclaration()	{
 11.2596 +        return 0;
 11.2597 +    }
 11.2598 +    /// Safely cast to an Unknown, or null.
 11.2599 +    virtual XMLUnknown*		ToUnknown()		{
 11.2600 +        return 0;
 11.2601 +    }
 11.2602 +
 11.2603 +    virtual const XMLElement*		ToElement() const		{
 11.2604 +        return 0;
 11.2605 +    }
 11.2606 +    virtual const XMLText*			ToText() const			{
 11.2607 +        return 0;
 11.2608 +    }
 11.2609 +    virtual const XMLComment*		ToComment() const		{
 11.2610 +        return 0;
 11.2611 +    }
 11.2612 +    virtual const XMLDocument*		ToDocument() const		{
 11.2613 +        return 0;
 11.2614 +    }
 11.2615 +    virtual const XMLDeclaration*	ToDeclaration() const	{
 11.2616 +        return 0;
 11.2617 +    }
 11.2618 +    virtual const XMLUnknown*		ToUnknown() const		{
 11.2619 +        return 0;
 11.2620 +    }
 11.2621 +
 11.2622 +    /** The meaning of 'value' changes for the specific type.
 11.2623 +    	@verbatim
 11.2624 +    	Document:	empty
 11.2625 +    	Element:	name of the element
 11.2626 +    	Comment:	the comment text
 11.2627 +    	Unknown:	the tag contents
 11.2628 +    	Text:		the text string
 11.2629 +    	@endverbatim
 11.2630 +    */
 11.2631 +    const char* Value() const			{
 11.2632 +        return _value.GetStr();
 11.2633 +    }
 11.2634 +
 11.2635 +    /** Set the Value of an XML node.
 11.2636 +    	@sa Value()
 11.2637 +    */
 11.2638 +    void SetValue( const char* val, bool staticMem=false );
 11.2639 +
 11.2640 +    /// Get the parent of this node on the DOM.
 11.2641 +    const XMLNode*	Parent() const			{
 11.2642 +        return _parent;
 11.2643 +    }
 11.2644 +
 11.2645 +    XMLNode* Parent()						{
 11.2646 +        return _parent;
 11.2647 +    }
 11.2648 +
 11.2649 +    /// Returns true if this node has no children.
 11.2650 +    bool NoChildren() const					{
 11.2651 +        return !_firstChild;
 11.2652 +    }
 11.2653 +
 11.2654 +    /// Get the first child node, or null if none exists.
 11.2655 +    const XMLNode*  FirstChild() const		{
 11.2656 +        return _firstChild;
 11.2657 +    }
 11.2658 +
 11.2659 +    XMLNode*		FirstChild()			{
 11.2660 +        return _firstChild;
 11.2661 +    }
 11.2662 +
 11.2663 +    /** Get the first child element, or optionally the first child
 11.2664 +        element with the specified name.
 11.2665 +    */
 11.2666 +    const XMLElement* FirstChildElement( const char* value=0 ) const;
 11.2667 +
 11.2668 +    XMLElement* FirstChildElement( const char* value=0 )	{
 11.2669 +        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
 11.2670 +    }
 11.2671 +
 11.2672 +    /// Get the last child node, or null if none exists.
 11.2673 +    const XMLNode*	LastChild() const						{
 11.2674 +        return _lastChild;
 11.2675 +    }
 11.2676 +
 11.2677 +    XMLNode*		LastChild()								{
 11.2678 +        return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
 11.2679 +    }
 11.2680 +
 11.2681 +    /** Get the last child element or optionally the last child
 11.2682 +        element with the specified name.
 11.2683 +    */
 11.2684 +    const XMLElement* LastChildElement( const char* value=0 ) const;
 11.2685 +
 11.2686 +    XMLElement* LastChildElement( const char* value=0 )	{
 11.2687 +        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
 11.2688 +    }
 11.2689 +
 11.2690 +    /// Get the previous (left) sibling node of this node.
 11.2691 +    const XMLNode*	PreviousSibling() const					{
 11.2692 +        return _prev;
 11.2693 +    }
 11.2694 +
 11.2695 +    XMLNode*	PreviousSibling()							{
 11.2696 +        return _prev;
 11.2697 +    }
 11.2698 +
 11.2699 +    /// Get the previous (left) sibling element of this node, with an optionally supplied name.
 11.2700 +    const XMLElement*	PreviousSiblingElement( const char* value=0 ) const ;
 11.2701 +
 11.2702 +    XMLElement*	PreviousSiblingElement( const char* value=0 ) {
 11.2703 +        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
 11.2704 +    }
 11.2705 +
 11.2706 +    /// Get the next (right) sibling node of this node.
 11.2707 +    const XMLNode*	NextSibling() const						{
 11.2708 +        return _next;
 11.2709 +    }
 11.2710 +
 11.2711 +    XMLNode*	NextSibling()								{
 11.2712 +        return _next;
 11.2713 +    }
 11.2714 +
 11.2715 +    /// Get the next (right) sibling element of this node, with an optionally supplied name.
 11.2716 +    const XMLElement*	NextSiblingElement( const char* value=0 ) const;
 11.2717 +
 11.2718 +    XMLElement*	NextSiblingElement( const char* value=0 )	{
 11.2719 +        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
 11.2720 +    }
 11.2721 +
 11.2722 +    /**
 11.2723 +    	Add a child node as the last (right) child.
 11.2724 +    */
 11.2725 +    XMLNode* InsertEndChild( XMLNode* addThis );
 11.2726 +
 11.2727 +    XMLNode* LinkEndChild( XMLNode* addThis )	{
 11.2728 +        return InsertEndChild( addThis );
 11.2729 +    }
 11.2730 +    /**
 11.2731 +    	Add a child node as the first (left) child.
 11.2732 +    */
 11.2733 +    XMLNode* InsertFirstChild( XMLNode* addThis );
 11.2734 +    /**
 11.2735 +    	Add a node after the specified child node.
 11.2736 +    */
 11.2737 +    XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
 11.2738 +
 11.2739 +    /**
 11.2740 +    	Delete all the children of this node.
 11.2741 +    */
 11.2742 +    void DeleteChildren();
 11.2743 +
 11.2744 +    /**
 11.2745 +    	Delete a child of this node.
 11.2746 +    */
 11.2747 +    void DeleteChild( XMLNode* node );
 11.2748 +
 11.2749 +    /**
 11.2750 +    	Make a copy of this node, but not its children.
 11.2751 +    	You may pass in a Document pointer that will be
 11.2752 +    	the owner of the new Node. If the 'document' is
 11.2753 +    	null, then the node returned will be allocated
 11.2754 +    	from the current Document. (this->GetDocument())
 11.2755 +
 11.2756 +    	Note: if called on a XMLDocument, this will return null.
 11.2757 +    */
 11.2758 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
 11.2759 +
 11.2760 +    /**
 11.2761 +    	Test if 2 nodes are the same, but don't test children.
 11.2762 +    	The 2 nodes do not need to be in the same Document.
 11.2763 +
 11.2764 +    	Note: if called on a XMLDocument, this will return false.
 11.2765 +    */
 11.2766 +    virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
 11.2767 +
 11.2768 +    /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
 11.2769 +    	XML tree will be conditionally visited and the host will be called back
 11.2770 +    	via the XMLVisitor interface.
 11.2771 +
 11.2772 +    	This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
 11.2773 +    	the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
 11.2774 +    	interface versus any other.)
 11.2775 +
 11.2776 +    	The interface has been based on ideas from:
 11.2777 +
 11.2778 +    	- http://www.saxproject.org/
 11.2779 +    	- http://c2.com/cgi/wiki?HierarchicalVisitorPattern
 11.2780 +
 11.2781 +    	Which are both good references for "visiting".
 11.2782 +
 11.2783 +    	An example of using Accept():
 11.2784 +    	@verbatim
 11.2785 +    	XMLPrinter printer;
 11.2786 +    	tinyxmlDoc.Accept( &printer );
 11.2787 +    	const char* xmlcstr = printer.CStr();
 11.2788 +    	@endverbatim
 11.2789 +    */
 11.2790 +    virtual bool Accept( XMLVisitor* visitor ) const = 0;
 11.2791 +
 11.2792 +    // internal
 11.2793 +    virtual char* ParseDeep( char*, StrPair* );
 11.2794 +
 11.2795 +protected:
 11.2796 +    XMLNode( XMLDocument* );
 11.2797 +    virtual ~XMLNode();
 11.2798 +    XMLNode( const XMLNode& );	// not supported
 11.2799 +    XMLNode& operator=( const XMLNode& );	// not supported
 11.2800 +
 11.2801 +    XMLDocument*	_document;
 11.2802 +    XMLNode*		_parent;
 11.2803 +    mutable StrPair	_value;
 11.2804 +
 11.2805 +    XMLNode*		_firstChild;
 11.2806 +    XMLNode*		_lastChild;
 11.2807 +
 11.2808 +    XMLNode*		_prev;
 11.2809 +    XMLNode*		_next;
 11.2810 +
 11.2811 +private:
 11.2812 +    MemPool*		_memPool;
 11.2813 +    void Unlink( XMLNode* child );
 11.2814 +};
 11.2815 +
 11.2816 +
 11.2817 +/** XML text.
 11.2818 +
 11.2819 +	Note that a text node can have child element nodes, for example:
 11.2820 +	@verbatim
 11.2821 +	<root>This is <b>bold</b></root>
 11.2822 +	@endverbatim
 11.2823 +
 11.2824 +	A text node can have 2 ways to output the next. "normal" output
 11.2825 +	and CDATA. It will default to the mode it was parsed from the XML file and
 11.2826 +	you generally want to leave it alone, but you can change the output mode with
 11.2827 +	SetCData() and query it with CData().
 11.2828 +*/
 11.2829 +class TINYXML2_LIB XMLText : public XMLNode
 11.2830 +{
 11.2831 +    friend class XMLBase;
 11.2832 +    friend class XMLDocument;
 11.2833 +public:
 11.2834 +    virtual bool Accept( XMLVisitor* visitor ) const;
 11.2835 +
 11.2836 +    virtual XMLText* ToText()			{
 11.2837 +        return this;
 11.2838 +    }
 11.2839 +    virtual const XMLText* ToText() const	{
 11.2840 +        return this;
 11.2841 +    }
 11.2842 +
 11.2843 +    /// Declare whether this should be CDATA or standard text.
 11.2844 +    void SetCData( bool isCData )			{
 11.2845 +        _isCData = isCData;
 11.2846 +    }
 11.2847 +    /// Returns true if this is a CDATA text element.
 11.2848 +    bool CData() const						{
 11.2849 +        return _isCData;
 11.2850 +    }
 11.2851 +
 11.2852 +    char* ParseDeep( char*, StrPair* endTag );
 11.2853 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
 11.2854 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
 11.2855 +
 11.2856 +protected:
 11.2857 +    XMLText( XMLDocument* doc )	: XMLNode( doc ), _isCData( false )	{}
 11.2858 +    virtual ~XMLText()												{}
 11.2859 +    XMLText( const XMLText& );	// not supported
 11.2860 +    XMLText& operator=( const XMLText& );	// not supported
 11.2861 +
 11.2862 +private:
 11.2863 +    bool _isCData;
 11.2864 +};
 11.2865 +
 11.2866 +
 11.2867 +/** An XML Comment. */
 11.2868 +class TINYXML2_LIB XMLComment : public XMLNode
 11.2869 +{
 11.2870 +    friend class XMLDocument;
 11.2871 +public:
 11.2872 +    virtual XMLComment*	ToComment()					{
 11.2873 +        return this;
 11.2874 +    }
 11.2875 +    virtual const XMLComment* ToComment() const		{
 11.2876 +        return this;
 11.2877 +    }
 11.2878 +
 11.2879 +    virtual bool Accept( XMLVisitor* visitor ) const;
 11.2880 +
 11.2881 +    char* ParseDeep( char*, StrPair* endTag );
 11.2882 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
 11.2883 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
 11.2884 +
 11.2885 +protected:
 11.2886 +    XMLComment( XMLDocument* doc );
 11.2887 +    virtual ~XMLComment();
 11.2888 +    XMLComment( const XMLComment& );	// not supported
 11.2889 +    XMLComment& operator=( const XMLComment& );	// not supported
 11.2890 +
 11.2891 +private:
 11.2892 +};
 11.2893 +
 11.2894 +
 11.2895 +/** In correct XML the declaration is the first entry in the file.
 11.2896 +	@verbatim
 11.2897 +		<?xml version="1.0" standalone="yes"?>
 11.2898 +	@endverbatim
 11.2899 +
 11.2900 +	TinyXML-2 will happily read or write files without a declaration,
 11.2901 +	however.
 11.2902 +
 11.2903 +	The text of the declaration isn't interpreted. It is parsed
 11.2904 +	and written as a string.
 11.2905 +*/
 11.2906 +class TINYXML2_LIB XMLDeclaration : public XMLNode
 11.2907 +{
 11.2908 +    friend class XMLDocument;
 11.2909 +public:
 11.2910 +    virtual XMLDeclaration*	ToDeclaration()					{
 11.2911 +        return this;
 11.2912 +    }
 11.2913 +    virtual const XMLDeclaration* ToDeclaration() const		{
 11.2914 +        return this;
 11.2915 +    }
 11.2916 +
 11.2917 +    virtual bool Accept( XMLVisitor* visitor ) const;
 11.2918 +
 11.2919 +    char* ParseDeep( char*, StrPair* endTag );
 11.2920 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
 11.2921 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
 11.2922 +
 11.2923 +protected:
 11.2924 +    XMLDeclaration( XMLDocument* doc );
 11.2925 +    virtual ~XMLDeclaration();
 11.2926 +    XMLDeclaration( const XMLDeclaration& );	// not supported
 11.2927 +    XMLDeclaration& operator=( const XMLDeclaration& );	// not supported
 11.2928 +};
 11.2929 +
 11.2930 +
 11.2931 +/** Any tag that TinyXML-2 doesn't recognize is saved as an
 11.2932 +	unknown. It is a tag of text, but should not be modified.
 11.2933 +	It will be written back to the XML, unchanged, when the file
 11.2934 +	is saved.
 11.2935 +
 11.2936 +	DTD tags get thrown into XMLUnknowns.
 11.2937 +*/
 11.2938 +class TINYXML2_LIB XMLUnknown : public XMLNode
 11.2939 +{
 11.2940 +    friend class XMLDocument;
 11.2941 +public:
 11.2942 +    virtual XMLUnknown*	ToUnknown()					{
 11.2943 +        return this;
 11.2944 +    }
 11.2945 +    virtual const XMLUnknown* ToUnknown() const		{
 11.2946 +        return this;
 11.2947 +    }
 11.2948 +
 11.2949 +    virtual bool Accept( XMLVisitor* visitor ) const;
 11.2950 +
 11.2951 +    char* ParseDeep( char*, StrPair* endTag );
 11.2952 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
 11.2953 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
 11.2954 +
 11.2955 +protected:
 11.2956 +    XMLUnknown( XMLDocument* doc );
 11.2957 +    virtual ~XMLUnknown();
 11.2958 +    XMLUnknown( const XMLUnknown& );	// not supported
 11.2959 +    XMLUnknown& operator=( const XMLUnknown& );	// not supported
 11.2960 +};
 11.2961 +
 11.2962 +
 11.2963 +enum XMLError {
 11.2964 +    XML_NO_ERROR = 0,
 11.2965 +    XML_SUCCESS = 0,
 11.2966 +
 11.2967 +    XML_NO_ATTRIBUTE,
 11.2968 +    XML_WRONG_ATTRIBUTE_TYPE,
 11.2969 +
 11.2970 +    XML_ERROR_FILE_NOT_FOUND,
 11.2971 +    XML_ERROR_FILE_COULD_NOT_BE_OPENED,
 11.2972 +    XML_ERROR_FILE_READ_ERROR,
 11.2973 +    XML_ERROR_ELEMENT_MISMATCH,
 11.2974 +    XML_ERROR_PARSING_ELEMENT,
 11.2975 +    XML_ERROR_PARSING_ATTRIBUTE,
 11.2976 +    XML_ERROR_IDENTIFYING_TAG,
 11.2977 +    XML_ERROR_PARSING_TEXT,
 11.2978 +    XML_ERROR_PARSING_CDATA,
 11.2979 +    XML_ERROR_PARSING_COMMENT,
 11.2980 +    XML_ERROR_PARSING_DECLARATION,
 11.2981 +    XML_ERROR_PARSING_UNKNOWN,
 11.2982 +    XML_ERROR_EMPTY_DOCUMENT,
 11.2983 +    XML_ERROR_MISMATCHED_ELEMENT,
 11.2984 +    XML_ERROR_PARSING,
 11.2985 +
 11.2986 +    XML_CAN_NOT_CONVERT_TEXT,
 11.2987 +    XML_NO_TEXT_NODE
 11.2988 +};
 11.2989 +
 11.2990 +
 11.2991 +/** An attribute is a name-value pair. Elements have an arbitrary
 11.2992 +	number of attributes, each with a unique name.
 11.2993 +
 11.2994 +	@note The attributes are not XMLNodes. You may only query the
 11.2995 +	Next() attribute in a list.
 11.2996 +*/
 11.2997 +class TINYXML2_LIB XMLAttribute
 11.2998 +{
 11.2999 +    friend class XMLElement;
 11.3000 +public:
 11.3001 +    /// The name of the attribute.
 11.3002 +    const char* Name() const {
 11.3003 +        return _name.GetStr();
 11.3004 +    }
 11.3005 +    /// The value of the attribute.
 11.3006 +    const char* Value() const {
 11.3007 +        return _value.GetStr();
 11.3008 +    }
 11.3009 +    /// The next attribute in the list.
 11.3010 +    const XMLAttribute* Next() const {
 11.3011 +        return _next;
 11.3012 +    }
 11.3013 +
 11.3014 +    /** IntValue interprets the attribute as an integer, and returns the value.
 11.3015 +        If the value isn't an integer, 0 will be returned. There is no error checking;
 11.3016 +    	use QueryIntValue() if you need error checking.
 11.3017 +    */
 11.3018 +    int		 IntValue() const				{
 11.3019 +        int i=0;
 11.3020 +        QueryIntValue( &i );
 11.3021 +        return i;
 11.3022 +    }
 11.3023 +    /// Query as an unsigned integer. See IntValue()
 11.3024 +    unsigned UnsignedValue() const			{
 11.3025 +        unsigned i=0;
 11.3026 +        QueryUnsignedValue( &i );
 11.3027 +        return i;
 11.3028 +    }
 11.3029 +    /// Query as a boolean. See IntValue()
 11.3030 +    bool	 BoolValue() const				{
 11.3031 +        bool b=false;
 11.3032 +        QueryBoolValue( &b );
 11.3033 +        return b;
 11.3034 +    }
 11.3035 +    /// Query as a double. See IntValue()
 11.3036 +    double 	 DoubleValue() const			{
 11.3037 +        double d=0;
 11.3038 +        QueryDoubleValue( &d );
 11.3039 +        return d;
 11.3040 +    }
 11.3041 +    /// Query as a float. See IntValue()
 11.3042 +    float	 FloatValue() const				{
 11.3043 +        float f=0;
 11.3044 +        QueryFloatValue( &f );
 11.3045 +        return f;
 11.3046 +    }
 11.3047 +
 11.3048 +    /** QueryIntValue interprets the attribute as an integer, and returns the value
 11.3049 +    	in the provided parameter. The function will return XML_NO_ERROR on success,
 11.3050 +    	and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
 11.3051 +    */
 11.3052 +    XMLError QueryIntValue( int* value ) const;
 11.3053 +    /// See QueryIntValue
 11.3054 +    XMLError QueryUnsignedValue( unsigned int* value ) const;
 11.3055 +    /// See QueryIntValue
 11.3056 +    XMLError QueryBoolValue( bool* value ) const;
 11.3057 +    /// See QueryIntValue
 11.3058 +    XMLError QueryDoubleValue( double* value ) const;
 11.3059 +    /// See QueryIntValue
 11.3060 +    XMLError QueryFloatValue( float* value ) const;
 11.3061 +
 11.3062 +    /// Set the attribute to a string value.
 11.3063 +    void SetAttribute( const char* value );
 11.3064 +    /// Set the attribute to value.
 11.3065 +    void SetAttribute( int value );
 11.3066 +    /// Set the attribute to value.
 11.3067 +    void SetAttribute( unsigned value );
 11.3068 +    /// Set the attribute to value.
 11.3069 +    void SetAttribute( bool value );
 11.3070 +    /// Set the attribute to value.
 11.3071 +    void SetAttribute( double value );
 11.3072 +    /// Set the attribute to value.
 11.3073 +    void SetAttribute( float value );
 11.3074 +
 11.3075 +private:
 11.3076 +    enum { BUF_SIZE = 200 };
 11.3077 +
 11.3078 +    XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
 11.3079 +    virtual ~XMLAttribute()	{}
 11.3080 +
 11.3081 +    XMLAttribute( const XMLAttribute& );	// not supported
 11.3082 +    void operator=( const XMLAttribute& );	// not supported
 11.3083 +    void SetName( const char* name );
 11.3084 +
 11.3085 +    char* ParseDeep( char* p, bool processEntities );
 11.3086 +
 11.3087 +    mutable StrPair _name;
 11.3088 +    mutable StrPair _value;
 11.3089 +    XMLAttribute*   _next;
 11.3090 +    MemPool*        _memPool;
 11.3091 +};
 11.3092 +
 11.3093 +
 11.3094 +/** The element is a container class. It has a value, the element name,
 11.3095 +	and can contain other elements, text, comments, and unknowns.
 11.3096 +	Elements also contain an arbitrary number of attributes.
 11.3097 +*/
 11.3098 +class TINYXML2_LIB XMLElement : public XMLNode
 11.3099 +{
 11.3100 +    friend class XMLBase;
 11.3101 +    friend class XMLDocument;
 11.3102 +public:
 11.3103 +    /// Get the name of an element (which is the Value() of the node.)
 11.3104 +    const char* Name() const		{
 11.3105 +        return Value();
 11.3106 +    }
 11.3107 +    /// Set the name of the element.
 11.3108 +    void SetName( const char* str, bool staticMem=false )	{
 11.3109 +        SetValue( str, staticMem );
 11.3110 +    }
 11.3111 +
 11.3112 +    virtual XMLElement* ToElement()				{
 11.3113 +        return this;
 11.3114 +    }
 11.3115 +    virtual const XMLElement* ToElement() const {
 11.3116 +        return this;
 11.3117 +    }
 11.3118 +    virtual bool Accept( XMLVisitor* visitor ) const;
 11.3119 +
 11.3120 +    /** Given an attribute name, Attribute() returns the value
 11.3121 +    	for the attribute of that name, or null if none
 11.3122 +    	exists. For example:
 11.3123 +
 11.3124 +    	@verbatim
 11.3125 +    	const char* value = ele->Attribute( "foo" );
 11.3126 +    	@endverbatim
 11.3127 +
 11.3128 +    	The 'value' parameter is normally null. However, if specified,
 11.3129 +    	the attribute will only be returned if the 'name' and 'value'
 11.3130 +    	match. This allow you to write code:
 11.3131 +
 11.3132 +    	@verbatim
 11.3133 +    	if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
 11.3134 +    	@endverbatim
 11.3135 +
 11.3136 +    	rather than:
 11.3137 +    	@verbatim
 11.3138 +    	if ( ele->Attribute( "foo" ) ) {
 11.3139 +    		if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
 11.3140 +    	}
 11.3141 +    	@endverbatim
 11.3142 +    */
 11.3143 +    const char* Attribute( const char* name, const char* value=0 ) const;
 11.3144 +
 11.3145 +    /** Given an attribute name, IntAttribute() returns the value
 11.3146 +    	of the attribute interpreted as an integer. 0 will be
 11.3147 +    	returned if there is an error. For a method with error
 11.3148 +    	checking, see QueryIntAttribute()
 11.3149 +    */
 11.3150 +    int		 IntAttribute( const char* name ) const		{
 11.3151 +        int i=0;
 11.3152 +        QueryIntAttribute( name, &i );
 11.3153 +        return i;
 11.3154 +    }
 11.3155 +    /// See IntAttribute()
 11.3156 +    unsigned UnsignedAttribute( const char* name ) const {
 11.3157 +        unsigned i=0;
 11.3158 +        QueryUnsignedAttribute( name, &i );
 11.3159 +        return i;
 11.3160 +    }
 11.3161 +    /// See IntAttribute()
 11.3162 +    bool	 BoolAttribute( const char* name ) const	{
 11.3163 +        bool b=false;
 11.3164 +        QueryBoolAttribute( name, &b );
 11.3165 +        return b;
 11.3166 +    }
 11.3167 +    /// See IntAttribute()
 11.3168 +    double 	 DoubleAttribute( const char* name ) const	{
 11.3169 +        double d=0;
 11.3170 +        QueryDoubleAttribute( name, &d );
 11.3171 +        return d;
 11.3172 +    }
 11.3173 +    /// See IntAttribute()
 11.3174 +    float	 FloatAttribute( const char* name ) const	{
 11.3175 +        float f=0;
 11.3176 +        QueryFloatAttribute( name, &f );
 11.3177 +        return f;
 11.3178 +    }
 11.3179 +
 11.3180 +    /** Given an attribute name, QueryIntAttribute() returns
 11.3181 +    	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
 11.3182 +    	can't be performed, or XML_NO_ATTRIBUTE if the attribute
 11.3183 +    	doesn't exist. If successful, the result of the conversion
 11.3184 +    	will be written to 'value'. If not successful, nothing will
 11.3185 +    	be written to 'value'. This allows you to provide default
 11.3186 +    	value:
 11.3187 +
 11.3188 +    	@verbatim
 11.3189 +    	int value = 10;
 11.3190 +    	QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
 11.3191 +    	@endverbatim
 11.3192 +    */
 11.3193 +    XMLError QueryIntAttribute( const char* name, int* value ) const				{
 11.3194 +        const XMLAttribute* a = FindAttribute( name );
 11.3195 +        if ( !a ) {
 11.3196 +            return XML_NO_ATTRIBUTE;
 11.3197 +        }
 11.3198 +        return a->QueryIntValue( value );
 11.3199 +    }
 11.3200 +    /// See QueryIntAttribute()
 11.3201 +    XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const	{
 11.3202 +        const XMLAttribute* a = FindAttribute( name );
 11.3203 +        if ( !a ) {
 11.3204 +            return XML_NO_ATTRIBUTE;
 11.3205 +        }
 11.3206 +        return a->QueryUnsignedValue( value );
 11.3207 +    }
 11.3208 +    /// See QueryIntAttribute()
 11.3209 +    XMLError QueryBoolAttribute( const char* name, bool* value ) const				{
 11.3210 +        const XMLAttribute* a = FindAttribute( name );
 11.3211 +        if ( !a ) {
 11.3212 +            return XML_NO_ATTRIBUTE;
 11.3213 +        }
 11.3214 +        return a->QueryBoolValue( value );
 11.3215 +    }
 11.3216 +    /// See QueryIntAttribute()
 11.3217 +    XMLError QueryDoubleAttribute( const char* name, double* value ) const			{
 11.3218 +        const XMLAttribute* a = FindAttribute( name );
 11.3219 +        if ( !a ) {
 11.3220 +            return XML_NO_ATTRIBUTE;
 11.3221 +        }
 11.3222 +        return a->QueryDoubleValue( value );
 11.3223 +    }
 11.3224 +    /// See QueryIntAttribute()
 11.3225 +    XMLError QueryFloatAttribute( const char* name, float* value ) const			{
 11.3226 +        const XMLAttribute* a = FindAttribute( name );
 11.3227 +        if ( !a ) {
 11.3228 +            return XML_NO_ATTRIBUTE;
 11.3229 +        }
 11.3230 +        return a->QueryFloatValue( value );
 11.3231 +    }
 11.3232 +
 11.3233 +	
 11.3234 +    /** Given an attribute name, QueryAttribute() returns
 11.3235 +    	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
 11.3236 +    	can't be performed, or XML_NO_ATTRIBUTE if the attribute
 11.3237 +    	doesn't exist. It is overloaded for the primitive types,
 11.3238 +		and is a generally more convenient replacement of
 11.3239 +		QueryIntAttribute() and related functions.
 11.3240 +		
 11.3241 +		If successful, the result of the conversion
 11.3242 +    	will be written to 'value'. If not successful, nothing will
 11.3243 +    	be written to 'value'. This allows you to provide default
 11.3244 +    	value:
 11.3245 +
 11.3246 +    	@verbatim
 11.3247 +    	int value = 10;
 11.3248 +    	QueryAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
 11.3249 +    	@endverbatim
 11.3250 +    */
 11.3251 +	int QueryAttribute( const char* name, int* value ) const {
 11.3252 +		return QueryIntAttribute( name, value );
 11.3253 +	}
 11.3254 +
 11.3255 +	int QueryAttribute( const char* name, unsigned int* value ) const {
 11.3256 +		return QueryUnsignedAttribute( name, value );
 11.3257 +	}
 11.3258 +
 11.3259 +	int QueryAttribute( const char* name, bool* value ) const {
 11.3260 +		return QueryBoolAttribute( name, value );
 11.3261 +	}
 11.3262 +
 11.3263 +	int QueryAttribute( const char* name, double* value ) const {
 11.3264 +		return QueryDoubleAttribute( name, value );
 11.3265 +	}
 11.3266 +
 11.3267 +	int QueryAttribute( const char* name, float* value ) const {
 11.3268 +		return QueryFloatAttribute( name, value );
 11.3269 +	}
 11.3270 +
 11.3271 +	/// Sets the named attribute to value.
 11.3272 +    void SetAttribute( const char* name, const char* value )	{
 11.3273 +        XMLAttribute* a = FindOrCreateAttribute( name );
 11.3274 +        a->SetAttribute( value );
 11.3275 +    }
 11.3276 +    /// Sets the named attribute to value.
 11.3277 +    void SetAttribute( const char* name, int value )			{
 11.3278 +        XMLAttribute* a = FindOrCreateAttribute( name );
 11.3279 +        a->SetAttribute( value );
 11.3280 +    }
 11.3281 +    /// Sets the named attribute to value.
 11.3282 +    void SetAttribute( const char* name, unsigned value )		{
 11.3283 +        XMLAttribute* a = FindOrCreateAttribute( name );
 11.3284 +        a->SetAttribute( value );
 11.3285 +    }
 11.3286 +    /// Sets the named attribute to value.
 11.3287 +    void SetAttribute( const char* name, bool value )			{
 11.3288 +        XMLAttribute* a = FindOrCreateAttribute( name );
 11.3289 +        a->SetAttribute( value );
 11.3290 +    }
 11.3291 +    /// Sets the named attribute to value.
 11.3292 +    void SetAttribute( const char* name, double value )		{
 11.3293 +        XMLAttribute* a = FindOrCreateAttribute( name );
 11.3294 +        a->SetAttribute( value );
 11.3295 +    }
 11.3296 +
 11.3297 +    /**
 11.3298 +    	Delete an attribute.
 11.3299 +    */
 11.3300 +    void DeleteAttribute( const char* name );
 11.3301 +
 11.3302 +    /// Return the first attribute in the list.
 11.3303 +    const XMLAttribute* FirstAttribute() const {
 11.3304 +        return _rootAttribute;
 11.3305 +    }
 11.3306 +    /// Query a specific attribute in the list.
 11.3307 +    const XMLAttribute* FindAttribute( const char* name ) const;
 11.3308 +
 11.3309 +    /** Convenience function for easy access to the text inside an element. Although easy
 11.3310 +    	and concise, GetText() is limited compared to getting the XMLText child
 11.3311 +    	and accessing it directly.
 11.3312 +
 11.3313 +    	If the first child of 'this' is a XMLText, the GetText()
 11.3314 +    	returns the character string of the Text node, else null is returned.
 11.3315 +
 11.3316 +    	This is a convenient method for getting the text of simple contained text:
 11.3317 +    	@verbatim
 11.3318 +    	<foo>This is text</foo>
 11.3319 +    		const char* str = fooElement->GetText();
 11.3320 +    	@endverbatim
 11.3321 +
 11.3322 +    	'str' will be a pointer to "This is text".
 11.3323 +
 11.3324 +    	Note that this function can be misleading. If the element foo was created from
 11.3325 +    	this XML:
 11.3326 +    	@verbatim
 11.3327 +    		<foo><b>This is text</b></foo>
 11.3328 +    	@endverbatim
 11.3329 +
 11.3330 +    	then the value of str would be null. The first child node isn't a text node, it is
 11.3331 +    	another element. From this XML:
 11.3332 +    	@verbatim
 11.3333 +    		<foo>This is <b>text</b></foo>
 11.3334 +    	@endverbatim
 11.3335 +    	GetText() will return "This is ".
 11.3336 +    */
 11.3337 +    const char* GetText() const;
 11.3338 +
 11.3339 +    /**
 11.3340 +    	Convenience method to query the value of a child text node. This is probably best
 11.3341 +    	shown by example. Given you have a document is this form:
 11.3342 +    	@verbatim
 11.3343 +    		<point>
 11.3344 +    			<x>1</x>
 11.3345 +    			<y>1.4</y>
 11.3346 +    		</point>
 11.3347 +    	@endverbatim
 11.3348 +
 11.3349 +    	The QueryIntText() and similar functions provide a safe and easier way to get to the
 11.3350 +    	"value" of x and y.
 11.3351 +
 11.3352 +    	@verbatim
 11.3353 +    		int x = 0;
 11.3354 +    		float y = 0;	// types of x and y are contrived for example
 11.3355 +    		const XMLElement* xElement = pointElement->FirstChildElement( "x" );
 11.3356 +    		const XMLElement* yElement = pointElement->FirstChildElement( "y" );
 11.3357 +    		xElement->QueryIntText( &x );
 11.3358 +    		yElement->QueryFloatText( &y );
 11.3359 +    	@endverbatim
 11.3360 +
 11.3361 +    	@returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
 11.3362 +    			 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
 11.3363 +
 11.3364 +    */
 11.3365 +    XMLError QueryIntText( int* ival ) const;
 11.3366 +    /// See QueryIntText()
 11.3367 +    XMLError QueryUnsignedText( unsigned* uval ) const;
 11.3368 +    /// See QueryIntText()
 11.3369 +    XMLError QueryBoolText( bool* bval ) const;
 11.3370 +    /// See QueryIntText()
 11.3371 +    XMLError QueryDoubleText( double* dval ) const;
 11.3372 +    /// See QueryIntText()
 11.3373 +    XMLError QueryFloatText( float* fval ) const;
 11.3374 +
 11.3375 +    // internal:
 11.3376 +    enum {
 11.3377 +        OPEN,		// <foo>
 11.3378 +        CLOSED,		// <foo/>
 11.3379 +        CLOSING		// </foo>
 11.3380 +    };
 11.3381 +    int ClosingType() const {
 11.3382 +        return _closingType;
 11.3383 +    }
 11.3384 +    char* ParseDeep( char* p, StrPair* endTag );
 11.3385 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
 11.3386 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
 11.3387 +
 11.3388 +private:
 11.3389 +    XMLElement( XMLDocument* doc );
 11.3390 +    virtual ~XMLElement();
 11.3391 +    XMLElement( const XMLElement& );	// not supported
 11.3392 +    void operator=( const XMLElement& );	// not supported
 11.3393 +
 11.3394 +    XMLAttribute* FindAttribute( const char* name );
 11.3395 +    XMLAttribute* FindOrCreateAttribute( const char* name );
 11.3396 +    //void LinkAttribute( XMLAttribute* attrib );
 11.3397 +    char* ParseAttributes( char* p );
 11.3398 +
 11.3399 +    int _closingType;
 11.3400 +    // The attribute list is ordered; there is no 'lastAttribute'
 11.3401 +    // because the list needs to be scanned for dupes before adding
 11.3402 +    // a new attribute.
 11.3403 +    XMLAttribute* _rootAttribute;
 11.3404 +};
 11.3405 +
 11.3406 +
 11.3407 +enum Whitespace {
 11.3408 +    PRESERVE_WHITESPACE,
 11.3409 +    COLLAPSE_WHITESPACE
 11.3410 +};
 11.3411 +
 11.3412 +
 11.3413 +/** A Document binds together all the functionality.
 11.3414 +	It can be saved, loaded, and printed to the screen.
 11.3415 +	All Nodes are connected and allocated to a Document.
 11.3416 +	If the Document is deleted, all its Nodes are also deleted.
 11.3417 +*/
 11.3418 +class TINYXML2_LIB XMLDocument : public XMLNode
 11.3419 +{
 11.3420 +    friend class XMLElement;
 11.3421 +public:
 11.3422 +    /// constructor
 11.3423 +    XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
 11.3424 +    ~XMLDocument();
 11.3425 +
 11.3426 +    virtual XMLDocument* ToDocument()				{
 11.3427 +        return this;
 11.3428 +    }
 11.3429 +    virtual const XMLDocument* ToDocument() const	{
 11.3430 +        return this;
 11.3431 +    }
 11.3432 +
 11.3433 +    /**
 11.3434 +    	Parse an XML file from a character string.
 11.3435 +    	Returns XML_NO_ERROR (0) on success, or
 11.3436 +    	an errorID.
 11.3437 +
 11.3438 +    	You may optionally pass in the 'nBytes', which is
 11.3439 +    	the number of bytes which will be parsed. If not
 11.3440 +    	specified, TinyXML-2 will assume 'xml' points to a
 11.3441 +    	null terminated string.
 11.3442 +    */
 11.3443 +    XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
 11.3444 +
 11.3445 +    /**
 11.3446 +    	Load an XML file from disk.
 11.3447 +    	Returns XML_NO_ERROR (0) on success, or
 11.3448 +    	an errorID.
 11.3449 +    */
 11.3450 +    XMLError LoadFile( const char* filename );
 11.3451 +
 11.3452 +    /**
 11.3453 +    	Load an XML file from disk. You are responsible
 11.3454 +    	for providing and closing the FILE*.
 11.3455 +
 11.3456 +    	Returns XML_NO_ERROR (0) on success, or
 11.3457 +    	an errorID.
 11.3458 +    */
 11.3459 +    XMLError LoadFile( FILE* );
 11.3460 +
 11.3461 +    /**
 11.3462 +    	Save the XML file to disk.
 11.3463 +    	Returns XML_NO_ERROR (0) on success, or
 11.3464 +    	an errorID.
 11.3465 +    */
 11.3466 +    XMLError SaveFile( const char* filename, bool compact = false );
 11.3467 +
 11.3468 +    /**
 11.3469 +    	Save the XML file to disk. You are responsible
 11.3470 +    	for providing and closing the FILE*.
 11.3471 +
 11.3472 +    	Returns XML_NO_ERROR (0) on success, or
 11.3473 +    	an errorID.
 11.3474 +    */
 11.3475 +    XMLError SaveFile( FILE* fp, bool compact = false );
 11.3476 +
 11.3477 +    bool ProcessEntities() const		{
 11.3478 +        return _processEntities;
 11.3479 +    }
 11.3480 +    Whitespace WhitespaceMode() const	{
 11.3481 +        return _whitespace;
 11.3482 +    }
 11.3483 +
 11.3484 +    /**
 11.3485 +    	Returns true if this document has a leading Byte Order Mark of UTF8.
 11.3486 +    */
 11.3487 +    bool HasBOM() const {
 11.3488 +        return _writeBOM;
 11.3489 +    }
 11.3490 +    /** Sets whether to write the BOM when writing the file.
 11.3491 +    */
 11.3492 +    void SetBOM( bool useBOM ) {
 11.3493 +        _writeBOM = useBOM;
 11.3494 +    }
 11.3495 +
 11.3496 +    /** Return the root element of DOM. Equivalent to FirstChildElement().
 11.3497 +        To get the first node, use FirstChild().
 11.3498 +    */
 11.3499 +    XMLElement* RootElement()				{
 11.3500 +        return FirstChildElement();
 11.3501 +    }
 11.3502 +    const XMLElement* RootElement() const	{
 11.3503 +        return FirstChildElement();
 11.3504 +    }
 11.3505 +
 11.3506 +    /** Print the Document. If the Printer is not provided, it will
 11.3507 +        print to stdout. If you provide Printer, this can print to a file:
 11.3508 +    	@verbatim
 11.3509 +    	XMLPrinter printer( fp );
 11.3510 +    	doc.Print( &printer );
 11.3511 +    	@endverbatim
 11.3512 +
 11.3513 +    	Or you can use a printer to print to memory:
 11.3514 +    	@verbatim
 11.3515 +    	XMLPrinter printer;
 11.3516 +    	doc.Print( &printer );
 11.3517 +    	// printer.CStr() has a const char* to the XML
 11.3518 +    	@endverbatim
 11.3519 +    */
 11.3520 +    void Print( XMLPrinter* streamer=0 ) const;
 11.3521 +    virtual bool Accept( XMLVisitor* visitor ) const;
 11.3522 +
 11.3523 +    /**
 11.3524 +    	Create a new Element associated with
 11.3525 +    	this Document. The memory for the Element
 11.3526 +    	is managed by the Document.
 11.3527 +    */
 11.3528 +    XMLElement* NewElement( const char* name );
 11.3529 +    /**
 11.3530 +    	Create a new Comment associated with
 11.3531 +    	this Document. The memory for the Comment
 11.3532 +    	is managed by the Document.
 11.3533 +    */
 11.3534 +    XMLComment* NewComment( const char* comment );
 11.3535 +    /**
 11.3536 +    	Create a new Text associated with
 11.3537 +    	this Document. The memory for the Text
 11.3538 +    	is managed by the Document.
 11.3539 +    */
 11.3540 +    XMLText* NewText( const char* text );
 11.3541 +    /**
 11.3542 +    	Create a new Declaration associated with
 11.3543 +    	this Document. The memory for the object
 11.3544 +    	is managed by the Document.
 11.3545 +
 11.3546 +    	If the 'text' param is null, the standard
 11.3547 +    	declaration is used.:
 11.3548 +    	@verbatim
 11.3549 +    		<?xml version="1.0" encoding="UTF-8"?>
 11.3550 +    	@endverbatim
 11.3551 +    */
 11.3552 +    XMLDeclaration* NewDeclaration( const char* text=0 );
 11.3553 +    /**
 11.3554 +    	Create a new Unknown associated with
 11.3555 +    	this Document. The memory for the object
 11.3556 +    	is managed by the Document.
 11.3557 +    */
 11.3558 +    XMLUnknown* NewUnknown( const char* text );
 11.3559 +
 11.3560 +    /**
 11.3561 +    	Delete a node associated with this document.
 11.3562 +    	It will be unlinked from the DOM.
 11.3563 +    */
 11.3564 +    void DeleteNode( XMLNode* node )	{
 11.3565 +        node->_parent->DeleteChild( node );
 11.3566 +    }
 11.3567 +
 11.3568 +    void SetError( XMLError error, const char* str1, const char* str2 );
 11.3569 +
 11.3570 +    /// Return true if there was an error parsing the document.
 11.3571 +    bool Error() const {
 11.3572 +        return _errorID != XML_NO_ERROR;
 11.3573 +    }
 11.3574 +    /// Return the errorID.
 11.3575 +    XMLError  ErrorID() const {
 11.3576 +        return _errorID;
 11.3577 +    }
 11.3578 +    /// Return a possibly helpful diagnostic location or string.
 11.3579 +    const char* GetErrorStr1() const {
 11.3580 +        return _errorStr1;
 11.3581 +    }
 11.3582 +    /// Return a possibly helpful secondary diagnostic location or string.
 11.3583 +    const char* GetErrorStr2() const {
 11.3584 +        return _errorStr2;
 11.3585 +    }
 11.3586 +    /// If there is an error, print it to stdout.
 11.3587 +    void PrintError() const;
 11.3588 +    
 11.3589 +    /// Clear the document, resetting it to the initial state.
 11.3590 +    void Clear();
 11.3591 +
 11.3592 +    // internal
 11.3593 +    char* Identify( char* p, XMLNode** node );
 11.3594 +
 11.3595 +    virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{
 11.3596 +        return 0;
 11.3597 +    }
 11.3598 +    virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{
 11.3599 +        return false;
 11.3600 +    }
 11.3601 +
 11.3602 +private:
 11.3603 +    XMLDocument( const XMLDocument& );	// not supported
 11.3604 +    void operator=( const XMLDocument& );	// not supported
 11.3605 +
 11.3606 +    bool        _writeBOM;
 11.3607 +    bool        _processEntities;
 11.3608 +    XMLError    _errorID;
 11.3609 +    Whitespace  _whitespace;
 11.3610 +    const char* _errorStr1;
 11.3611 +    const char* _errorStr2;
 11.3612 +    char*       _charBuffer;
 11.3613 +
 11.3614 +    MemPoolT< sizeof(XMLElement) >	 _elementPool;
 11.3615 +    MemPoolT< sizeof(XMLAttribute) > _attributePool;
 11.3616 +    MemPoolT< sizeof(XMLText) >		 _textPool;
 11.3617 +    MemPoolT< sizeof(XMLComment) >	 _commentPool;
 11.3618 +};
 11.3619 +
 11.3620 +
 11.3621 +/**
 11.3622 +	A XMLHandle is a class that wraps a node pointer with null checks; this is
 11.3623 +	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
 11.3624 +	DOM structure. It is a separate utility class.
 11.3625 +
 11.3626 +	Take an example:
 11.3627 +	@verbatim
 11.3628 +	<Document>
 11.3629 +		<Element attributeA = "valueA">
 11.3630 +			<Child attributeB = "value1" />
 11.3631 +			<Child attributeB = "value2" />
 11.3632 +		</Element>
 11.3633 +	</Document>
 11.3634 +	@endverbatim
 11.3635 +
 11.3636 +	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
 11.3637 +	easy to write a *lot* of code that looks like:
 11.3638 +
 11.3639 +	@verbatim
 11.3640 +	XMLElement* root = document.FirstChildElement( "Document" );
 11.3641 +	if ( root )
 11.3642 +	{
 11.3643 +		XMLElement* element = root->FirstChildElement( "Element" );
 11.3644 +		if ( element )
 11.3645 +		{
 11.3646 +			XMLElement* child = element->FirstChildElement( "Child" );
 11.3647 +			if ( child )
 11.3648 +			{
 11.3649 +				XMLElement* child2 = child->NextSiblingElement( "Child" );
 11.3650 +				if ( child2 )
 11.3651 +				{
 11.3652 +					// Finally do something useful.
 11.3653 +	@endverbatim
 11.3654 +
 11.3655 +	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
 11.3656 +	of such code. A XMLHandle checks for null pointers so it is perfectly safe
 11.3657 +	and correct to use:
 11.3658 +
 11.3659 +	@verbatim
 11.3660 +	XMLHandle docHandle( &document );
 11.3661 +	XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
 11.3662 +	if ( child2 )
 11.3663 +	{
 11.3664 +		// do something useful
 11.3665 +	@endverbatim
 11.3666 +
 11.3667 +	Which is MUCH more concise and useful.
 11.3668 +
 11.3669 +	It is also safe to copy handles - internally they are nothing more than node pointers.
 11.3670 +	@verbatim
 11.3671 +	XMLHandle handleCopy = handle;
 11.3672 +	@endverbatim
 11.3673 +
 11.3674 +	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
 11.3675 +*/
 11.3676 +class TINYXML2_LIB XMLHandle
 11.3677 +{
 11.3678 +public:
 11.3679 +    /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
 11.3680 +    XMLHandle( XMLNode* node )												{
 11.3681 +        _node = node;
 11.3682 +    }
 11.3683 +    /// Create a handle from a node.
 11.3684 +    XMLHandle( XMLNode& node )												{
 11.3685 +        _node = &node;
 11.3686 +    }
 11.3687 +    /// Copy constructor
 11.3688 +    XMLHandle( const XMLHandle& ref )										{
 11.3689 +        _node = ref._node;
 11.3690 +    }
 11.3691 +    /// Assignment
 11.3692 +    XMLHandle& operator=( const XMLHandle& ref )							{
 11.3693 +        _node = ref._node;
 11.3694 +        return *this;
 11.3695 +    }
 11.3696 +
 11.3697 +    /// Get the first child of this handle.
 11.3698 +    XMLHandle FirstChild() 													{
 11.3699 +        return XMLHandle( _node ? _node->FirstChild() : 0 );
 11.3700 +    }
 11.3701 +    /// Get the first child element of this handle.
 11.3702 +    XMLHandle FirstChildElement( const char* value=0 )						{
 11.3703 +        return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
 11.3704 +    }
 11.3705 +    /// Get the last child of this handle.
 11.3706 +    XMLHandle LastChild()													{
 11.3707 +        return XMLHandle( _node ? _node->LastChild() : 0 );
 11.3708 +    }
 11.3709 +    /// Get the last child element of this handle.
 11.3710 +    XMLHandle LastChildElement( const char* _value=0 )						{
 11.3711 +        return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
 11.3712 +    }
 11.3713 +    /// Get the previous sibling of this handle.
 11.3714 +    XMLHandle PreviousSibling()												{
 11.3715 +        return XMLHandle( _node ? _node->PreviousSibling() : 0 );
 11.3716 +    }
 11.3717 +    /// Get the previous sibling element of this handle.
 11.3718 +    XMLHandle PreviousSiblingElement( const char* _value=0 )				{
 11.3719 +        return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
 11.3720 +    }
 11.3721 +    /// Get the next sibling of this handle.
 11.3722 +    XMLHandle NextSibling()													{
 11.3723 +        return XMLHandle( _node ? _node->NextSibling() : 0 );
 11.3724 +    }
 11.3725 +    /// Get the next sibling element of this handle.
 11.3726 +    XMLHandle NextSiblingElement( const char* _value=0 )					{
 11.3727 +        return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
 11.3728 +    }
 11.3729 +
 11.3730 +    /// Safe cast to XMLNode. This can return null.
 11.3731 +    XMLNode* ToNode()							{
 11.3732 +        return _node;
 11.3733 +    }
 11.3734 +    /// Safe cast to XMLElement. This can return null.
 11.3735 +    XMLElement* ToElement() 					{
 11.3736 +        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
 11.3737 +    }
 11.3738 +    /// Safe cast to XMLText. This can return null.
 11.3739 +    XMLText* ToText() 							{
 11.3740 +        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
 11.3741 +    }
 11.3742 +    /// Safe cast to XMLUnknown. This can return null.
 11.3743 +    XMLUnknown* ToUnknown() 					{
 11.3744 +        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
 11.3745 +    }
 11.3746 +    /// Safe cast to XMLDeclaration. This can return null.
 11.3747 +    XMLDeclaration* ToDeclaration() 			{
 11.3748 +        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
 11.3749 +    }
 11.3750 +
 11.3751 +private:
 11.3752 +    XMLNode* _node;
 11.3753 +};
 11.3754 +
 11.3755 +
 11.3756 +/**
 11.3757 +	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
 11.3758 +	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
 11.3759 +*/
 11.3760 +class TINYXML2_LIB XMLConstHandle
 11.3761 +{
 11.3762 +public:
 11.3763 +    XMLConstHandle( const XMLNode* node )											{
 11.3764 +        _node = node;
 11.3765 +    }
 11.3766 +    XMLConstHandle( const XMLNode& node )											{
 11.3767 +        _node = &node;
 11.3768 +    }
 11.3769 +    XMLConstHandle( const XMLConstHandle& ref )										{
 11.3770 +        _node = ref._node;
 11.3771 +    }
 11.3772 +
 11.3773 +    XMLConstHandle& operator=( const XMLConstHandle& ref )							{
 11.3774 +        _node = ref._node;
 11.3775 +        return *this;
 11.3776 +    }
 11.3777 +
 11.3778 +    const XMLConstHandle FirstChild() const											{
 11.3779 +        return XMLConstHandle( _node ? _node->FirstChild() : 0 );
 11.3780 +    }
 11.3781 +    const XMLConstHandle FirstChildElement( const char* value=0 ) const				{
 11.3782 +        return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
 11.3783 +    }
 11.3784 +    const XMLConstHandle LastChild()	const										{
 11.3785 +        return XMLConstHandle( _node ? _node->LastChild() : 0 );
 11.3786 +    }
 11.3787 +    const XMLConstHandle LastChildElement( const char* _value=0 ) const				{
 11.3788 +        return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
 11.3789 +    }
 11.3790 +    const XMLConstHandle PreviousSibling() const									{
 11.3791 +        return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
 11.3792 +    }
 11.3793 +    const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const		{
 11.3794 +        return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
 11.3795 +    }
 11.3796 +    const XMLConstHandle NextSibling() const										{
 11.3797 +        return XMLConstHandle( _node ? _node->NextSibling() : 0 );
 11.3798 +    }
 11.3799 +    const XMLConstHandle NextSiblingElement( const char* _value=0 ) const			{
 11.3800 +        return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
 11.3801 +    }
 11.3802 +
 11.3803 +
 11.3804 +    const XMLNode* ToNode() const				{
 11.3805 +        return _node;
 11.3806 +    }
 11.3807 +    const XMLElement* ToElement() const			{
 11.3808 +        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
 11.3809 +    }
 11.3810 +    const XMLText* ToText() const				{
 11.3811 +        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
 11.3812 +    }
 11.3813 +    const XMLUnknown* ToUnknown() const			{
 11.3814 +        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
 11.3815 +    }
 11.3816 +    const XMLDeclaration* ToDeclaration() const	{
 11.3817 +        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
 11.3818 +    }
 11.3819 +
 11.3820 +private:
 11.3821 +    const XMLNode* _node;
 11.3822 +};
 11.3823 +
 11.3824 +
 11.3825 +/**
 11.3826 +	Printing functionality. The XMLPrinter gives you more
 11.3827 +	options than the XMLDocument::Print() method.
 11.3828 +
 11.3829 +	It can:
 11.3830 +	-# Print to memory.
 11.3831 +	-# Print to a file you provide.
 11.3832 +	-# Print XML without a XMLDocument.
 11.3833 +
 11.3834 +	Print to Memory
 11.3835 +
 11.3836 +	@verbatim
 11.3837 +	XMLPrinter printer;
 11.3838 +	doc.Print( &printer );
 11.3839 +	SomeFunction( printer.CStr() );
 11.3840 +	@endverbatim
 11.3841 +
 11.3842 +	Print to a File
 11.3843 +
 11.3844 +	You provide the file pointer.
 11.3845 +	@verbatim
 11.3846 +	XMLPrinter printer( fp );
 11.3847 +	doc.Print( &printer );
 11.3848 +	@endverbatim
 11.3849 +
 11.3850 +	Print without a XMLDocument
 11.3851 +
 11.3852 +	When loading, an XML parser is very useful. However, sometimes
 11.3853 +	when saving, it just gets in the way. The code is often set up
 11.3854 +	for streaming, and constructing the DOM is just overhead.
 11.3855 +
 11.3856 +	The Printer supports the streaming case. The following code
 11.3857 +	prints out a trivially simple XML file without ever creating
 11.3858 +	an XML document.
 11.3859 +
 11.3860 +	@verbatim
 11.3861 +	XMLPrinter printer( fp );
 11.3862 +	printer.OpenElement( "foo" );
 11.3863 +	printer.PushAttribute( "foo", "bar" );
 11.3864 +	printer.CloseElement();
 11.3865 +	@endverbatim
 11.3866 +*/
 11.3867 +class TINYXML2_LIB XMLPrinter : public XMLVisitor
 11.3868 +{
 11.3869 +public:
 11.3870 +    /** Construct the printer. If the FILE* is specified,
 11.3871 +    	this will print to the FILE. Else it will print
 11.3872 +    	to memory, and the result is available in CStr().
 11.3873 +    	If 'compact' is set to true, then output is created
 11.3874 +    	with only required whitespace and newlines.
 11.3875 +    */
 11.3876 +    XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
 11.3877 +    ~XMLPrinter()	{}
 11.3878 +
 11.3879 +    /** If streaming, write the BOM and declaration. */
 11.3880 +    void PushHeader( bool writeBOM, bool writeDeclaration );
 11.3881 +    /** If streaming, start writing an element.
 11.3882 +        The element must be closed with CloseElement()
 11.3883 +    */
 11.3884 +    void OpenElement( const char* name );
 11.3885 +    /// If streaming, add an attribute to an open element.
 11.3886 +    void PushAttribute( const char* name, const char* value );
 11.3887 +    void PushAttribute( const char* name, int value );
 11.3888 +    void PushAttribute( const char* name, unsigned value );
 11.3889 +    void PushAttribute( const char* name, bool value );
 11.3890 +    void PushAttribute( const char* name, double value );
 11.3891 +    /// If streaming, close the Element.
 11.3892 +    void CloseElement();
 11.3893 +
 11.3894 +    /// Add a text node.
 11.3895 +    void PushText( const char* text, bool cdata=false );
 11.3896 +    /// Add a text node from an integer.
 11.3897 +    void PushText( int value );
 11.3898 +    /// Add a text node from an unsigned.
 11.3899 +    void PushText( unsigned value );
 11.3900 +    /// Add a text node from a bool.
 11.3901 +    void PushText( bool value );
 11.3902 +    /// Add a text node from a float.
 11.3903 +    void PushText( float value );
 11.3904 +    /// Add a text node from a double.
 11.3905 +    void PushText( double value );
 11.3906 +
 11.3907 +    /// Add a comment
 11.3908 +    void PushComment( const char* comment );
 11.3909 +
 11.3910 +    void PushDeclaration( const char* value );
 11.3911 +    void PushUnknown( const char* value );
 11.3912 +
 11.3913 +    virtual bool VisitEnter( const XMLDocument& /*doc*/ );
 11.3914 +    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
 11.3915 +        return true;
 11.3916 +    }
 11.3917 +
 11.3918 +    virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
 11.3919 +    virtual bool VisitExit( const XMLElement& element );
 11.3920 +
 11.3921 +    virtual bool Visit( const XMLText& text );
 11.3922 +    virtual bool Visit( const XMLComment& comment );
 11.3923 +    virtual bool Visit( const XMLDeclaration& declaration );
 11.3924 +    virtual bool Visit( const XMLUnknown& unknown );
 11.3925 +
 11.3926 +    /**
 11.3927 +    	If in print to memory mode, return a pointer to
 11.3928 +    	the XML file in memory.
 11.3929 +    */
 11.3930 +    const char* CStr() const {
 11.3931 +        return _buffer.Mem();
 11.3932 +    }
 11.3933 +    /**
 11.3934 +    	If in print to memory mode, return the size
 11.3935 +    	of the XML file in memory. (Note the size returned
 11.3936 +    	includes the terminating null.)
 11.3937 +    */
 11.3938 +    int CStrSize() const {
 11.3939 +        return _buffer.Size();
 11.3940 +    }
 11.3941 +
 11.3942 +private:
 11.3943 +    void SealElement();
 11.3944 +    void PrintSpace( int depth );
 11.3945 +    void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
 11.3946 +    void Print( const char* format, ... );
 11.3947 +
 11.3948 +    bool _elementJustOpened;
 11.3949 +    bool _firstElement;
 11.3950 +    FILE* _fp;
 11.3951 +    int _depth;
 11.3952 +    int _textDepth;
 11.3953 +    bool _processEntities;
 11.3954 +    bool _compactMode;
 11.3955 +
 11.3956 +    enum {
 11.3957 +        ENTITY_RANGE = 64,
 11.3958 +        BUF_SIZE = 200
 11.3959 +    };
 11.3960 +    bool _entityFlag[ENTITY_RANGE];
 11.3961 +    bool _restrictedEntityFlag[ENTITY_RANGE];
 11.3962 +
 11.3963 +    DynArray< const char*, 10 > _stack;
 11.3964 +    DynArray< char, 20 > _buffer;
 11.3965 +#ifdef _MSC_VER
 11.3966 +    DynArray< char, 20 > _accumulator;
 11.3967 +#endif
 11.3968 +};
 11.3969 +
 11.3970 +
 11.3971 +}	// tinyxml2
 11.3972 +
 11.3973 +#if defined(_MSC_VER)
 11.3974 +#   pragma warning(pop)
 11.3975 +#endif
 11.3976 +
 11.3977 +#endif // TINYXML2_INCLUDED