regularize TexturePool interfaces for cube maps etc.

This commit is contained in:
David Rose 2005-08-02 22:35:12 +00:00
parent c8502c7a02
commit f169ddb221
11 changed files with 476 additions and 54 deletions

View File

@ -29,6 +29,7 @@
#include "preparedGraphicsObjects.h"
#include "pnmImage.h"
#include "virtualFileSystem.h"
#include "hashFilename.h"
#include <stddef.h>
@ -393,24 +394,13 @@ write(const Filename &name, int z) const {
// corresponding number of digits.
////////////////////////////////////////////////////////////////////
bool Texture::
read_pages(const Filename &fullpath_template, int z_size) {
string fp = fullpath_template.get_fullpath();
size_t hash = fp.rfind('#');
if (hash == string::npos) {
read_pages(const HashFilename &fullpath_template, int z_size) {
if (!fullpath_template.has_hash()) {
gobj_cat.error()
<< "Template " << fullpath_template << " contains no hash marks.\n";
return false;
}
// Count the number of hash marks.
size_t num_hash = 1;
while (hash >= num_hash && fp[hash - num_hash] == '#') {
num_hash++;
}
string prefix = fp.substr(0, hash - num_hash + 1);
string suffix = fp.substr(hash + 1);
clear_ram_image();
if (z_size == 0) {
@ -432,29 +422,23 @@ read_pages(const Filename &fullpath_template, int z_size) {
if (z_size != 0) {
set_z_size(z_size);
for (int z = 0; z < z_size; z++) {
ostringstream strm;
strm << prefix << setw(num_hash) << setfill('0') << z << suffix;
if (!read(strm.str(), z)) {
if (!read(fullpath_template.get_filename_index(z), z)) {
return false;
}
}
} else {
set_z_size(0);
int z = 0;
ostringstream strm;
strm << prefix << setw(num_hash) << setfill('0') << z << suffix;
Filename file(strm.str());
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
Filename file = fullpath_template.get_filename_index(z);
while (vfs->exists(file)) {
if (!read(file, z)) {
return false;
}
++z;
ostringstream strm;
strm << prefix << setw(num_hash) << setfill('0') << z << suffix;
file = Filename(strm.str());
file = fullpath_template.get_filename_index(z);
}
}
@ -475,28 +459,15 @@ read_pages(const Filename &fullpath_template, int z_size) {
// corresponding number of digits.
////////////////////////////////////////////////////////////////////
bool Texture::
write_pages(const Filename &fullpath_template) {
string fp = fullpath_template.get_fullpath();
size_t hash = fp.rfind('#');
if (hash == string::npos) {
write_pages(const HashFilename &fullpath_template) {
if (!fullpath_template.has_hash()) {
gobj_cat.error()
<< "Template " << fullpath_template << " contains no hash marks.\n";
return false;
}
// Count the number of hash marks.
size_t num_hash = 1;
while (hash >= num_hash && fp[hash - num_hash] == '#') {
num_hash++;
}
string prefix = fp.substr(0, hash - num_hash + 1);
string suffix = fp.substr(hash + 1);
for (int z = 0; z < _z_size; z++) {
ostringstream strm;
strm << prefix << setw(num_hash) << setfill('0') << z << suffix;
if (!write(strm.str(), z)) {
if (!write(fullpath_template.get_filename_index(z), z)) {
return false;
}
}

View File

@ -21,6 +21,7 @@
#include "pandabase.h"
#include "filename.h"
#include "typedWritableReferenceCount.h"
#include "namable.h"
#include "graphicsStateGuardianBase.h"
@ -30,6 +31,7 @@ class PNMImage;
class TextureContext;
class FactoryParams;
class PreparedGraphicsObjects;
class HashFilename;
////////////////////////////////////////////////////////////////////
// Class : Texture
@ -159,8 +161,8 @@ PUBLISHED:
int primary_file_num_channels = 0, int alpha_file_channel = 0);
bool write(const Filename &fullpath, int z = 0) const;
bool read_pages(const Filename &fullpath_template, int z_size = 0);
bool write_pages(const Filename &fullpath_template);
bool read_pages(const HashFilename &fullpath_template, int z_size = 0);
bool write_pages(const HashFilename &fullpath_template);
bool load(const PNMImage &pnmimage, int z = 0);
bool store(PNMImage &pnmimage, int z = 0) const;

View File

@ -74,6 +74,50 @@ load_texture(const string &filename, const string &alpha_filename,
alpha_file_channel);
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::load_3d_texture
// Access: Published, Static
// Description: Loads a 3-D texture that is specified with a series
// of n pages, all numbered in sequence, and beginning
// with index 0. The filename should include a sequence
// of one or more hash characters ("#") which will be
// filled in with the index number of each level.
////////////////////////////////////////////////////////////////////
INLINE Texture *TexturePool::
load_3d_texture(const string &filename_template) {
return get_ptr()->ns_load_3d_texture(filename_template);
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::load_cube_map
// Access: Published, Static
// Description: Loads a cube map texture that is specified with a
// series of 6 pages, numbered 0 through 5. The
// filename should include a sequence of one or more
// hash characters ("#") which will be filled in with
// the index number of each pagee.
////////////////////////////////////////////////////////////////////
INLINE Texture *TexturePool::
load_cube_map(const string &filename_template) {
return get_ptr()->ns_load_cube_map(filename_template);
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::get_normalization_cube_map
// Access: Published, Static
// Description: Returns a standard Texture object that has been
// created with
// Texture::generate_normalization_cube_map(). This
// Texture may be shared by any application code
// requiring a normalization cube map. It will be at
// least as large as the specified size, though it may
// be larger.
////////////////////////////////////////////////////////////////////
INLINE Texture *TexturePool::
get_normalization_cube_map(int size) {
return get_ptr()->ns_get_normalization_cube_map(size);
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::add_texture
// Access: Published, Static

View File

@ -93,11 +93,8 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels) {
<< "Loading texture " << filename << "\n";
PT(Texture) tex = new Texture;
if (!tex->read(filename, 0, primary_file_num_channels)) {
// This texture was not found.
gobj_cat.error()
<< "Unable to read texture \"" << filename << "\""
<< " on texture_path " << texture_path
<< " or model_path " << model_path <<"\n";
// This texture was not found or could not be read.
report_texture_unreadable(filename);
return NULL;
}
@ -145,8 +142,8 @@ ns_load_texture(const Filename &orig_filename,
PT(Texture) tex = new Texture;
if (!tex->read(filename, alpha_filename, 0, primary_file_num_channels,
alpha_file_channel)) {
// This texture was not found.
gobj_cat.error() << "Unable to read texture " << filename << "\n";
// This texture was not found or could not be read.
report_texture_unreadable(filename);
return NULL;
}
@ -158,6 +155,114 @@ ns_load_texture(const Filename &orig_filename,
return tex;
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::ns_load_3d_texture
// Access: Private
// Description: The nonstatic implementation of load_3d_texture().
////////////////////////////////////////////////////////////////////
Texture *TexturePool::
ns_load_3d_texture(const HashFilename &filename_template) {
// Look up filename 0 on the model path.
Filename filename = filename_template.get_filename_index(0);
if (!_fake_texture_image.empty()) {
filename = _fake_texture_image;
}
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
vfs->resolve_filename(filename, get_texture_path()) ||
vfs->resolve_filename(filename, get_model_path());
// Then, replace everything before the hash code with the directory
// we've found.
string hash = filename_template.get_hash_to_end();
HashFilename hash_filename(filename.substr(0, filename.length() - hash.length()) + hash);
Textures::const_iterator ti;
ti = _textures.find(hash_filename);
if (ti != _textures.end()) {
// This texture was previously loaded.
return (*ti).second;
}
gobj_cat.info()
<< "Loading 3-d texture " << hash_filename << "\n";
PT(Texture) tex = new Texture;
tex->setup_3d_texture();
if (!tex->read_pages(hash_filename)) {
// This texture was not found or could not be read.
report_texture_unreadable(filename);
}
// Set the original filename, before we searched along the path.
tex->set_filename(filename_template);
_textures[hash_filename] = tex;
return tex;
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::ns_load_cube_map
// Access: Private
// Description: The nonstatic implementation of load_cube_map().
////////////////////////////////////////////////////////////////////
Texture *TexturePool::
ns_load_cube_map(const HashFilename &filename_template) {
// Look up filename 0 on the model path.
Filename filename = filename_template.get_filename_index(0);
if (!_fake_texture_image.empty()) {
filename = _fake_texture_image;
}
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
vfs->resolve_filename(filename, get_texture_path()) ||
vfs->resolve_filename(filename, get_model_path());
// Then, replace everything before the hash code with the directory
// we've found.
string hash = filename_template.get_hash_to_end();
HashFilename hash_filename(filename.substr(0, filename.length() - hash.length()) + hash);
Textures::const_iterator ti;
ti = _textures.find(hash_filename);
if (ti != _textures.end()) {
// This texture was previously loaded.
return (*ti).second;
}
gobj_cat.info()
<< "Loading cube map texture " << hash_filename << "\n";
PT(Texture) tex = new Texture;
tex->setup_cube_map();
if (!tex->read_pages(hash_filename)) {
// This texture was not found or could not be read.
report_texture_unreadable(filename);
}
// Set the original filename, before we searched along the path.
tex->set_filename(filename_template);
_textures[hash_filename] = tex;
return tex;
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::ns_get_normalization_cube_map
// Access: Private
// Description: The nonstatic implementation of get_normalization_cube_map().
////////////////////////////////////////////////////////////////////
Texture *TexturePool::
ns_get_normalization_cube_map(int size) {
if (_normalization_cube_map == (Texture *)NULL) {
_normalization_cube_map = new Texture("normalization_cube_map");
}
if (_normalization_cube_map->get_x_size() < size ||
_normalization_cube_map->get_texture_type() != Texture::TT_cube_map) {
_normalization_cube_map->generate_normalization_cube_map(size);
}
return _normalization_cube_map;
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::ns_add_texture
// Access: Private
@ -197,6 +302,7 @@ ns_release_texture(Texture *tex) {
void TexturePool::
ns_release_all_textures() {
_textures.clear();
_normalization_cube_map = NULL;
}
////////////////////////////////////////////////////////////////////
@ -224,6 +330,16 @@ ns_garbage_collect() {
}
_textures.swap(new_set);
if (_normalization_cube_map->get_ref_count() == 1) {
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Releasing normalization cube map\n";
}
++num_released;
_normalization_cube_map = NULL;
}
return num_released;
}
@ -244,6 +360,38 @@ ns_list_contents(ostream &out) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::report_texture_unreadable
// Access: Private
// Description: Prints a suitable error message when a texture could
// not be loaded.
////////////////////////////////////////////////////////////////////
void TexturePool::
report_texture_unreadable(const Filename &filename) const {
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
if (!vfs->exists(filename)) {
if (filename.is_local()) {
// The file doesn't exist, and it wasn't
// fully-qualified--therefore, it wasn't found along either
// search path.
gobj_cat.error()
<< "Unable to find texture \"" << filename << "\""
<< " on texture_path " << texture_path
<< " or model_path " << model_path <<"\n";
} else {
// A fully-specified filename is not searched along the path, so
// don't mislead the user with the error message.
gobj_cat.error()
<< "Texture \"" << filename << "\" does not exist.\n";
}
} else {
// The file exists, but it couldn't be read for some reason.
gobj_cat.error()
<< "Texture \"" << filename << "\" exists but cannot be read.\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::get_ptr
// Access: Private, Static

View File

@ -23,6 +23,7 @@
#include "texture.h"
#include "filename.h"
#include "config_gobj.h"
#include "hashFilename.h"
#include "pmap.h"
@ -47,6 +48,11 @@ PUBLISHED:
const string &alpha_filename,
int primary_file_num_channels = 0,
int alpha_file_channel = 0);
INLINE static Texture *load_3d_texture(const string &filename_template);
INLINE static Texture *load_cube_map(const string &filename_template);
INLINE static Texture *get_normalization_cube_map(int size);
INLINE static void add_texture(Texture *texture);
INLINE static void release_texture(Texture *texture);
INLINE static void release_all_textures();
@ -60,7 +66,6 @@ PUBLISHED:
INLINE static bool has_fake_texture_image();
INLINE static const string &get_fake_texture_image();
// static void output(ostream &out);
static void write(ostream &out);
private:
@ -72,18 +77,26 @@ private:
const Filename &orig_alpha_filename,
int primary_file_num_channels,
int alpha_file_channel);
Texture *ns_load_3d_texture(const HashFilename &filename_template);
Texture *ns_load_cube_map(const HashFilename &filename_template);
Texture *ns_get_normalization_cube_map(int size);
void ns_add_texture(Texture *texture);
void ns_release_texture(Texture *texture);
void ns_release_all_textures();
int ns_garbage_collect();
void ns_list_contents(ostream &out) const;
void report_texture_unreadable(const Filename &filename) const;
static TexturePool *get_ptr();
static TexturePool *_global_ptr;
typedef phash_map<string, PT(Texture), string_hash> Textures;
Textures _textures;
string _fake_texture_image;
PT(Texture) _normalization_cube_map;
};
#include "texturePool.I"

View File

@ -74,6 +74,7 @@ SpriteParticleRenderer(Texture *tex) :
SpriteParticleRenderer::
SpriteParticleRenderer(const SpriteParticleRenderer& copy) :
BaseParticleRenderer(copy),
_anims(copy._anims),
_color(copy._color),
_height(copy._height),
_width(copy._width),
@ -95,7 +96,6 @@ SpriteParticleRenderer(const SpriteParticleRenderer& copy) :
_blend_method(copy._blend_method),
_color_interpolation_manager(copy._color_interpolation_manager),
_pool_size(0),
_anims(copy._anims),
_birth_list(copy._birth_list) {
init_geoms();
}
@ -299,7 +299,6 @@ add_from_node(const NodePath &node_path, bool size_from_texels, bool resize) {
GeomNode *gnode = NULL;
const Geom *geom;
const GeomPrimitive *primitive;
bool got_texcoord;
for (int i = 0; i < np_col.get_num_paths(); ++i) {
// Get the node from which we'll extract the geometry information.
@ -309,7 +308,7 @@ add_from_node(const NodePath &node_path, bool size_from_texels, bool resize) {
nassertv(gnode->get_num_geoms() > 0);
geom = gnode->get_geom(0);
got_texcoord = false;
bool got_texcoord = false;
TexCoordf min_uv(0.0f, 0.0f);
TexCoordf max_uv(0.0f, 0.0f);
@ -389,7 +388,7 @@ add_from_node(const NodePath &node_path, bool size_from_texels, bool resize) {
float height = max(max_xyz[1] - min_xyz[1],
max_xyz[2] - min_xyz[2]);
if (size_from_texels && got_texcoord) {
if (size_from_texels) {
// If size_from_texels is true, we get the particle size from the
// number of texels in the source image.
float y_texels = _anims[0]->get_frame(0)->get_y_size() * fabs(_anims[0]->get_ur(0)[1] - _anims[0]->get_ll(0)[1]);
@ -601,7 +600,7 @@ render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) {
for (i = 0; i < anim_count; ++i) {
for (j = 0; j < _anim_size[i]; ++j) {
// Set the particle per frame counts to 0.
memset(_ttl_count[i],NULL,_anim_size[i]*sizeof(int));
memset(_ttl_count[i], 0, _anim_size[i]*sizeof(int));
_sprite_writer[i][j].vertex = GeomVertexWriter(_vdata[i][j], InternalName::get_vertex());
_sprite_writer[i][j].color = GeomVertexWriter(_vdata[i][j], InternalName::get_color());

View File

@ -31,6 +31,7 @@
firstOfPairCompare.I firstOfPairCompare.h \
firstOfPairLess.I firstOfPairLess.h \
globalPointerRegistry.I globalPointerRegistry.h \
hashFilename.I hashFilename.h \
indirectCompareNames.I indirectCompareNames.h \
indirectCompareSort.I indirectCompareSort.h \
indirectCompareTo.I indirectCompareTo.h \
@ -70,7 +71,9 @@
datagramInputFile.cxx datagramOutputFile.cxx \
factoryBase.cxx \
factoryParam.cxx factoryParams.cxx \
globalPointerRegistry.cxx ioPtaDatagramFloat.cxx \
globalPointerRegistry.cxx \
hashFilename.cxx \
ioPtaDatagramFloat.cxx \
ioPtaDatagramInt.cxx ioPtaDatagramShort.cxx \
keyboardButton.cxx lineStream.cxx lineStreamBuf.cxx \
load_prc_file.cxx \
@ -113,6 +116,7 @@
firstOfPairCompare.I firstOfPairCompare.h \
firstOfPairLess.I firstOfPairLess.h \
globalPointerRegistry.I globalPointerRegistry.h \
hashFilename.I hashFilename.h \
indirectCompareNames.I indirectCompareNames.h \
indirectCompareSort.I indirectCompareSort.h \
indirectCompareTo.I indirectCompareTo.h \

View File

@ -0,0 +1,100 @@
// Filename: hashFilename.I
// Created by: drose (02Aug05)
//
////////////////////////////////////////////////////////////////////
//
// 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: HashFilename::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE HashFilename::
HashFilename(const string &filename_pattern) :
Filename(filename_pattern)
{
locate_hash();
}
////////////////////////////////////////////////////////////////////
// Function: HashFilename::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE HashFilename::
HashFilename(const HashFilename &copy) :
Filename(copy),
_hash_start(copy._hash_start),
_hash_end(copy._hash_end)
{
}
////////////////////////////////////////////////////////////////////
// Function: HashFilename::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void HashFilename::
operator = (const HashFilename &copy) {
Filename::operator = (copy);
_hash_start = copy._hash_start;
_hash_end = copy._hash_end;
}
////////////////////////////////////////////////////////////////////
// Function: HashFilename::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void HashFilename::
operator = (const Filename &copy) {
Filename::operator = (copy);
locate_hash();
}
////////////////////////////////////////////////////////////////////
// Function: HashFilename::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE HashFilename::
~HashFilename() {
}
////////////////////////////////////////////////////////////////////
// Function: HashFilename::has_hash
// Access: Published
// Description: Returns true if the filename pattern did include a
// sequence of hash marks, false otherwise. If this is
// true, then get_filename_index() will return a
// different filename each time.
////////////////////////////////////////////////////////////////////
INLINE bool HashFilename::
has_hash() const {
return (_hash_start != _hash_end);
}
////////////////////////////////////////////////////////////////////
// Function: HashFilename::get_hash_to_end
// Access: Published
// Description: Returns the part of the filename beginning at the
// hash sequence (if any), and continuing to the end of
// the filename.
////////////////////////////////////////////////////////////////////
INLINE string HashFilename::
get_hash_to_end() const {
return _filename.substr(_hash_start);
}

View File

@ -0,0 +1,80 @@
// Filename: hashFilename.cxx
// Created by: drose (02Aug05)
//
////////////////////////////////////////////////////////////////////
//
// 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 "hashFilename.h"
////////////////////////////////////////////////////////////////////
// Function: HashFilename::get_filename_index
// Access: Published
// Description: Returns a Filename, derived from the HashFilename,
// with the sequence of hash marks (if any) replaced by
// the indicated index number. If the HashFilename does
// not contain a sequence of hash marks, this quietly
// returns the original filename.
////////////////////////////////////////////////////////////////////
Filename HashFilename::
get_filename_index(int index) const {
Filename file(*this);
if (_hash_end != _hash_start) {
ostringstream strm;
strm << _filename.substr(0, _hash_start)
<< setw(_hash_end - _hash_start) << setfill('0') << index
<< _filename.substr(_hash_end);
file.set_fullpath(strm.str());
}
return file;
}
////////////////////////////////////////////////////////////////////
// Function: HashFilename::set_hash_to_end
// Access: Published
// Description: Replaces the part of the filename from the beginning
// of the has sequence to the end of the filename.
////////////////////////////////////////////////////////////////////
void HashFilename::
set_hash_to_end(const string &s) {
_filename.replace(_hash_start, string::npos, s);
locate_basename();
locate_extension();
locate_hash();
}
////////////////////////////////////////////////////////////////////
// Function: HashFilename::locate_hash
// Access: Private
// Description: Identifies the part of the filename that contains the
// sequence of hash marks, if any.
////////////////////////////////////////////////////////////////////
void HashFilename::
locate_hash() {
_hash_end = _filename.rfind('#');
if (_hash_end == string::npos) {
_hash_end = string::npos;
_hash_start = string::npos;
} else {
_hash_start = _hash_end;
++_hash_end;
while (_hash_start > 0 && _filename[_hash_start - 1] == '#') {
--_hash_start;
}
}
}

View File

@ -0,0 +1,60 @@
// Filename: hashFilename.h
// Created by: drose (02Aug05)
//
////////////////////////////////////////////////////////////////////
//
// 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 HASHFILENAME_H
#define HASHFILENAME_H
#include "pandabase.h"
#include "filename.h"
////////////////////////////////////////////////////////////////////
// Class : HashFilename
// Description : This is a specialization on Filename that is intended
// to be used to record a filename pattern for reading a
// numeric sequence of filenames in a directory; for
// instance, as used by TexturePool::load_cube_map().
//
// The Filename may include a string of one or more hash
// marks ('#') in the basename or extension part. These
// will be filled in with digits when
// get_filename_index() is called.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA HashFilename : public Filename {
PUBLISHED:
INLINE HashFilename(const string &filename_pattern = string());
INLINE HashFilename(const HashFilename &copy);
INLINE void operator = (const HashFilename &copy);
INLINE void operator = (const Filename &copy);
INLINE ~HashFilename();
INLINE bool has_hash() const;
Filename get_filename_index(int index) const;
INLINE string get_hash_to_end() const;
void set_hash_to_end(const string &s);
private:
void locate_hash();
size_t _hash_start;
size_t _hash_end;
};
#include "hashFilename.I"
#endif

View File

@ -17,6 +17,7 @@
#include "factoryParam.cxx"
#include "factoryParams.cxx"
#include "globalPointerRegistry.cxx"
#include "hashFilename.cxx"
#include "ioPtaDatagramFloat.cxx"
#include "ioPtaDatagramInt.cxx"
#include "ioPtaDatagramShort.cxx"