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