begin work on xfile parser

This commit is contained in:
David Rose 2004-10-04 03:09:08 +00:00
parent 9d564e2470
commit 7d2b0346ac
51 changed files with 2691 additions and 31 deletions

View File

@ -2,7 +2,7 @@
#define TARGET ptloader
#define BUILDING_DLL BUILDING_PTLOADER
#define LOCAL_LIBS \
fltegg flt lwoegg lwo dxfegg dxf vrmlegg pvrml xfile \
fltegg flt lwoegg lwo dxfegg dxf vrmlegg pvrml xfileegg xfile \
converter pandatoolbase
#define OTHER_LIBS \
egg2pg:c builder:c egg:c pandaegg:m \

View File

@ -1,36 +1,36 @@
// The .x converter takes advantage of the DirectX API's; therefore,
// it can only be built if we have DX available (and therefore it only
// builds on Windows--sorry).
#define BUILD_DIRECTORY $[HAVE_DX]
#define USE_PACKAGES dx
#define YACC_PREFIX xyy
#define LFLAGS -i
#begin ss_lib_target
#define TARGET xfile
#define LOCAL_LIBS eggbase progbase pandatoolbase
#define LOCAL_LIBS pandatoolbase
#define OTHER_LIBS \
egg:c pandaegg:m \
mathutil:c linmath:c putil:c panda:m \
express:c pandaexpress:m \
dtoolconfig dtool pystub \
#define WIN_SYS_LIBS \
d3dxof.lib dxguid.lib d3d8.lib d3dx8.lib dxerr8.lib
#define COMBINED_SOURCES $[TARGET]_composite1.cxx
mathutil:c linmath:c panda:m \
dtoolbase:c dtool:m
#define SOURCES \
config_xfile.h \
xFileAnimationSet.h \
xFileFace.h xFileMaker.h xFileMaterial.h \
xFileMesh.h xFileNormal.h xFileTemplates.h \
xFileToEggConverter.h xFileVertex.h
#define INCLUDED_SOURCES \
config_xfile.cxx \
xFileAnimationSet.cxx \
xFileFace.cxx xFileMaker.cxx xFileMaterial.cxx \
xFileMesh.cxx xFileNormal.cxx xFileTemplates.cxx \
xFileToEggConverter.cxx xFileVertex.cxx
config_xfile.h config_xfile.cxx \
windowsGuid.cxx windowsGuid.h \
xLexer.lxx xLexerDefs.h \
xParser.yxx xParserDefs.h \
xFile.cxx xFile.I xFile.h \
xFileArrayDef.cxx xFileArrayDef.I xFileArrayDef.h \
xFileDataDef.cxx xFileDataDef.I xFileDataDef.h \
xFileNode.cxx xFileNode.I xFileNode.h \
xFileTemplate.cxx xFileTemplate.I xFileTemplate.h
#end ss_lib_target
#begin test_bin_target
#define TARGET x-trans
#define LOCAL_LIBS \
progbase xfile
#define OTHER_LIBS \
linmath:c panda:m \
express:c pandaexpress:m \
dtoolutil:c dtoolbase:c dconfig:c dtoolconfig:m dtool:m pystub
#define SOURCES \
xFileTrans.cxx xFileTrans.h
#end test_bin_target

View File

@ -17,6 +17,10 @@
////////////////////////////////////////////////////////////////////
#include "config_xfile.h"
#include "xFile.h"
#include "xFileDataDef.h"
#include "xFileNode.h"
#include "xFileTemplate.h"
#include "dconfig.h"
@ -48,5 +52,10 @@ init_libxfile() {
return;
}
initialized = true;
XFile::init_type();
XFileDataDef::init_type();
XFileNode::init_type();
XFileTemplate::init_type();
}

View File

@ -0,0 +1,108 @@
xof 0303txt 0032
template Header {
<3d82ab43-62da-11cf-ab39-0020af71e433>
WORD major;
WORD minor;
DWORD flags;
}
template Coords2d {
<f6f23f44-7686-11cf-8f52-0040333594a3>
FLOAT u;
FLOAT v;
}
template Vector {
<3d82ab5e-62da-11cf-ab39-0020af71e433>
FLOAT x;
FLOAT y;
FLOAT z;
}
template ColorRGBA {
<35ff44e0-6c7c-11cf-8f52-0040333594a3>
FLOAT red;
FLOAT green;
FLOAT blue;
FLOAT alpha;
}
template ColorRGB {
<d3e16e81-7835-11cf-8f52-0040333594a3>
FLOAT red;
FLOAT green;
FLOAT blue;
}
template IndexedColor {
<1630b820-7842-11cf-8f52-0040333594a3>
DWORD index;
ColorRGBA indexColor;
}
template TextureFilename {
<a42790e1-7810-11cf-8f52-0040333594a3>
STRING filename;
}
template Matrix4x4 {
<f6f23f45-7686-11cf-8f52-0040333594a3>
array FLOAT matrix[16];
}
template Material {
<3d82ab4d-62da-11cf-ab39-0020af71e433>
ColorRGBA faceColor;
FLOAT power;
ColorRGB specularColor;
ColorRGB emissiveColor;
[...]
}
template MeshFace {
<3d82ab5f-62da-11cf-ab39-0020af71e433>
DWORD nFaceVertexIndices;
array DWORD faceVertexIndices[nFaceVertexIndices];
}
template Mesh {
<3d82ab44-62da-11cf-ab39-0020af71e433>
DWORD nVertices;
array Vector vertices[nVertices];
DWORD nFaces;
array MeshFace faces[nFaces];
[...]
}
template MeshNormals {
<f6f23f43-7686-11cf-8f52-0040333594a3>
DWORD nNormals;
array Vector normals[nNormals];
DWORD nFaceNormals;
array MeshFace faceNormals[nFaceNormals];
}
template MeshTextureCoords {
<f6f23f40-7686-11cf-8f52-0040333594a3>
DWORD nTextureCoords;
array Coords2d textureCoords[nTextureCoords];
}
template MeshMaterialList {
<f6f23f42-7686-11cf-8f52-0040333594a3>
DWORD nMaterials;
DWORD nFaceIndexes;
array DWORD faceIndexes[nFaceIndexes];
[Material <3d82ab4d-62da-11cf-ab39-0020af71e433>]
}
template FrameTransformMatrix {
<f6f23f41-7686-11cf-8f52-0040333594a3>
Matrix4x4 frameMatrix;
}
template Frame {
<3d82ab46-62da-11cf-ab39-0020af71e433>
[...]
}

View File

@ -0,0 +1,122 @@
// Filename: windowsGuid.I
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE WindowsGuid::
WindowsGuid() {
memset(this, 0, sizeof(WindowsGuid));
}
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE WindowsGuid::
WindowsGuid(unsigned long data1,
unsigned short data2, unsigned short data3,
unsigned char b1, unsigned char b2, unsigned char b3,
unsigned char b4, unsigned char b5, unsigned char b6,
unsigned char b7, unsigned char b8) :
_data1(data1),
_data2(data2),
_data3(data3),
_b1(b1),
_b2(b2),
_b3(b3),
_b4(b4),
_b5(b5),
_b6(b6),
_b7(b7),
_b8(b8)
{
}
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE WindowsGuid::
WindowsGuid(const WindowsGuid &copy) {
(*this) = copy;
}
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void WindowsGuid::
operator = (const WindowsGuid &copy) {
memcpy(this, &copy, sizeof(WindowsGuid));
}
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::operator ==
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool WindowsGuid::
operator == (const WindowsGuid &other) const {
return compare_to(other) == 0;
}
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::operator !=
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool WindowsGuid::
operator != (const WindowsGuid &other) const {
return compare_to(other) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::operator <
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool WindowsGuid::
operator < (const WindowsGuid &other) const {
return compare_to(other) < 0;
}
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::compare_to
// Access: Published
// Description: Returns a number less than zero if this WindowsGuid
// sorts before the other one, greater than zero if it
// sorts after, or zero if they are equivalent.
////////////////////////////////////////////////////////////////////
INLINE int WindowsGuid::
compare_to(const WindowsGuid &other) const {
return memcmp(this, &other, sizeof(WindowsGuid));
}
INLINE ostream &
operator << (ostream &out, const WindowsGuid &guid) {
guid.output(out);
return out;
}

View File

@ -0,0 +1,86 @@
// Filename: windowsGuid.cxx
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "windowsGuid.h"
#include "notify.h"
#include <stdio.h> // for sscanf, sprintf
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::parse_string
// Access: Public
// Description: Parses the hex representation in the indicated string
// and stores it in the WindowsGuid object. Returns
// true if successful, false if the string
// representation is malformed.
////////////////////////////////////////////////////////////////////
bool WindowsGuid::
parse_string(const string &str) {
long data1;
short data2, data3;
short b1, b2, b3, b4, b5, b6, b7, b8;
int result = sscanf(str.c_str(),
"%08lx-%04hx-%04hx-%02x%02x-%02x%02x%02x%02x%02x%02x",
&data1, &data2, &data3,
&b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8);
if (result != 11) {
return false;
}
_data1 = data1;
_data2 = data2;
_data3 = data3;
_b1 = b1;
_b2 = b2;
_b3 = b3;
_b4 = b4;
_b5 = b5;
_b6 = b6;
_b7 = b7;
_b8 = b8;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::format_string
// Access: Public
// Description: Returns a hex representation of the GUID.
////////////////////////////////////////////////////////////////////
string WindowsGuid::
format_string() const {
static const int buf_length = 128; // Actually, we only need 36 + 1 == 37.
char buffer[buf_length];
sprintf(buffer,
"%08lx-%04hx-%04hx-%02x%02x-%02x%02x%02x%02x%02x%02x",
_data1, _data2, _data3,
_b1, _b2, _b3, _b4, _b5, _b6, _b7, _b8);
nassertr(strlen(buffer) < buf_length, string());
return string(buffer);
}
////////////////////////////////////////////////////////////////////
// Function: WindowsGuid::output
// Access: Public
// Description: Outputs a hex representation of the GUID.
////////////////////////////////////////////////////////////////////
void WindowsGuid::
output(ostream &out) const {
out << format_string();
}

View File

@ -0,0 +1,66 @@
// Filename: windowsGuid.h
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef WINDOWS_GUID_H
#define WINDOWS_GUID_H
#include "pandatoolbase.h"
#include <string.h> // For memcpy, memcmp
////////////////////////////////////////////////////////////////////
// Class : WindowsGuid
// Description : This is an implementation of the Windows GUID object,
// used everywhere as a world-unique identifier for
// anything and everything. In particular, it's used in
// the X file format to identify standard templates.
////////////////////////////////////////////////////////////////////
class WindowsGuid {
public:
INLINE WindowsGuid();
INLINE WindowsGuid(unsigned long data1,
unsigned short data2, unsigned short data3,
unsigned char b1, unsigned char b2, unsigned char b3,
unsigned char b4, unsigned char b5, unsigned char b6,
unsigned char b7, unsigned char b8);
INLINE WindowsGuid(const WindowsGuid &copy);
INLINE void operator = (const WindowsGuid &copy);
INLINE bool operator == (const WindowsGuid &other) const;
INLINE bool operator != (const WindowsGuid &other) const;
INLINE bool operator < (const WindowsGuid &other) const;
INLINE int compare_to(const WindowsGuid &other) const;
bool parse_string(const string &str);
string format_string() const;
void output(ostream &out) const;
private:
unsigned long _data1;
unsigned short _data2;
unsigned short _data3;
unsigned char _b1, _b2, _b3, _b4, _b5, _b6, _b7, _b8;
};
INLINE ostream &operator << (ostream &out, const WindowsGuid &guid);
#include "windowsGuid.I"
#endif

View File

@ -0,0 +1,18 @@
// Filename: xFile.I
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,361 @@
// Filename: xFile.cxx
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFile.h"
#include "xParserDefs.h"
#include "xLexerDefs.h"
#include "config_xfile.h"
#include "config_express.h"
#include "virtualFileSystem.h"
TypeHandle XFile::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: XFile::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFile::
XFile() : XFileNode("xfile") {
_major_version = 1;
_minor_version = 1;
_format_type = FT_text;
_float_size = FS_64;
}
////////////////////////////////////////////////////////////////////
// Function: XFile::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFile::
~XFile() {
clear();
}
////////////////////////////////////////////////////////////////////
// Function: XFile::add_child
// Access: Public, Virtual
// Description: Adds the indicated node as a child of this node.
////////////////////////////////////////////////////////////////////
void XFile::
add_child(XFileNode *node) {
XFileNode::add_child(node);
}
////////////////////////////////////////////////////////////////////
// Function: XFile::clear
// Access: Public, Virtual
// Description: Removes all of the classes defined within the XFile
// and prepares it for reading a new file.
////////////////////////////////////////////////////////////////////
void XFile::
clear() {
XFileNode::clear();
}
////////////////////////////////////////////////////////////////////
// Function: XFile::read
// Access: Public
// Description: Opens and reads the indicated .x file by name. The
// nodes and templates defined in the file will be
// appended to the set of nodes already recorded, if
// any.
//
// Returns true if the file is successfully read, false
// if there was an error (in which case the file might
// have been partially read).
////////////////////////////////////////////////////////////////////
bool XFile::
read(Filename filename) {
ifstream in;
filename.set_text();
if (use_vfs) {
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
istream *in = vfs->open_read_file(filename);
if (in == (istream *)NULL) {
xfile_cat.error()
<< "Cannot open " << filename << " for reading.\n";
return false;
}
bool okflag = read(*in, filename);
delete in;
return okflag;
} else {
filename.open_read(in);
if (!in) {
xfile_cat.error()
<< "Cannot open " << filename << " for reading.\n";
return false;
}
return read(in, filename);
}
}
////////////////////////////////////////////////////////////////////
// Function: XFile::read
// Access: Public
// Description: Parses the already-opened input stream for
// distributed class descriptions. The filename
// parameter is optional and is only used when reporting
// errors.
//
// The distributed classes defined in the file will be
// appended to the set of distributed classes already
// recorded, if any.
//
// Returns true if the file is successfully read, false
// if there was an error (in which case the file might
// have been partially read).
////////////////////////////////////////////////////////////////////
bool XFile::
read(istream &in, const string &filename) {
if (!read_header(in)) {
return false;
}
if (_format_type != FT_text) {
// Does anyone actually use the binary format? It wouldn't be too
// hard to support it if there were any reason at all to do so.
xfile_cat.error()
<< "Cannot read binary .x files at this time.\n";
return false;
}
x_init_parser(in, filename, *this);
xyyparse();
x_cleanup_parser();
return (x_error_count() == 0);
}
////////////////////////////////////////////////////////////////////
// Function: XFile::write
// Access: Public
// Description: Opens the indicated filename for output and writes a
// parseable description of all the known distributed
// classes to the file.
//
// Returns true if the description is successfully
// written, false otherwise.
////////////////////////////////////////////////////////////////////
bool XFile::
write(Filename filename) const {
ofstream out;
// We actually open the file to write in binary mode, to avoid the
// MS-DOS newline characters (since Windows seems to do this too).
filename.set_binary();
filename.open_write(out);
if (!out) {
xfile_cat.error()
<< "Can't open " << filename << " for output.\n";
return false;
}
return write(out);
}
////////////////////////////////////////////////////////////////////
// function: XFile::write
// Access: Public
// Description: Writes a parseable description of all the known
// nodes and templates to the stream.
//
// Returns true if the description is successfully
// written, false otherwise.
////////////////////////////////////////////////////////////////////
bool XFile::
write(ostream &out) const {
if (!write_header(out)) {
return false;
}
write_text(out, 0);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFile::write_text
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFile::
write_text(ostream &out, int indent_level) const {
Children::const_iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
(*ci)->write_text(out, indent_level);
out << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: XFile::read_header
// Access: Private
// Description: Reads the header and magic number associated with the
// file. Returns true on success, false otherwise.
////////////////////////////////////////////////////////////////////
bool XFile::
read_header(istream &in) {
char magic[4];
if (!in.read(magic, 4)) {
xfile_cat.error()
<< "Empty file.\n";
return false;
}
if (memcmp(magic, "xof ", 4) != 0) {
xfile_cat.error()
<< "Not a DirectX file.\n";
return false;
}
char version[4];
if (!in.read(version, 4)) {
xfile_cat.error()
<< "Truncated file.\n";
return false;
}
_major_version = (version[0] - '0') * 10 + (version[1] - '0');
_minor_version = (version[2] - '0') * 10 + (version[3] - '0');
char format[4];
if (!in.read(format, 4)) {
xfile_cat.error()
<< "Truncated file.\n";
return false;
}
if (memcmp(format, "txt ", 4) == 0) {
_format_type = FT_text;
} else if (memcmp(format, "bin ", 4) == 0) {
_format_type = FT_binary;
} else if (memcmp(format, "com ", 4) == 0) {
_format_type = FT_compressed;
} else {
xfile_cat.error()
<< "Unknown format type: " << string(format, 4) << "\n";
return false;
}
if (_format_type == FT_compressed) {
// Read and ignore the compression type, since we don't support
// compression anyway.
char compression_type[4];
in.read(compression_type, 4);
}
char float_size[4];
if (!in.read(float_size, 4)) {
xfile_cat.error()
<< "Truncated file.\n";
return false;
}
if (memcmp(float_size, "0032", 4) == 0) {
_float_size = FS_32;
} else if (memcmp(float_size, "0064", 4) == 0) {
_float_size = FS_64;
} else {
xfile_cat.error()
<< "Unknown float size: " << string(float_size, 4) << "\n";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFile::write_header
// Access: Private
// Description: Writes the header and magic number associated with the
// file. Returns true on success, false otherwise.
////////////////////////////////////////////////////////////////////
bool XFile::
write_header(ostream &out) const {
out.write("xof ", 4);
char buffer[128];
sprintf(buffer, "%02d%02d", _major_version, _minor_version);
if (strlen(buffer) != 4) {
xfile_cat.error()
<< "Invalid version: " << _major_version << "." << _minor_version
<< "\n";
return false;
}
out.write(buffer, 4);
switch (_format_type) {
case FT_text:
out.write("txt ", 4);
break;
case FT_binary:
out.write("bin ", 4);
break;
case FT_compressed:
out.write("cmp ", 4);
break;
default:
xfile_cat.error()
<< "Invalid format type: " << _format_type << "\n";
return false;
}
if (_format_type == FT_compressed) {
// Write a bogus compression type, just so we have a valid header.
out.write("xxx ", 4);
}
switch (_float_size) {
case FS_32:
out.write("0032", 4);
break;
case FS_64:
out.write("0064", 4);
break;
default:
xfile_cat.error()
<< "Invalid float size: " << _float_size << "\n";
return false;
}
if (_format_type == FT_text) {
// If it's a text format, we can now write a newline.
out << "\n";
}
return true;
}

View File

@ -0,0 +1,89 @@
// Filename: xFile.h
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILE_H
#define XFILE_H
#include "pandatoolbase.h"
#include "xFileNode.h"
#include "filename.h"
////////////////////////////////////////////////////////////////////
// Class : XFile
// Description : This represents the complete contents of an X file
// (file.x) in memory. It may be read or written from
// or to a disk file.
////////////////////////////////////////////////////////////////////
class XFile : public XFileNode {
public:
XFile();
~XFile();
virtual void add_child(XFileNode *node);
virtual void clear();
bool read(Filename filename);
bool read(istream &in, const string &filename = string());
bool write(Filename filename) const;
bool write(ostream &out) const;
virtual void write_text(ostream &out, int indent_level) const;
enum FormatType {
FT_text,
FT_binary,
FT_compressed,
};
enum FloatSize {
FS_32,
FS_64,
};
private:
bool read_header(istream &in);
bool write_header(ostream &out) const;
int _major_version, _minor_version;
FormatType _format_type;
FloatSize _float_size;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
XFileNode::init_type();
register_type(_type_handle, "XFile",
XFileNode::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "xFile.I"
#endif

View File

@ -0,0 +1,79 @@
// Filename: xFileArrayDef.I
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: XFileArrayDef::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE XFileArrayDef::
XFileArrayDef(int fixed_size) :
_fixed_size(fixed_size),
_dynamic_size(NULL)
{
}
////////////////////////////////////////////////////////////////////
// Function: XFileArrayDef::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE XFileArrayDef::
XFileArrayDef(XFileDataDef *dynamic_size) :
_fixed_size(0),
_dynamic_size(dynamic_size)
{
}
////////////////////////////////////////////////////////////////////
// Function: XFileArrayDef::is_fixed_size
// Access: Public
// Description: Returns true if this array definition specifies a
// const-size array, false if it is a dynamic-size
// array.
////////////////////////////////////////////////////////////////////
INLINE bool XFileArrayDef::
is_fixed_size() const {
return (_dynamic_size == (XFileDataDef *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: XFileArrayDef::get_fixed_size
// Access: Public
// Description: Returns the const size of the array, if
// is_fixed_size() returned true.
////////////////////////////////////////////////////////////////////
INLINE int XFileArrayDef::
get_fixed_size() const {
nassertr(is_fixed_size(), 0);
return _fixed_size;
}
////////////////////////////////////////////////////////////////////
// Function: XFileArrayDef::get_dynamic_size
// Access: Public
// Description: Returns the data element that names the dynamic size
// of the array, if is_fixed_size() returned false.
////////////////////////////////////////////////////////////////////
INLINE XFileDataDef *XFileArrayDef::
get_dynamic_size() const {
nassertr(!is_fixed_size(), NULL);
return _dynamic_size;
}

View File

@ -0,0 +1,34 @@
// Filename: xFileArrayDef.cxx
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFileArrayDef.h"
#include "xFileDataDef.h"
////////////////////////////////////////////////////////////////////
// Function: XFileArrayDef::output
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void XFileArrayDef::
output(ostream &out) const {
if (is_fixed_size()) {
out << "[" << _fixed_size << "]";
} else {
out << "[" << _dynamic_size->get_name() << "]";
}
}

View File

@ -0,0 +1,53 @@
// Filename: xFileArrayDef.h
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILEARRAYDEF_H
#define XFILEARRAYDEF_H
#include "pandatoolbase.h"
#include "notify.h"
class XFileDataDef;
////////////////////////////////////////////////////////////////////
// Class : XFileArrayDef
// Description : Defines one level of array bounds for an associated
// XFileDataDef element.
////////////////////////////////////////////////////////////////////
class XFileArrayDef {
public:
INLINE XFileArrayDef(int fixed_size);
INLINE XFileArrayDef(XFileDataDef *dynamic_size);
INLINE bool is_fixed_size() const;
INLINE int get_fixed_size() const;
INLINE XFileDataDef *get_dynamic_size() const;
void output(ostream &out) const;
private:
int _fixed_size;
XFileDataDef *_dynamic_size;
};
#include "xFileArrayDef.I"
#endif

View File

@ -0,0 +1,32 @@
// Filename: xFileDataDef.I
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE XFileDataDef::
XFileDataDef(XFileDataDef::Type type, const string &name,
XFileTemplate *xtemplate) :
XFileNode(name),
_type(type),
_template(xtemplate)
{
}

View File

@ -0,0 +1,126 @@
// Filename: xFileDataDef.cxx
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFileDataDef.h"
#include "indent.h"
TypeHandle XFileDataDef::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
XFileDataDef::
~XFileDataDef() {
clear();
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::clear
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void XFileDataDef::
clear() {
XFileNode::clear();
_array_def.clear();
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::add_array_def
// Access: Public
// Description: Adds an additional array dimension to the data
// description.
////////////////////////////////////////////////////////////////////
void XFileDataDef::
add_array_def(const XFileArrayDef &array_def) {
_array_def.push_back(array_def);
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::write_text
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileDataDef::
write_text(ostream &out, int indent_level) const {
indent(out, indent_level);
if (!_array_def.empty()) {
out << "array ";
}
switch (_type) {
case T_word:
out << "WORD";
break;
case T_dword:
out << "DWORD";
break;
case T_float:
out << "FLOAT";
break;
case T_double:
out << "DOUBLE";
break;
case T_char:
out << "CHAR";
break;
case T_uchar:
out << "UCHAR";
break;
case T_byte:
out << "BYTE";
break;
case T_string:
out << "STRING";
break;
case T_cstring:
out << "CSTRING";
break;
case T_unicode:
out << "UNICODE";
break;
case T_template:
out << _template->get_name();
break;
}
if (has_name()) {
out << " " << get_name();
}
ArrayDef::const_iterator ai;
for (ai = _array_def.begin(); ai != _array_def.end(); ++ai) {
(*ai).output(out);
}
out << ";\n";
}

View File

@ -0,0 +1,90 @@
// Filename: xFileDataDef.h
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILEDATADEF_H
#define XFILEDATADEF_H
#include "pandatoolbase.h"
#include "namable.h"
#include "xFileNode.h"
#include "xFileArrayDef.h"
#include "xFileTemplate.h"
#include "pvector.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : XFileDataDef
// Description : A definition of a single data element appearing
// within a template record.
////////////////////////////////////////////////////////////////////
class XFileDataDef : public XFileNode {
public:
enum Type {
T_word,
T_dword,
T_float,
T_double,
T_char,
T_uchar,
T_byte,
T_string,
T_cstring,
T_unicode,
T_template,
};
INLINE XFileDataDef(Type type, const string &name,
XFileTemplate *xtemplate = NULL);
virtual ~XFileDataDef();
virtual void clear();
void add_array_def(const XFileArrayDef &array_def);
virtual void write_text(ostream &out, int indent_level) const;
private:
Type _type;
PT(XFileTemplate) _template;
typedef pvector<XFileArrayDef> ArrayDef;
ArrayDef _array_def;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
XFileNode::init_type();
register_type(_type_handle, "XFileDataDef",
XFileNode::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "xFileDataDef.I"
#endif

View File

@ -0,0 +1,18 @@
// Filename: xFileNode.I
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,96 @@
// Filename: xFileNode.cxx
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFileNode.h"
TypeHandle XFileNode::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: XFileNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileNode::
XFileNode(const string &name) : Namable(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: XFileNode::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
XFileNode::
~XFileNode() {
clear();
}
////////////////////////////////////////////////////////////////////
// Function: XFileNode::find_child
// Access: Public
// Description: Returns the child with the indicated name, if any, or
// NULL if none.
////////////////////////////////////////////////////////////////////
XFileNode *XFileNode::
find_child(const string &name) const {
ChildrenByName::const_iterator ni;
ni = _children_by_name.find(name);
if (ni != _children_by_name.end()) {
return (*ni).second;
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: XFileNode::add_child
// Access: Public, Virtual
// Description: Adds the indicated node as a child of this node.
////////////////////////////////////////////////////////////////////
void XFileNode::
add_child(XFileNode *node) {
_children.push_back(node);
if (node->has_name()) {
_children_by_name.insert(ChildrenByName::value_type(node->get_name(), node));
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileNode::clear
// Access: Public, Virtual
// Description: Removes all children from the node, and otherwise
// resets it to its initial state.
////////////////////////////////////////////////////////////////////
void XFileNode::
clear() {
_children.clear();
}
////////////////////////////////////////////////////////////////////
// Function: XFileNode::write_text
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileNode::
write_text(ostream &out, int indent_level) const {
Children::const_iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
(*ci)->write_text(out, indent_level);
}
}

View File

@ -0,0 +1,78 @@
// Filename: xFileNode.h
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILENODE_H
#define XFILENODE_H
#include "pandatoolbase.h"
#include "typedReferenceCount.h"
#include "pointerTo.h"
#include "namable.h"
#include "pvector.h"
#include "pmap.h"
////////////////////////////////////////////////////////////////////
// Class : XFileNode
// Description : A single node of an X file. This may be either a
// template or a data node.
////////////////////////////////////////////////////////////////////
class XFileNode : public TypedReferenceCount, public Namable {
public:
XFileNode(const string &name);
virtual ~XFileNode();
INLINE int get_num_children() const;
INLINE XFileNode *get_child(int n) const;
XFileNode *find_child(const string &name) const;
virtual void add_child(XFileNode *node);
virtual void clear();
virtual void write_text(ostream &out, int indent_level) const;
protected:
typedef pvector< PT(XFileNode) > Children;
Children _children;
typedef pmap<string, XFileNode *> ChildrenByName;
ChildrenByName _children_by_name;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedReferenceCount::init_type();
register_type(_type_handle, "XFileNode",
TypedReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "xFileNode.I"
#endif

View File

@ -0,0 +1,18 @@
// Filename: xFileTemplate.I
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,53 @@
// Filename: xFileTemplate.cxx
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFileTemplate.h"
#include "indent.h"
TypeHandle XFileTemplate::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: XFileTemplate::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileTemplate::
XFileTemplate(const string &name, const WindowsGuid &guid) :
XFileNode(name),
_guid(guid)
{
}
////////////////////////////////////////////////////////////////////
// Function: XFileTemplate::write_text
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileTemplate::
write_text(ostream &out, int indent_level) const {
indent(out, indent_level)
<< "template " << get_name() << " {\n";
indent(out, indent_level + 2)
<< "<" << _guid << ">\n";
XFileNode::write_text(out, indent_level + 2);
indent(out, indent_level)
<< "}\n";
}

View File

@ -0,0 +1,65 @@
// Filename: xFileTemplate.h
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILETEMPLATE_H
#define XFILETEMPLATE_H
#include "pandatoolbase.h"
#include "xFileNode.h"
#include "windowsGuid.h"
class XFileDataDef;
////////////////////////////////////////////////////////////////////
// Class : XFileTemplate
// Description : A template definition in the X file. This defines
// the data structures that may be subsequently read.
////////////////////////////////////////////////////////////////////
class XFileTemplate : public XFileNode {
public:
XFileTemplate(const string &name, const WindowsGuid &guid);
virtual void write_text(ostream &out, int indent_level) const;
private:
WindowsGuid _guid;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
XFileNode::init_type();
register_type(_type_handle, "XFileTemplate",
XFileNode::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "xFileTemplate.I"
#endif

View File

@ -0,0 +1,107 @@
// Filename: xFileTrans.cxx
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFileTrans.h"
#include "xFile.h"
////////////////////////////////////////////////////////////////////
// Function: XFileTrans::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileTrans::
XFileTrans() :
WithOutputFile(true, true, false)
{
// Indicate the extension name we expect the user to supply for
// output files.
_preferred_extension = ".x";
set_program_description
("This program reads a DirectX retained-mode file (.x) and writes an "
"essentially equivalent .x file. It is primarily useful for "
"debugging the X file parser that is part of the Pandatool library.");
clear_runlines();
add_runline("[opts] input.x > output.x");
add_runline("[opts] input.x output.x");
add_runline("[opts] -o output.x input.x");
add_option
("o", "filename", 0,
"Specify the filename to which the resulting .x file will be written. "
"If this option is omitted, the last parameter name is taken to be the "
"name of the output file.",
&XFileTrans::dispatch_filename, &_got_output_filename, &_output_filename);
}
////////////////////////////////////////////////////////////////////
// Function: XFileTrans::run
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void XFileTrans::
run() {
nout << "Reading " << _input_filename << "\n";
XFile file;
if (!file.read(_input_filename)) {
nout << "Unable to read.\n";
exit(1);
}
if (!file.write(get_output())) {
nout << "Unable to write.\n";
exit(1);
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileTrans::handle_args
// Access: Protected, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool XFileTrans::
handle_args(ProgramBase::Args &args) {
if (!check_last_arg(args, 1)) {
return false;
}
if (args.empty()) {
nout << "You must specify the .x file to read on the command line.\n";
return false;
} else if (args.size() != 1) {
nout << "You must specify only one .x file to read on the command line.\n";
return false;
}
_input_filename = args[0];
return true;
}
int main(int argc, char *argv[]) {
XFileTrans prog;
prog.parse_command_line(argc, argv);
prog.run();
return 0;
}

View File

@ -0,0 +1,46 @@
// Filename: xFileTrans.h
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILETRANS_H
#define XFILETRANS_H
#include "pandatoolbase.h"
#include "programBase.h"
#include "withOutputFile.h"
////////////////////////////////////////////////////////////////////
// Class : XFileTrans
// Description : A program to read a X file and output an
// essentially similar X file. This is mainly useful
// to test the X file parser used in Panda.
////////////////////////////////////////////////////////////////////
class XFileTrans : public ProgramBase, public WithOutputFile {
public:
XFileTrans();
void run();
protected:
virtual bool handle_args(Args &args);
Filename _input_filename;
};
#endif

View File

@ -0,0 +1,540 @@
/*
// Filename: xLexer.lxx
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
*/
%{
#include "xLexerDefs.h"
#include "xParserDefs.h"
#include "xParser.h"
#include "indent.h"
#include "notify.h"
static int yyinput(void); // declared by flex.
extern "C" int xyywrap();
////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////
// We'll increment line_number and col_number as we parse the file, so
// that we can report the position of an error.
static int line_number = 0;
static int col_number = 0;
// current_line holds as much of the current line as will fit. Its
// only purpose is for printing it out to report an error to the user.
static const int max_error_width = 1024;
static char current_line[max_error_width + 1];
static int error_count = 0;
static int warning_count = 0;
// This is the pointer to the current input stream.
static istream *inp = NULL;
// This is the name of the x file we're parsing. We keep it so we
// can print it out for error messages.
static string x_filename;
////////////////////////////////////////////////////////////////////
// Defining the interface to the lexer.
////////////////////////////////////////////////////////////////////
void
x_init_lexer(istream &in, const string &filename) {
inp = &in;
x_filename = filename;
line_number = 0;
col_number = 0;
error_count = 0;
warning_count = 0;
}
int
x_error_count() {
return error_count;
}
int
x_warning_count() {
return warning_count;
}
////////////////////////////////////////////////////////////////////
// Internal support functions.
////////////////////////////////////////////////////////////////////
int
xyywrap(void) {
return 1;
}
void
xyyerror(const string &msg) {
cerr << "\nError";
if (!x_filename.empty()) {
cerr << " in " << x_filename;
}
cerr
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
<< "^\n" << msg << "\n\n";
error_count++;
}
void
xyywarning(const string &msg) {
cerr << "\nWarning";
if (!x_filename.empty()) {
cerr << " in " << x_filename;
}
cerr
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
<< "^\n" << msg << "\n\n";
warning_count++;
}
// Now define a function to take input from an istream instead of a
// stdio FILE pointer. This is flex-specific.
static void
input_chars(char *buffer, int &result, int max_size) {
nassertv(inp != NULL);
if (*inp) {
inp->read(buffer, max_size);
result = inp->gcount();
if (result >= 0 && result < max_size) {
// Truncate at the end of the read.
buffer[result] = '\0';
}
if (line_number == 0) {
// This is a special case. If we are reading the very first bit
// from the stream, copy it into the current_line array. This
// is because the \n.* rule below, which fills current_line
// normally, doesn't catch the first line.
strncpy(current_line, xyytext, max_error_width);
current_line[max_error_width] = '\0';
line_number++;
col_number = 0;
// Truncate it at the newline.
char *end = strchr(current_line, '\n');
if (end != NULL) {
*end = '\0';
}
}
} else {
// End of file or I/O error.
result = 0;
}
}
#undef YY_INPUT
#define YY_INPUT(buffer, result, max_size) input_chars(buffer, result, max_size)
// read_char reads and returns a single character, incrementing the
// supplied line and column numbers as appropriate. A convenience
// function for the scanning functions below.
static int
read_char(int &line, int &col) {
int c = yyinput();
if (c == '\n') {
line++;
col = 0;
} else {
col++;
}
return c;
}
// scan_quoted_string reads a string delimited by quotation marks and
// returns it.
static string
scan_quoted_string(char quote_mark) {
string result;
// We don't touch the current line number and column number during
// scanning, so that if we detect an error while scanning the string
// (e.g. an unterminated string), we'll report the error as
// occurring at the start of the string, not at the end--somewhat
// more convenient for the user.
// Instead of adjusting the global line_number and col_number
// variables, we'll operate on our own local variables for the
// interim.
int line = line_number;
int col = col_number;
int c;
c = read_char(line, col);
while (c != quote_mark && c != EOF) {
// A newline is not allowed within a string unless it is escaped.
if (c == '\n') {
c = EOF;
break;
} else if (c == '\\') {
// Backslash escapes the following character. We also respect
// some C conventions.
c = read_char(line, col);
switch (c) {
case 'a':
result += '\a';
c = read_char(line, col);
break;
case 'n':
result += '\n';
c = read_char(line, col);
break;
case 'r':
result += '\r';
c = read_char(line, col);
break;
case 't':
result += '\t';
c = read_char(line, col);
break;
case 'x':
{
int hex = 0;
c = read_char(line, col);
for (int i = 0; i < 2 && isxdigit(c); i++) {
hex = hex * 16 + (isdigit(c) ? c - '0' : tolower(c) - 'a' + 10);
c = read_char(line, col);
}
result += hex;
}
break;
case '0':
{
int oct = 0;
c = read_char(line, col);
for (int i = 0; i < 3 && (c >= '0' && c < '7'); i++) {
oct = oct * 8 + (c - '0');
c = read_char(line, col);
}
result += oct;
}
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
int dec = 0;
c = read_char(line, col);
for (int i = 0; i < 3 && isdigit(c); i++) {
dec = dec * 10 + (c - '0');
c = read_char(line, col);
}
result += dec;
}
break;
case EOF:
break;
default:
result += c;
c = read_char(line, col);
}
} else {
result += c;
c = read_char(line, col);
}
}
if (c == EOF) {
xyyerror("This quotation mark is unterminated.");
}
line_number = line;
col_number = col;
return result;
}
// scan_guid_string reads a string of hexadecimal digits delimited by
// angle brackets and returns the corresponding string.
static string
scan_guid_string() {
// We don't touch the current line number and column number during
// scanning, so that if we detect an error while scanning the string
// (e.g. an unterminated string), we'll report the error as
// occurring at the start of the string, not at the end--somewhat
// more convenient for the user.
// Instead of adjusting the global line_number and col_number
// variables, we'll operate on our own local variables for the
// interim.
int line = line_number;
int col = col_number;
int num_digits = 0;
int num_hyphens = 0;
string result;
int c;
c = read_char(line, col);
while (c != '>' && c != EOF) {
if (isxdigit(c)) {
num_digits++;
} else if (c == '-') {
num_hyphens++;
} else {
line_number = line;
col_number = col;
xyyerror("Invalid character in GUID.");
return string();
}
result += c;
c = read_char(line, col);
}
if (c == EOF) {
xyyerror("This GUID string is unterminated.");
return string();
} else if (num_digits != 32) {
xyyerror("Incorrect number of hex digits in GUID.");
return string();
} else if (num_hyphens != 4) {
xyyerror("Incorrect number of hyphens in GUID.");
return string();
}
line_number = line;
col_number = col;
return result;
}
// accept() is called below as each piece is pulled off and
// accepted by the lexer; it increments the current column number.
inline void accept() {
col_number += yyleng;
}
%}
INTEGERNUM ([+-]?([0-9]+))
UNSIGNED_HEXNUM (0x[0-9a-fA-F]*)
REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
%%
%{
%}
\n.* {
// New line. Save a copy of the line so we can print it out for the
// benefit of the user in case we get an error.
strncpy(current_line, xyytext+1, max_error_width);
current_line[max_error_width] = '\0';
line_number++;
col_number=0;
// Return the whole line to the lexer, except the newline character,
// which we eat.
yyless(1);
}
[ \t\r] {
// Eat whitespace.
accept();
}
"//".* {
// Eat C++-style comments.
accept();
}
"#".* {
// Eat sh-style comments.
accept();
}
"array" {
accept();
return KW_ARRAY;
}
"byte" {
accept();
return KW_BYTE;
}
"char" {
accept();
return KW_CHAR;
}
"cstring" {
accept();
return KW_CSTRING;
}
"double" {
accept();
return KW_DOUBLE;
}
"dword" {
accept();
return KW_DWORD;
}
"float" {
accept();
return KW_FLOAT;
}
"string" {
accept();
return KW_STRING;
}
"template" {
accept();
return KW_TEMPLATE;
}
"uchar" {
accept();
return KW_UCHAR;
}
"unicode" {
accept();
return KW_UNICODE;
}
"word" {
accept();
return KW_WORD;
}
[.][.][.] {
accept();
return ELLIPSIS;
}
{INTEGERNUM} {
// A signed or unsigned integer number.
accept();
xyylval.u.s_int = atol(xyytext);
xyylval.str = yytext;
return INTEGER;
}
{UNSIGNED_HEXNUM} {
// A hexadecimal integer number.
accept();
// As above, we'll decode the hex string by hand.
xyylval.str = xyytext;
xyylval.u.s_int = 0;
const char *p = xyytext + 2;
while (*p != '\0') {
int next_value = xyylval.u.s_int * 16;
if (next_value < xyylval.u.s_int) {
xyyerror("Number out of range.");
xyylval.u.s_int = 1;
return INTEGER;
}
if (isalpha(*p)) {
xyylval.u.s_int = next_value + (tolower(*p) - 'a' + 10);
} else {
xyylval.u.s_int = next_value + (*p - '0');
}
++p;
}
return INTEGER;
}
{REALNUM} {
// A floating-point number.
accept();
xyylval.u.real = atof(xyytext);
xyylval.str = xyytext;
return REAL;
}
["] {
// Quoted string.
accept();
xyylval.str = scan_quoted_string('"');
return STRING;
}
['] {
// Single-quoted string.
accept();
xyylval.str = scan_quoted_string('\'');
return STRING;
}
[<] {
// Long GUID string.
accept();
xyylval.str = scan_guid_string();
if (!xyylval.guid.parse_string(xyylval.str)) {
xyyerror("Malformed GUID.");
}
return WINDOWS_GUID;
}
[A-Za-z_-][A-Za-z_0-9-]* {
// Identifier.
accept();
xyylval.str = xyytext;
return IDENTIFIER;
}
. {
// Send any other printable character as itself.
accept();
return xyytext[0];
}

View File

@ -0,0 +1,33 @@
// Filename: xLexerDefs.h
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XLEXERDEFS_H
#define XLEXERDEFS_H
#include "pandatoolbase.h"
void x_init_lexer(istream &in, const string &filename);
int x_error_count();
int x_warning_count();
void xyyerror(const string &msg);
void xyywarning(const string &msg);
int xyylex();
#endif

View File

@ -0,0 +1,237 @@
// Filename: xParser.yxx
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
%{
#include "xLexerDefs.h"
#include "xParserDefs.h"
#include "xFile.h"
#include "xFileTemplate.h"
#include "xFileDataDef.h"
#include "xFileArrayDef.h"
#include "dcast.h"
// Because our token type contains objects of type string, which
// require correct copy construction (and not simply memcpying), we
// cannot use bison's built-in auto-stack-grow feature. As an easy
// solution, we ensure here that we have enough yacc stack to start
// with, and that it doesn't ever try to grow.
#define YYINITDEPTH 1000
#define YYMAXDEPTH 1000
static XFile *x_file = (XFile *)NULL;
static XFileNode *current_node = (XFileNode *)NULL;
static XFileDataDef *current_data_def = (XFileDataDef *)NULL;
////////////////////////////////////////////////////////////////////
// Defining the interface to the parser.
////////////////////////////////////////////////////////////////////
void
x_init_parser(istream &in, const string &filename, XFile &file) {
x_file = &file;
current_node = &file;
x_init_lexer(in, filename);
}
void
x_cleanup_parser() {
x_file = (XFile *)NULL;
current_node = (XFileNode *)NULL;
}
%}
%token <u.s_int> INTEGER
%token <u.real> REAL
%token <str> STRING IDENTIFIER
%token <guid> WINDOWS_GUID
%token KW_ARRAY
%token KW_BYTE
%token KW_CHAR
%token KW_CSTRING
%token KW_DOUBLE
%token KW_DWORD
%token KW_FLOAT
%token KW_STRING
%token KW_TEMPLATE
%token KW_UCHAR
%token KW_UNICODE
%token KW_WORD
%token ELLIPSIS
%type <u.node> xtemplate
%type <u.data_def> data_def
%type <str> optional_identifier
%type <guid> optional_guid
%%
xfile:
empty
| xfile xtemplate
| xfile data_object
;
xtemplate:
KW_TEMPLATE IDENTIFIER '{' WINDOWS_GUID
{
$$ = current_node;
XFileTemplate *templ = new XFileTemplate($2, $4);
current_node->add_child(templ);
current_node = templ;
}
template_members template_restrictions '}'
{
$$ = current_node;
current_node = $<u.node>5;
}
;
template_members:
empty
| template_members template_member ';'
;
template_member:
data_def
{
current_node->add_child($1);
}
| KW_ARRAY data_def
{
current_node->add_child($2);
current_data_def = $2;
}
array_dimensions
;
data_def:
KW_WORD optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_word, $2);
}
| KW_DWORD optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_dword, $2);
}
| KW_FLOAT optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_float, $2);
}
| KW_DOUBLE optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_double, $2);
}
| KW_CHAR optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_char, $2);
}
| KW_UCHAR optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_uchar, $2);
}
| KW_BYTE optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_byte, $2);
}
| KW_STRING optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_string, $2);
}
| KW_CSTRING optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_cstring, $2);
}
| KW_UNICODE optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_unicode, $2);
}
| IDENTIFIER optional_identifier
{
$$ = new XFileDataDef(XFileDataDef::T_word, $2);
}
;
array_dimensions:
array_level
| array_dimensions array_level
;
array_level:
'[' INTEGER ']'
{
current_data_def->add_array_def(XFileArrayDef($2));
}
| '[' IDENTIFIER ']'
{
XFileNode *data_def = current_node->find_child($2);
if (data_def == (XFileNode *)NULL) {
yyerror("Unknown identifier: " + $2);
} else {
current_data_def->add_array_def(XFileArrayDef(DCAST(XFileDataDef, data_def)));
}
}
;
template_restrictions:
empty
| '[' ELLIPSIS ']'
| '[' template_list ']'
;
template_list:
IDENTIFIER optional_guid
| template_list ',' IDENTIFIER optional_guid
;
data_object:
IDENTIFIER optional_identifier '{'
{
}
data_object_members '}'
{
}
;
data_object_members:
empty
| data_object_members data_object_member
;
data_object_member:
data_object
| data_reference
| INTEGER
| REAL
| STRING
| ';'
| ','
;
data_reference:
'{' IDENTIFIER '}'
;
optional_identifier:
empty
{
$$ = string();
}
| IDENTIFIER
;
optional_guid:
empty
{
$$ = WindowsGuid();
}
| WINDOWS_GUID
;
empty:
;

View File

@ -0,0 +1,57 @@
// Filename: xParserDefs.h
// Created by: drose (03Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XPARSERDEFS_H
#define XPARSERDEFS_H
#include "pandatoolbase.h"
#include "windowsGuid.h"
class XFile;
class XFileNode;
class XFileDataDef;
void x_init_parser(istream &in, const string &filename, XFile &file);
void x_cleanup_parser();
int xyyparse();
// This structure holds the return value for each token.
// Traditionally, this is a union, and is declared with the %union
// declaration in the parser.y file, but unions are pretty worthless
// in C++ (you can't include an object that has member functions in a
// union), so we'll use a class instead. That means we need to
// declare it externally, here.
class XTokenType {
public:
union U {
int s_int;
double real;
XFileNode *node;
XFileDataDef *data_def;
} u;
string str;
WindowsGuid guid;
};
// The yacc-generated code expects to use the symbol 'YYSTYPE' to
// refer to the above class.
#define YYSTYPE XTokenType
#endif

View File

@ -0,0 +1,34 @@
// The .x converter takes advantage of the DirectX API's; therefore,
// it can only be built if we have DX available (and therefore it only
// builds on Windows--sorry).
#define BUILD_DIRECTORY $[HAVE_DX]
#define USE_PACKAGES dx
#begin ss_lib_target
#define TARGET xfileegg
#define LOCAL_LIBS xfile eggbase progbase pandatoolbase
#define OTHER_LIBS \
egg:c pandaegg:m \
mathutil:c linmath:c putil:c panda:m \
express:c pandaexpress:m \
dtoolconfig dtool pystub \
#define WIN_SYS_LIBS \
d3dxof.lib dxguid.lib d3d8.lib d3dx8.lib dxerr8.lib
#define COMBINED_SOURCES $[TARGET]_composite1.cxx
#define SOURCES \
xFileAnimationSet.h \
xFileFace.h xFileMaker.h xFileMaterial.h \
xFileMesh.h xFileNormal.h xFileTemplates.h \
xFileToEggConverter.h xFileVertex.h
#define INCLUDED_SOURCES \
xFileAnimationSet.cxx \
xFileFace.cxx xFileMaker.cxx xFileMaterial.cxx \
xFileMesh.cxx xFileNormal.cxx xFileTemplates.cxx \
xFileToEggConverter.cxx xFileVertex.cxx
#end ss_lib_target

View File

@ -7,7 +7,7 @@
#begin bin_target
#define TARGET egg2x
#define LOCAL_LIBS xfile eggbase progbase pandatoolbase
#define LOCAL_LIBS xfileegg xfile eggbase progbase pandatoolbase
#define OTHER_LIBS \
egg:c pandaegg:m \
mathutil:c linmath:c putil:c panda:m \
@ -24,7 +24,7 @@
#begin bin_target
#define TARGET x2egg
#define LOCAL_LIBS xfile converter eggbase progbase pandatoolbase
#define LOCAL_LIBS xfileegg xfile converter eggbase progbase pandatoolbase
#define OTHER_LIBS \
egg:c pandaegg:m \
mathutil:c linmath:c putil:c panda:m \

View File

@ -44,10 +44,15 @@ XFileToEgg() :
add_option
("a", "name", 0,
"Convert as an animatable model, converting Frames into Joints. "
"Note that animation support in x2egg is currently experimental and "
"likely to be broken.",
/*
"Convert as an animatable model, converting Frames into Joints. This "
"should be specified for a model which is intended to be animated. The "
"default is to convert the model as a normal static model, which is "
"usually more optimal if animation is not required.",
*/
&XFileToEgg::dispatch_string, &_make_char, &_char_name);
redescribe_option